SitePoint Sponsor

User Tag List

Results 1 to 8 of 8
  1. #1
    SitePoint Zealot
    Join Date
    Nov 2008
    Posts
    172
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Help creating my first class

    I figure if I can get walked through this class I should be well on my way to creating my own.

    What I want to accomplish is a class to create a form, something very close to one I found on Google (http://php.xivix.net/php_7_Object_Oriented_Forms), only not as advanced. I just want the class to create a template for the form and a variable inside to display all text fields that are created (just setting it up for text fields will be fine).

    So the class would print from <form action="$var"> down to </form> including the submit button. The only problem is I can only figure out how to add a single text field. How do I add any number of fields?

  2. #2
    Use The Cloud
    Join Date
    Jan 2006
    Location
    Boise, ID
    Posts
    556
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It might be helpful if you posted what you have so far.

    Basically though, you will store your "fields" in an array, and then you can call a method to add another field to the array.

    PHP Code:
    <?php

    class Form
    {
        private 
    $_fields = array();

        public function 
    addField($string)
        {
            
    $this->_fields[] = $string;
            return 
    $this;
        }

        public function 
    getFields()
        {
            return 
    $this->_fields;
        }
    }

    $form = new Form();
    $form->addField('Foo')
         ->
    addField('Bar')
         ->
    addField('Baz');


    print_r($form->getFields());
    Output

    Code:
    Array
    (
        [0] => Foo
        [1] => Bar
        [2] => Baz
    )
    Edit:

    Here is a slightly more complex example using object composition.

    PHP Code:
    <?php

    $form 
    = new Form();
    $form->setAction('page2.php')
         ->
    addElement(new Form_Element_Text('foo'))
         ->
    addElement(new Form_Element_Text('bar'))
         ->
    addElement(new Form_Element_Submit('submit'));

    echo 
    $form->render();

    class 
    Form
    {
        protected 
    $_elements = array();
        protected 
    $_action   null;
        protected 
    $_method   'post';

        public function 
    addElement(Form_Element $element)
        {
            
    $this->_elements[] = $element;
            return 
    $this;
        }

        public function 
    setAction($action)
        {
            
    $this->_action $action;
            return 
    $this;
        }

        public function 
    setMethod($method)
        {
            
    $this->_method $method;
            return 
    $this;
        }

        public function 
    render()
        {
            
    $output '<form action="' $this->_action '" method="' $this->_method '">';
            foreach (
    $this->_elements as $element)
            {
                
    $output .= $element->getHtml();
            }
            
    $output .= '</form>';
            return 
    $output;
        }
    }

    abstract class 
    Form_Element
    {
        protected 
    $_name;

        public function 
    __construct($name)
        {
            
    $this->_name $name
        
    }

        abstract public function 
    getHtml();
    }

    class 
    Form_Element_Text extends Form_Element
    {
        public function 
    getHtml()
        {
            return 
    '<input type="text" name="' $this->_name '" />';
        }
    }

    class 
    Form_Element_Submit extends Form_Element
    {
        public function 
    getHtml()
        {
            return 
    '<input type="submit" name="' $this->_name '" />';
        }
    }
    Output:

    HTML Code:
    <form action="page2.php" method="post"><input type="text" name="foo" /><input type="text" name="bar" /><input type="submit" name="submit" /></form>
    It's very basic, but should help demonstrate how objects can work together.
    Last edited by bhanson; Dec 30, 2008 at 17:29.
    Brad Hanson, Web Applications & Scalability Specialist
    ► Is your website outgrowing its current hosting solution?
    ► PM me for a FREE scalability consult!
    ► USA Based: Available by Phone, Skype, AIM, and E-mail.

  3. #3
    Use The Cloud
    Join Date
    Jan 2006
    Location
    Boise, ID
    Posts
    556
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I had a spare hour so I extended it to include Validation support.

    Obviously it's still rough, but it should be functional and easily extendable.

    Library: (each of these classes should really be in a separate file)

    PHP Code:
    class Form
    {
        protected 
    $_elements = array();
        protected 
    $_action   null;
        protected 
    $_method   'post';

        public function 
    __construct()
        {
            
    $this->init();
        }

        public function 
    init()
        {}

        public function 
    addElement(Form_Element $element)
        {
            if (
    null === $element->getName()) {
                throw new 
    Exception('Element must have name');
            }

            
    $this->_elements[$element->getName()] = $element;

            return 
    $this;
        }

        public function 
    setAction($action)
        {
            
    $this->_action $action;
            return 
    $this;
        }

        public function 
    setMethod($method)
        {
            
    $this->_method $method;
            return 
    $this;
        }

        public function 
    render()
        {
            
    $output '<form action="' $this->_action '" method="' $this->_method '">';
            foreach (
    $this->_elements as $element) {
                
    $output .= '<pre>' print_r($element->getErrors(), true) . '</pre>';
                
    $output .= '<p>' $element->getHtml() . '</p>';
            }
            
    $output .= '</form>';
            return 
    $output;
        }

        public function 
    isValid(array $data)
        {
            
    $valid true;
            foreach (
    $this->getElements() as $key => $element) {
                if (isset(
    $data[$key])) {
                    
    $valid $element->isValid($data[$key]) && $valid;
                    
    $element->setValue($data[$key]);
                } else {
                    
    $valid $element->isValid(null) && $valid;
                }
            }
            return 
    $valid;
        }

        public function 
    getElements()
        {
            return 
    $this->_elements;
        }
    }

    abstract class 
    Form_Element
    {
        protected 
    $_name null;
        protected 
    $_validators = array();
        protected 
    $_value null;
        protected 
    $_errors = array();

        public function 
    __construct($name null)
        {
            
    $this->setName($name);
        }

        public function 
    setName($name)
        {
            
    $this->_name $name;
        }

        public function 
    getName()
        {
            return 
    $this->_name;
        }

        public function 
    setValue($string)
        {
            
    $this->_value $string;
        }

        public function 
    addValidator(Validate $validator)
        {
            
    $this->_validators[] = $validator;
        }

        public function 
    isValid($string)
        {
            
    $valid true;
            foreach (
    $this->getValidators() as $validator) {
                if (
    $validator->isValid($string)) {
                    
    $valid true && $valid;
                } else {
                    
    $valid false;
                    
    $this->_errors[] = $validator->getError();
                }
            }
            return 
    $valid;
        }

        public function 
    getErrors()
        {
            return 
    $this->_errors;
        }

        public function 
    getValidators()
        {
            return 
    $this->_validators;
        }

        abstract public function 
    getHtml();
    }

    class 
    Form_Element_Text extends Form_Element
    {
        public function 
    getHtml()
        {
            return 
    '<input type="text" name="' $this->_name '" value="' $this->_value '"/>';
        }
    }

    class 
    Form_Element_Submit extends Form_Element
    {
        public function 
    getHtml()
        {
            return 
    '<input type="submit" name="' $this->_name '" />';
        }
    }

    abstract class 
    Validate
    {
        protected 
    $_options = array();
        protected 
    $_error null;

        public function 
    __construct(array $options = array())
        {
            
    $this->setOptions($options);
        }

        public function 
    setOptions(array $options = array())
        {
            
    $this->_options $options;
        }

        public function 
    getOption($key)
        {
            return 
    $this->_options[$key];
        }

        protected function 
    _setError($text)
        {
            
    $this->_error $text;
        }

        public function 
    getError()
        {
            if (
    null === $this->_error) {
                return 
    false;
            } else {
                return 
    $this->_error;
            }
        }

        abstract public function 
    isValid($string); 
    }

    class 
    Validate_StringLength extends Validate
    {
        public function 
    isValid($string)
        {
            
    $length strlen($string);
            if ((
    $length >= $this->getOption('min')) && ($length <= $this->getOption('max'))) {
                return 
    true;
            }
            
    $this->_setError("\"$string\" length is not >= {$this->getOption('min')} && <= {$this->getOption('max')}");
            return 
    false;
        }
    }

    class 
    Validate_Numeric extends Validate
    {
        public function 
    isValid($string)
        {
            if (
    is_numeric($string)) {
                return 
    true;
            }
            
    $this->_setError("$string is not numeric");
            return 
    false;
        }

    Build your form:

    PHP Code:
    class ExampleForm extends Form
    {
        public function 
    init()
        {
            
    $this->setMethod('post');

            
    $name = new Form_Element_Text('name');
            
    $name->addValidator(
                new 
    Validate_StringLength(array(
                    
    'min' => 4,
                    
    'max' => 20,
                ))
            );

            
    $age = new Form_Element_Text('age');
            
    $age->addValidator(new Validate_Numeric());
            
    $age->addValidator(
                new 
    Validate_StringLength(array(
                    
    'min' => 1,
                    
    'max' => 2,
                ))
            );

            
    $submit = new Form_Element_Submit('submit');

            
    $this->addElement($name)
                 ->
    addElement($age)
                 ->
    addElement($submit);
        }

    Use it!

    PHP Code:
    $form = new ExampleForm();
    $form->setAction($_SERVER['PHP_SELF']);

    if (!empty(
    $_POST)) {
        if (
    $form->isValid($_POST)) {
            echo 
    "Valid form!\n";
        }
    }

    echo 
    $form->render(); 
    This displays the form, validates it, displays error messages, and auto repopulates data automatically for you.

    If anyone has questions feel free to ask.
    Last edited by bhanson; Dec 31, 2008 at 17:19. Reason: Fixed a mis-aligned foreach brace
    Brad Hanson, Web Applications & Scalability Specialist
    ► Is your website outgrowing its current hosting solution?
    ► PM me for a FREE scalability consult!
    ► USA Based: Available by Phone, Skype, AIM, and E-mail.

  4. #4
    Twitter: @AnthonySterling silver trophy AnthonySterling's Avatar
    Join Date
    Apr 2008
    Location
    North-East, UK.
    Posts
    6,111
    Mentioned
    3 Post(s)
    Tagged
    0 Thread(s)
    Brad,

    First off, great example! It's really good to see people post advanced examples for others...

    Secondly, could you please tell me why you coded Form_Element::isValid() the way you have, more specifically "$valid = true && $valid;" and not like the following...
    PHP Code:
    <?php
    public function isValid($string)
    {
        
    $valid true;
        foreach (
    $this->getValidators() as $validator) {
            if (!
    $validator->isValid($string)) {
                
    $valid false;
                
    $this->_errors[] = $validator->getError();
            }
        }
        return 
    $valid;
    }
    ?>
    Am I missing something?
    @AnthonySterling: I'm a PHP developer, a consultant for oopnorth.com and the organiser of @phpne, a PHP User Group covering the North-East of England.

  5. #5
    Use The Cloud
    Join Date
    Jan 2006
    Location
    Boise, ID
    Posts
    556
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by SilverBulletUK View Post
    Brad,

    First off, great example! It's really good to see people post advanced examples for others...

    Secondly, could you please tell me why you coded Form_Element::isValid() the way you have, more specifically "$valid = true && $valid;" and not like the following...
    PHP Code:
    <?php
    public function isValid($string)
    {
        
    $valid true;
        foreach (
    $this->getValidators() as $validator) {
            if (!
    $validator->isValid($string)) {
                
    $valid false;
                
    $this->_errors[] = $validator->getError();
            }
        }
        return 
    $valid;
    }
    ?>
    Am I missing something?
    I think I had some extra code there which needed a true case, but I guess I removed it and never refactored.

    There's some other things that should probably be changed as well, but I'll leave that as an exercise for anyone who may want to use the code. I don't actually build libraries anymore for common functionality in my projects, I reuse existing ones. Overall it saves me a lot of time.
    Brad Hanson, Web Applications & Scalability Specialist
    ► Is your website outgrowing its current hosting solution?
    ► PM me for a FREE scalability consult!
    ► USA Based: Available by Phone, Skype, AIM, and E-mail.

  6. #6
    Twitter: @AnthonySterling silver trophy AnthonySterling's Avatar
    Join Date
    Apr 2008
    Location
    North-East, UK.
    Posts
    6,111
    Mentioned
    3 Post(s)
    Tagged
    0 Thread(s)
    Thanks for the reply Brad, I figured as much.

    I just wanted to be sure I wasn't missing something, I hope you have a great new year and hope to see more of your code in 2009.

    Anthony.
    @AnthonySterling: I'm a PHP developer, a consultant for oopnorth.com and the organiser of @phpne, a PHP User Group covering the North-East of England.

  7. #7
    SitePoint Zealot
    Join Date
    Nov 2008
    Posts
    172
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hey thanks for all the input! And the same as SBUK said, have a great new year and hope to see you all in '09! Have a safe holiday!

  8. #8
    SitePoint Addict
    Join Date
    Aug 2007
    Location
    St. Louis, MO.
    Posts
    206
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by bhanson View Post
    I had a spare hour so I extended it to include Validation support.

    Obviously it's still rough, but it should be functional and easily extendable.

    Library: (each of these classes should really be in a separate file)

    [PHP]class Form
    {
    protected $_elements = array();
    protected $_action = null;
    protected $_method = 'post';

    public function __construct()
    {
    $this->init();
    }

    public function init()
    {}

    // ...
    Truly a great example! Wish I had seen this when I was trying to figure out OOP


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •