Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Task 2


Published on

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Task 2

  1. 1. Task Sheet 02 EdiPHP Students PHP Meetup November 11, 2009 This is the second task sheet of EdiPHP. If you’re stuck on the tasks, or find a mistake in them, or simply want to have a chat, feel free to contact us via our Facebook group or Twitter account. 1 Introduction In this task, we will extend our previous task - creating a lolcat, by creating a form, where user could specify lolcats’ name, image and caption and our script will generate it. So, our form will have these fields: 1. Name 2. Image URL 3. Caption 4. Submit Button Our fields should be validated this way: • Name must be at least 5 characters long, but no longer than 20 characters long, • Image URL must be a image url (end with .jpg), and not empty (at least 1 character long), • Caption must be at least 10 characters long, but no longer than 100 characters long. You can look here to see how it should work: 1
  2. 2. 2 Task 1 - Create an abstract class for form field Open file FormField.php. You should see this header of the class FormField there: abstract class FormField { private $_name; private $_value; private $_title; private $_minLength; private $_maxLength; public function __construct($name, $title = null, $value = null, $minLength = 0, $maxLength = -1); public function setName($name); public function getName(); public function setValue($value); public function getValue(); public function setTitle($title); public function getTitle(); public function setMinLength($minLength); public function getMinLength(); public function setMaxLength($maxLength); public function getMaxLength(); public abstract function __toString(); public function isValid(); } This is only representation of function interface, you will need to write the functions yourself. The private variables $_name, $_value, $_title, $_minLength, $_maxLength represent name, value, title, minimal and maximal length of input in a form field, respectively. 2
  3. 3. 2.1 Implement these functions: 1. Setters and getters: • setName($name) and getName() - that set and get $_name (respectively); • setValue($value) and getValue() - that set and get $_value; • setTitle($title) and getTitle() - that set and get $_title; • setMinLength($minLength) and getMinLength() - that set and get $_minLength; • setMaxLength($maxLength) and getMaxLength() - that set and get $_maxLength. Note that the behaviour of these functions is quite self-explanatory, so I won’t talk about it in detail in future tasks. 2. __construct($name, ..., $maxLength = -1) Note: I skip some parameters here, please check with the header above. This function sets $name, $title, ..., $maxLength (as specified in declara- tion) thus constructs the class. 3. isValid() This function should return true if ((length of value is greater than or equal the minimal length) and (less than or equal the maximal length or maximal length is less than zero)). Note: I added parentheses for clarity. Leave __toString() as it is. To check your implementation, you can run tests/FormFieldTest.php and check whether all of tests are OK. The test file is formatted to be run from console. 2.2 Example To implement setName($name) function, you will have to replace this line: public function setName($name); to your implementation of setName($name) function. So it would now look like: public function setName($name) { $this->_name = $name; return $this; } 3
  4. 4. 3 Task 2 - Implement a class, that represents a text input field We have already created a class that represents a form field. However, a form field can be a lot of different things: <input> field, <textarea> field, <select> field, etc. Which one is our FormField? Well it is, actually all of them. However, we will need to print it. So we’ll have to be a bit more specific about that. Open file TextInput.php. Note, that it requires file FormField.php, where our FormField class is defined. Here you see an interface for our new class TextInput which extends our FormField by making it an <input type="text"> field. Note that this class has only one function - __toString(). This means that it inherits every function from class FormField, except the __toString() function, which is defined there. 3.1 Implementing a function Implement a function __toString() function should return the following: <strong>!!title!!</strong>: <input type="text" name="!!name!!" value="!!value!!" /> Where !!title!!, !!name!!, !!value!! are title, name and value of the field. Important note: don’t forget to escape the value with htmlspecialchars(), using the quote style ENT_QUOTES, when outputting it. If you forget to do this, this may become a serious security issue. 3.2 Example $foobar = new TextInput(’foobar’, ’A bar of foo’, ’bar>foo’); echo $foobar; This code should return: <strong>A bar of foo</strong>: <input type="text" name="foobar" value="bar&gt;foo" /> Also, you can check your solution with the tests/TextInputTest.php. 4 Task 3 - Implement a class, that represents an image input field Now we have two classes: one that represents a form field, the other that represents an input field. These pretty much cover form fields for Name and Caption. As they both are input fields. On the other hand, despite the fact our image URL field, is an input field, it is not an object of our class TextInput, because we have to validate it differentely. Open ImageUrl.php. You’ll see that it requires TextInput.php. You will also see that our new class ImageUrl extends TextInput so it inherits everything from it (even the __toString() method we wrote in previous task). 4
  5. 5. 4.1 Implementing validation We’ll now implement validation for image URL. This is how the isValid() should work: 1. Call parent’s validator, and check whether everything is OK there. Parent’s validator can be called like this: parent::isValid() Your function should return false, if parent’s validator returns false. 2. Validate image extension to be .jpg. This means that the value of field must have this extension. Please consult PHP documentation on how to do that: kc8yds at gmail dot com’s note there could be helpful. 4.2 Example $a = new ImageUrl(’’, null, ’’); $b = new ImageUrl(’’, null, ’’); $c = new ImageUrl(’’, null, ’’); echo $a->isValid() ? "True" : "False"; echo PHP_EOL; echo $b->isValid() ? "True" : "False"; echo PHP_EOL; echo $c->isValid() ? "True" : "False"; echo PHP_EOL; Notes: The ternary operator: $a ? $b : $c returns $b if $a is true, or $c otherwise. PHP_EOL is a constant that represents newline symbol. The snippet above returns: True False False Note, that third one is false because we assume that only .jpg is a valid image. Feel free to extend this validation to accept other types, if you want. You can check your solution running an appropriate test in tests/ folder. 5 Task 4 - Implement a class for submit button This task is very similar to Task 2. Open file SubmitButton.php. You will see that our class SubmitButton is similar to TextInput class. Go ahead and implement __toString() method for SubmitButton class, which should return: 5
  6. 6. <input type="submit" value="!!title!!" /> Where !!title!! is the title (not the value) of the element. 6 Task 5 - Implement a class for form Now we will implement a class that wraps together everything we already implemented into a form object. Open file Form.php. You will see the declaration for form’s interface there. We have only one private variable there $_fields - an array that keeps all of our form fields in it. Go ahead and implement a getFields() method. You know how. 6.1 Implementation of addField() Now we will implement addField(FormField $field). This function takes an object of FormField family (an object that inherits FormField) as a formal parameter. Then it adds the object to $_field array so the object’s name becomes a key, and the object itself becomes a value in it. Such that the following code: $t = new TextInput(’test’); $f = new Form (); $f->addField($t); print_r($f->getFields()); Prints out: Array ( [test] => TextInput Object ( [_name:FormField:private] => test [_value:FormField:private] => [_title:FormField:private] => [_minLength:FormField:private] => 0 [_maxLength:FormField:private] => -1 ) ) 6
  7. 7. 6.2 Implementation of isValid() As we now implemented a way to add and return fields, we can start working with them. First, we’re going to implement a function that returns true if the form is valid. And the form is valid iff all of its fields are valid. So, write a function isValid() to check this property. 6.3 Implementation of populate() Now we need to find a way to populate our form with new data in a comfortable way. That is what our function populate($data) is going to do. The populate($data) function takes post data array ($_POST) as a formal parameter, and populates all of it’s fields with the data in it. $_POST data array consists of $name => $value pairs of input. Our populate($data) method should assign values in $data to our form fields for each of these pairs, where $name is the field name and $value is the field value. Example: $array = array(’foo’ => ’bar’); $fo = new Form(); $fo->addField(new TextInput(’foo’)) ->populate($array); $fields = $fo->getFields(); echo $fields[’foo’]->getValue(); Prints out ”bar”. 6.4 Implementation of getValues() It would also be handy to have a reverse function of populate: a function that returns an array of similar structure to the $_POST ($name => $value) from our field object data. Implement this function. Example: this line, appended to previous example: $fo->getValues() would return $array. 6.5 Implementation of toString() We’re almost done with this class. Now let’s just implement a __toString() method for the form. __toString() should return this: <form action="" method="post"> !!Field1 Str!! !!Field2 Str!! ... !!FieldN Str!! </form> 7
  8. 8. Where, obviously, !!FieldX Str!! is a string representation (output of __toString()) of the form fields in the form. Check your solution with appropriate test in tests/ 7 Connecting everything Hooray! We finished creating the objects for our form. Now let’s actually build them into one, working HTML page. Please note, that file LolCat.php contains my implementation of class LolCat, which was our previous task. We’re going to use it here. Feel free to change it to your implementation of the class, if you want. Open index.php. You’ll see some HTML already pre-written to you. Tell PHP, that you need files Form.php and LolCat.php in this page, by adding require "Form.php"; and require "LolCat.php" on top of all PHP code. Now create a Form object, call the variable $form. You should know how to do that, by looking at the examples in this document. Add the fields to the form. You can find those at the very beginning of the document. Think about which class should you use for each of them, and how to construct them. Note: Use null for empty value. Now add echo $form; somewhere between <body> and </body>. Don’t forget that this must be between PHP tags (<?php and ?>). Browse to your index.php via http://localhost/ (you will need to set up web server there first, see previous task for further details). And gaze at your created form. Though, you’re not able to submit it yet. That is why because we did not implement $_POST variable handling anywhere. To implement $_POST variable handling we first need to check whether we have a form submitted. This is as easy as this: if ($_POST) { //Form was submitted } else { //It was not submitted } If the form was not submitted, we print empty form (echo $form;). If the form was submitted we have to populate (function populate()) our form with the $_POST data and check whether this, populated data is valid. If the data was not valid, we print error and the populated form. If the data was valid, we create object $lolcat which is a new LolCat($name, $imageUrl, $caption), where the constructor values, are, of course, the values submitted by the user in the form. And print the lolcat, as well as the populated form. .. And we’re done! Implement this and play with the lolcats. 8
  9. 9. 8 Conclusion We spent a great effort on writing this form. There are quicker to write solutions for making forms like this. However, representing forms as objects is a easily reusable and manageable solution which is used by many frameworks and is considered a good style of writing your code. This means that it is easy to add another field to a form, or create a completely different form with the classes we have so far, if we need to, isn’t it? So, stay tuned for more PHP, EdiPHP P.S. This is officially the longest document with code snippets in it I have ever written. And it is all L TEXpowered! Awesome! :) A 9