SitePoint Sponsor

User Tag List

Page 1 of 2 12 LastLast
Results 1 to 25 of 49
  1. #1
    Theoretical Physics Student bronze trophy Jake Arkinstall's Avatar
    Join Date
    May 2006
    Location
    Lancaster University, UK
    Posts
    7,062
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)

    Thumbs up What would be a handy OOP class?

    Hi everyone.

    So, I want to know what you guys would want out of a good PHP OOP class. What annoys you about writing the code you write?
    What tasks do you find tedious?
    What repeditive code do you grind your teeth while writing?

    I'm asking because I'm thinking about writing a few handy classes in PHP, which I will use to make my PHPing easier. Once I have fully tested them (bugs, etc), I will upload the source-code to my server and allow everyone to get them, for free of course.

    I have been thinking about what annoys me, and this is what I have so far:
    • Writing Insert, Update and Delete files to modify data in a database (for example, adding a user, changing their details, deleting them). Especially writing and validating the forms.
    • Writing login scripts and customising pages for users
    • Securing admin-sides of websites
    • Form validation


    So, what would you want in a class?
    Jake Arkinstall
    "Sometimes you don't need to reinvent the wheel;
    Sometimes its enough to make that wheel more rounded"-Molona

  2. #2
    dooby dooby doo silver trophybronze trophy
    spikeZ's Avatar
    Join Date
    Aug 2004
    Location
    Manchester UK
    Posts
    13,807
    Mentioned
    158 Post(s)
    Tagged
    3 Thread(s)
    Evening Jake,

    Think of the most popular type of monotonous code type things we all write....

    1/ Image upload
    2/ Image resizing - thumbnail and on-the-fly
    3/ writing forms
    4/ MySQL connection and database interaction

    If I think of anything else I will post here
    Mike Swiffin - Community Team Advisor
    Only a woman can read between the lines of a one word answer.....

  3. #3
    Theoretical Physics Student bronze trophy Jake Arkinstall's Avatar
    Join Date
    May 2006
    Location
    Lancaster University, UK
    Posts
    7,062
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Thanks for the ideas - I'll get on to writing the classes.

    Anyone else?
    Jake Arkinstall
    "Sometimes you don't need to reinvent the wheel;
    Sometimes its enough to make that wheel more rounded"-Molona

  4. #4
    Worship the Krome kromey's Avatar
    Join Date
    Sep 2006
    Location
    Fairbanks, AK
    Posts
    1,621
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    A huge and whole-hearted "Second!" on the form-writing. Give me a way to create a form object and populate it with the input elements I need.

    I also second the image upload, but generalize it to generic file upload. A derived image upload class, however, would be very handy as well.
    PHP questions? RTFM
    MySQL questions? RTFM

  5. #5
    Theoretical Physics Student bronze trophy Jake Arkinstall's Avatar
    Join Date
    May 2006
    Location
    Lancaster University, UK
    Posts
    7,062
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    kl - good ideas.

    I've got a bit done on the form one, but it's literally a 5 min mock-up. I will make it much better when I get round to brainstorming it...

    formmaker.php
    PHP Code:
    <?
    class FormMaker{
        function 
    FormStart($action$method){
            echo 
    "\n<form action=\"".$action."\" method=\"".$method."\">";
        }

        function 
    SelectInput($query$name$display$value=null){
            
    $q mysql_query($query);
            
    $str "\n<select name=\"$name\">";
            while(
    $row mysql_fetch_array($q)){
                
    $str .= "\n<option value=\"".$row[$value]."\">".$row[$display]."</option>";
            }
            
    $str .= "\n</select>";
            echo 
    $str;
        }
        function 
    TextInput($name$value=null){
                echo 
    "\n<input type=\"text\" name=\"".$name."\" id=\"".$name."\" value=\"".$value."\" />";
        }

        function 
    Button($name$value=null){
                echo 
    "\n<button name=\"".$name."\" id=\"".$name."\">".$value."</button>";
        }

        function 
    TextArea($name$value=null){
                echo 
    "\n<textarea name=\"".$name."\" id=\"".$name."\">".$value."</textarea>";
        }

        function 
    CheckBox($name$value$checked=0){
            if(
    $checked == 1){
                
    $checked " checked";
            }else{
                
    $checked "";
            }
            echo 
    "\n<input type=\"checkbox\" name=\"".$name."\" id=\"".$name."\" value=\"".$value."\" ".$checked."/>";
        }

        function 
    submit($name$value){
            echo 
    "\n<input type=\"submit\" name=\"".$name."\" value=\"".$value."\">";
        }

        function 
    endform(){
            echo 
    "\n</form>";
        }
        function 
    newline(){
            echo 
    "\n<br>";
        }
    }
    ?>
    example:
    PHP Code:
    <?
    echo "<br />begin<br />";
    include(
    "formmaker.php");
    $QS = new FormMaker;
    $QS->FormStart($_SERVER['PHP_SELF'], "POST");
    $QS->newline();
    $QS->TextInput("text""text");
    $QS->newline();
    $QS->Button("button""button");
    $QS->newline();
    $QS->TextArea("textarea""textarea");
    $QS->newline();
    $QS->CheckBox("checkbox""checkbox"1);
    $QS->newline();
    $QS->CheckBox("checkbox2""checkbox2"0);
    $QS->newline();
    $QS->submit("submit""submit");
    $QS->newline();
    $QS->endform();
    echo 
    "<br />end<br />";
    ?>
    Jake Arkinstall
    "Sometimes you don't need to reinvent the wheel;
    Sometimes its enough to make that wheel more rounded"-Molona

  6. #6
    Theoretical Physics Student bronze trophy Jake Arkinstall's Avatar
    Join Date
    May 2006
    Location
    Lancaster University, UK
    Posts
    7,062
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    see it in action here
    Jake Arkinstall
    "Sometimes you don't need to reinvent the wheel;
    Sometimes its enough to make that wheel more rounded"-Molona

  7. #7
    Worship the Krome kromey's Avatar
    Join Date
    Sep 2006
    Location
    Fairbanks, AK
    Posts
    1,621
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    For this to be a class that I would use (so take it as you will - I'm certainly not your entire audience!) I'd want its usage to be more like thus:
    PHP Code:
    $form = new FormMaker($action$method);
    $form->input($type$name[, $value[, $attributes]]);
    $form->render(); 
    In essence, let me build the form as an object, but don't actually print it to the screen until I explicitly call for it. I don't want procedural code pretending to be an object, I want an object I can construct and pass around and hold onto until I'm ready to render the form.

    Again, take that as you will - I'm only 1 potential user, not your entire audience.
    PHP questions? RTFM
    MySQL questions? RTFM

  8. #8
    dooby dooby doo silver trophybronze trophy
    spikeZ's Avatar
    Join Date
    Aug 2004
    Location
    Manchester UK
    Posts
    13,807
    Mentioned
    158 Post(s)
    Tagged
    3 Thread(s)
    Good start there Jake and I second Kromey's suggestion
    Mike Swiffin - Community Team Advisor
    Only a woman can read between the lines of a one word answer.....

  9. #9
    Theoretical Physics Student bronze trophy Jake Arkinstall's Avatar
    Join Date
    May 2006
    Location
    Lancaster University, UK
    Posts
    7,062
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    In which case consider it changed
    Jake Arkinstall
    "Sometimes you don't need to reinvent the wheel;
    Sometimes its enough to make that wheel more rounded"-Molona

  10. #10
    Keep it simple, stupid! bokehman's Avatar
    Join Date
    Jul 2005
    Posts
    1,935
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by arkinstall View Post
    I've got a bit done on the form one
    That's just a bag.

  11. #11
    Theoretical Physics Student bronze trophy Jake Arkinstall's Avatar
    Join Date
    May 2006
    Location
    Lancaster University, UK
    Posts
    7,062
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Ok, so i've done quite a bit on it so far.

    The souce code for formmaker.php is:
    PHP Code:
    <? 
    class FormMaker
        var 
    $action$method$enctype$inputArray$labelArray$betweenfields
        function 
    __construct($action$method$enctype=null){ 
            if((
    strtolower($method) == "post") || (strtolower($method) == "get")){ 
                
    $this->method $method
            }else{ 
                
    $this->output_error("Class Instantiation""Incorrect form method. Please use one of the following options: <ul><li>Post</li><li>Get</li></ul>"); 
            } 
            if(isset(
    $action)){ 
                
    $this->action $action
            }else{ 
                
    $this->action $_SERVER['PHP_SELF']; 
            } 
            
    $this->enctype $enctype
            
    $this->betweenfields "<br />"
        } 

        function 
    between_fields($brk){ 
            
    $this->breakbetweenfields $brk
        } 
         
        function 
    output_error($funcname$error){ 
            echo 
    "<p>FormMaker Error:<br />Function: ".$funcname."<br />Error: ".$error."</p>"
        } 
         
        function 
    input($type$name$value=null$attributes=null){ 
            
    $this->inputArray[] = array("type" => $type"name" => $name"value" => $value"attributes" => $attributes); 
        } 
         
        function 
    label($for$text$attributes null){ 
            
    $this->labelArray[$for] = array("text" => $text"attributes" => $attributes); 
        } 
         
        function 
    select($name$options$attributes=null){ 
            
    $this->inputArray[] = array("type" => "select""name" => $name"options" => $options"attributes" => $attributes); 
        } 
         
        function 
    querySelect($result$fielddisplay$fieldvalue$name$attributes=null){ 
            
    $options = array(); 
            while(
    $row mysql_fetch_array($result)){ 
                
    $options[] = array($row[$fieldvalue], $row[$fielddisplay]); 
            } 
            
    $this->inputArray[] = array("type" => "select""name" => $name"options" => $options"attributes" => $attributes); 
        } 
         
        function 
    parse_input($key){ 
            
    $input $this->inputArray[$key]; 
            
    $name $input['name']; 
            
    $value = (isset($input['value']) ? $input['value'] : ""); 
            
    $attr ""
            if(isset(
    $input['attributes'])){ 
                foreach(
    $input['attributes'] as $attrname => $attrvalue){ 
                    
    $attr " ".$attrname."=\"".$attrvalue."\""
                } 
            } 
            if(isset(
    $this->labelArray[$name])){ 
                
    $label $this->labelArray[$name]; 
                
    $out "<label for=\"".$name."\"".$attr.">".$label['text']."</label>"
            }else{ 
                
    $out ""
            } 
            switch(
    $input['type']){ 
                case 
    "textarea"
                    
    $out .= "<textarea name=\"".$name."\"".$attr.">".$value."</textarea>"
                break; 
                case 
    "select"
                    
    $options ""
                    foreach(
    $input['options'] as $opt){ 
                        
    $options .= "\n<option value=\"".$opt[0]."\">".$opt[1]."</option>"
                    } 
                    
    $out .= "<select name=\"".$name."\"".$attr.">".$options."\n</select>"
                break; 
                default: 
                    
    $out .= "<input type=\"".$input['type']."\" name=\"".$name."\" value=\"".$value."\"".$attr." />"
                break; 
            } 
            if(isset(
    $this->betweenfields)){ 
                
    $out .= $this->betweenfields
            } 
            return 
    $out."\n"
        } 
         
        function 
    render(){ 
            
    $outputstring "<form action=\"".$this->action."\" method=\"".$this->method."\"".((!isset($this->enctype)) ? " enctype=\"".$this->enctype."\"" "").">\n"
            foreach(
    $this->inputArray as $key => $value){ 
                
    $outputstring .= $this->parse_input($key); 
            } 
            
    $outputstring .= "</form>\n"
            echo 
    $outputstring
        } 

    ?>
    and you can use it like this:
    PHP Code:
    <?
    require("../../db_connect.php");
    require(
    "formmaker.php");
    $q mysql_query("SELECT * FROM `User_Data`");
    $form = new FormMaker(null"POST");
    $form->input("text""input1");
    $form->select("select1", array(array("1""one"), array("2""two"), array("3""three")));
    $form->querySelect($q"Username""ID""select2");
    $form->input("submit""bob""send");
    $form->label("input1""Input 1: ");
    $form->label("select1""Select 1: ");
    $form->label("select2""Select 2: ");
    $form->render();
    ?>
    the querySelect() function is i handy function, it fills a select box with results from a query., this is how it's used:
    $result: mysql query resource.
    $fielddisplay: data field to display in the select box.
    $fieldvalue: data field to use as the select boxes ID.

    I'll be updating it regularly 'till it's finished.

    Feel free to rip it apart with complaints, compliments and comments. Oh, you can use it too, if you like
    Jake Arkinstall
    "Sometimes you don't need to reinvent the wheel;
    Sometimes its enough to make that wheel more rounded"-Molona

  12. #12
    SitePoint Wizard Hammer65's Avatar
    Join Date
    Nov 2004
    Location
    Lincoln Nebraska
    Posts
    1,161
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I've been trying to find time to do my own form class. When I get to it, I want to try to model it after how Xoops CMS does it, at least outwardly.

    It may be somewhat verbose, but flexible. Basically the idea is to do something somewhat similar to the DOM in that you have a form object, and then you have child elements that are also objects. You don't have to replicate the DOM and some of the classes would be pretty simple (textbox, textarea) but each element and the form could inherit from a class that provided methods for setting attributes.

    One thing I don't like about some CMS systems that use OOP to construct forms, is that often they allow the setting of only the tag attributes that the developer thought were important. I want to be able to set any attribute to anything I want.

    Other good classes for the list would be..

    Spam blocker/email validation (because very few email classes include this)

    HTML table class (not for layout just tabbed data)

    class to convert a database result to various XML formats. (I use this a lot with Flash and map API's)

    I use a class to do tables for HTML data virtually every day. No more while($row=mysql_fetch_whatever()) with tr and td's in strings, I just feed it some parameters and the data set as an array and let it go. it's a huge time saver. It actually does each row as an instance of a separate class. There is a render method that then tells all the child objects to render and puts their output into the table tags.

    I also have a utility class that has a lot of functions in it that normally would just be floating around.

  13. #13
    SitePoint Evangelist
    Join Date
    May 2007
    Location
    Montreal
    Posts
    408
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Can you upload files with this script?
    Also, does it save it in the db or its an email form?

  14. #14
    Theoretical Physics Student bronze trophy Jake Arkinstall's Avatar
    Join Date
    May 2006
    Location
    Lancaster University, UK
    Posts
    7,062
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    no, it doesn't go that far. It isn't a form handling script, a form creation script.

    However, i'll upgrade it to handle aswell.

    Thanks for the idea.
    Jake Arkinstall
    "Sometimes you don't need to reinvent the wheel;
    Sometimes its enough to make that wheel more rounded"-Molona

  15. #15
    Worship the Krome kromey's Avatar
    Join Date
    Sep 2006
    Location
    Fairbanks, AK
    Posts
    1,621
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Handling may be a little (a lot?) tricky, since you'd have to cover so many different possibilities. I'd say that at most you take the submitted data and turn it into an object which can then be processed by the site developer as he/she sees fit, although even that may be more work than it is worth since you can always just go straight to the source (i.e. $_POST/$_GET and $_FILES).

    Edit:


    Forgot to say that this new incarnation is a huge step in the right direction. Don't get too caught up in specifics, though - make it general-purpose and keep it that way. Most developers will adopt the use of a class that fits their style, and will skip over those that force them to fit their style to the class.
    PHP questions? RTFM
    MySQL questions? RTFM

  16. #16
    . shoooo... silver trophy logic_earth's Avatar
    Join Date
    Oct 2005
    Location
    CA
    Posts
    9,013
    Mentioned
    8 Post(s)
    Tagged
    0 Thread(s)
    I could not help be mess with this class, I haven't finished modifying it yet but Inputs are done >.< Brought it a bit more into PHP 5.

    FormMaker
    PHP Code:
    <?php

    function __autoload ($class) {
        
    $class str_replace('_''/'$class);
        require_once 
    dirname(__FILE__ ) . '/' $class '.php';
    }

    require_once 
    'FormMaker/Input.php';

    class 
    FormMaker {

        const 
    METHOD_GET  'get'# Default
        
    const METHOD_POST 'post';

        const 
    ENCTYPE_APPLICATION 'application/x-www-form-urlencoded'# Default (W3C)
        
    const ENCTYPE_MULTIPART   'multipart/form-data';

        protected 
    $action;
        protected 
    $method;
        protected 
    $enctype;

        protected 
    $labels;
        protected 
    $inputs;

    #-------------------------------------------------------------------------------

        
    function __construct ($action$method self::METHOD_GET$enctype null) {

            
    $this->setAction($action);
            
    $this->setMethod($method);
            
    $this->setEnctype($enctype);

        }

    #-------------------------------------------------------------------------------

        
    public function setAction ($action) {

            
    $action trim($action);
            if (empty(
    $action)) {
                throw new 
    FormMaker_Exception('An empty Action was supplied.');
                return;
            }

            if (
    function_exists('filter_var')) {
                
    // Doesn't need to be a URL...mistake...
                /*$test = filter_var($action, FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED | FILTER_FLAG_HOST_REQUIRED);
                if ($test === false) {
                    throw new FormMaker_Exception('An invalid action URL was passed');
                    return;
                }*/

                
    $action filter_var($testFILTER_SANITIZE_URL);
            }

            
    $this->action $action;
            return 
    $this;

        }

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

    #-------------------------------------------------------------------------------

        
    public function setMethod ($method self::METHOD_GET) {

            
    $method strtolower(trim($method));

            if (
    $method == self::METHOD_GET || $method == self::METHOD_POST) {
                
    $this->method $method;
                return 
    $this;
            }

            throw new 
    FormMaker_Exception('Invalid method was passed. Allowed types: GET and POST');
            return;

        }

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

    #-------------------------------------------------------------------------------

        
    public function setEnctype ($enctype null) {

            
    $enctype trim($enctype);
            if (empty(
    $enctype)) {
                
    $this->enctype self::ENCTYPE_APPLICATION;
                return 
    $this;
            }

            
    $enctype strtolower($enctype);
            if (
    $enctype == self::ENCTYPE_APPLICATION || $enctype == self::ENCTYPE_MULTIPART) {
                
    $this->enctype $enctype;
                return 
    $this;
            }

            throw new 
    FormMaker_Exception('Invalid enctype passed. Allowed enctype: '
                
    self::ENCTYPE_APPLICATION ' and ' self::ENCTYPE_MULTIPART);
            return;

        }

        public function 
    getEnctype () {
            return 
    $this->enctype;
        }

    #-------------------------------------------------------------------------------

        
    public function addInput ($type null$name null$value null$attr null) {

            if (
    is_null($type)) {
                
    $type FormMaker_Input::TYPE_TEXT;
            }

            
    $r = new FormMaker_Input($type$name$value$attr);
            
    $this->inputs[$r->getName()] = $r;

            return 
    $r;

        }

    #-------------------------------------------------------------------------------

        
    public function __toString () {

            
    $format '<form action="%s" method="%s" enctype="%s">%s</form>';

            
    $inputs '';
            if (!empty(
    $this->inputs)) {
                foreach (
    $this->inputs as $input) {
                    
    $inputs .= (string)$input;
                }
            }

            return 
    sprintf($format$this->action$this->method$this->enctype$inputs);

        }

        public function 
    render () {
            return 
    $this->__toString();
        }

    }
    FormMaker_Inputs
    PHP Code:
    <?php

    class FormMaker_Input {

        
    // Types as defined by the W3C
        
    const TYPE_BUTTON   =  1;
        const 
    TYPE_CHECKBOX =  2;
        const 
    TYPE_FILE     =  3;
        const 
    TYPE_HIDDEN   =  4;
        const 
    TYPE_IMAGE    =  5;
        const 
    TYPE_PASSWORD =  6;
        const 
    TYPE_RADIO    =  7;
        const 
    TYPE_RESET    =  8;
        const 
    TPYE_SUBMIT   =  9;
        const 
    TYPE_TEXT     10;

        private 
    $_types = array(
            
    'button'   => self::TYPE_BUTTON,
            
    'checkbox' => self::TYPE_CHECKBOX,
            
    'file'     => self::TYPE_FILE,
            
    'hidden'   => self::TYPE_HIDDEN,
            
    'image'    => self::TYPE_IMAGE,
            
    'password' => self::TYPE_PASSWORD,
            
    'radio'    => self::TYPE_RADIO,
            
    'reset'    => self::TYPE_RESET,
            
    'submit'   => self::TPYE_SUBMIT,
            
    'text'     => self::TYPE_TEXT
        
    );

        protected 
    $type;
        protected 
    $name;
        protected 
    $value;
        protected 
    $attributes;

    #-------------------------------------------------------------------------------

        
    public function __construct ($type self::TYPE_TEXT$name null$value null$attr null) {

            
    // I would assume a text box is the default for an input so set that.
            // Next if a name is empty create a random name.
            
    $this->setType($type);
            
    $this->setName($name);
            
    $this->setValue($value);
            
    $this->setAttributes($attr);

        }

    #-------------------------------------------------------------------------------

        
    private function _typeToName ($type) {

            
    $type  = (int)$type;
            
    $types array_flip($this->_types);

            if (isset(
    $types[$type])) {
                return 
    $types[$type];
            }

            return 
    false;

        }

        private function 
    _typeToInteger ($type) {

            
    $type  strtolower(trim($type));
            
    $types $this->_types;

            if (isset(
    $types[$type])) {
                return 
    $types[$type];
            }

            return 
    false;

        }

        public function 
    setType ($type self::TYPE_TEXT) {

            if (
    in_array((int)$type$this->_types)) {
                
    $this->type $type;
                return 
    $this;
            }

            
    $tmp $this->_typeToInteger($type);
            if (
    $tmp !== false) {
                
    $this->type $tmp;
                return 
    $this;
            }

            throw new 
    FormMaker_Exception('An invalid input type was passed. Allowed types: '
                
    join(', 'array_keys($this->_types)));
            return;

        }

        public function 
    getType () {
            return 
    $this->_typeToName($this->type);
        }

    #-------------------------------------------------------------------------------

        
    public function setName ($name null) {

            if (empty(
    $name)) {
                
    $this->name str_shuffle(base64_encode(mt_rand(100000999999)));
                return 
    $this;
            }

            
    // Sanity Check
            
    if (preg_match('/^[^\w\[\]\-.]+$/i'$name)) {
                throw new 
    FormMaker_Exception('An invalid name was passed. Allowed characters: a-z 0-9 _ - . [ ]');
                return;
            }

            
    $this->name $name;
            return 
    $this;

        }

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

    #-------------------------------------------------------------------------------

        
    public function setValue ($value null) {

            if (empty(
    $value)) {
                
    $this->value null;
                return 
    $this;
            }

            
    // Need to URL encode the value for transport.
            
    $this->value rawurlencode($value);
            return 
    $this;

        }

        public function 
    getValue () {
            return 
    $this->value;
        }

    #-------------------------------------------------------------------------------

        
    public function setAttributes () {

            if (
    func_num_args() == || is_null(func_get_arg(0))) {
                return 
    $this;
            }

            if (
    func_num_args() == && is_array(func_get_arg(0))) {

                
    $arg func_get_arg(0);
                foreach (
    $arg as $key => $value) {
                    
    $key strtolower($key);
                    
    $this->attributes[$key] =  htmlspecialchars($valueENT_COMPAT'UTF-8');
                }

                return 
    $this;

            }

            
    // Here a strided list is used.
            
    $args func_get_args();
            
    $args array_chunk($args2);

            foreach (
    $args as $arg) {
                list(
    $key$value) = $arg;
                
    $key strtolower($key);
                
    $this->attributes[$key] =  htmlspecialchars($valueENT_COMPAT'UTF-8');
            }

            return 
    $this;

        }

        public function 
    getAttributes () {
            return 
    $this->attributes;
        }

        
    // Single Attributes
        
    public function setAttribute ($name$value) {
            return 
    $this->setAttributes($name$value);
        }

        public function 
    getAttribute ($name) {

            
    $name strtolower($name);
            if (isset(
    $this->attributes[$name])) {
                return 
    $this->attributes[$name];
            }

            return 
    false;

        }

    #-------------------------------------------------------------------------------

        
    public function __toString () {

            
    $format '<input type="%1$s" name="%2$s" id="%2$s" value="%3$s"%4$s>';

            
    $attr '';
            if (!empty(
    $this->attributes)) {
                foreach (
    $this->attributes as $key => $value) {
                    
    $attr .= sprintf(' %s="%s"'$key$value);
                }
            }

            return 
    sprintf($format$this->_typeToName($this->type), $this->name$this->value$attr);

        }

        public function 
    build () {
            return 
    $this->__toString();
        }


    }
    Test
    PHP Code:
    <?php

    require 'FormMaker.php';

    try {

        
    $form = new FormMaker('http://sandbox.loc/');

            
    $user $form->addInput('text')
                         ->
    setName('username')
                         ->
    setValue('something')
                         ->
    setAttribute('class''something');

            
    $pass $form->addInput('password''password');

        
    var_dump((string)$form); # same thing as $form->__toString()

    } catch (FormMaker_Exception $e) {
        
    var_dump($e);
    } catch (
    Exception $e) {
        
    var_dump($e);
    }
    Logic without the fatal effects.
    All code snippets are licensed under WTFPL.


  17. #17
    Theoretical Physics Student bronze trophy Jake Arkinstall's Avatar
    Join Date
    May 2006
    Location
    Lancaster University, UK
    Posts
    7,062
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    V. Nice work there Logic - way beyond what I know about OOP.

    The only problems I see there is that you wouldn't be able to do other form inputs, such as <textarea> and <select>.

    Hopefully the new XHTML specification may depricate <textarea> and <select>, replacing them with <input type="textarea" /> and <input type="select" />....
    Jake Arkinstall
    "Sometimes you don't need to reinvent the wheel;
    Sometimes its enough to make that wheel more rounded"-Molona

  18. #18
    . shoooo... silver trophy logic_earth's Avatar
    Join Date
    Oct 2005
    Location
    CA
    Posts
    9,013
    Mentioned
    8 Post(s)
    Tagged
    0 Thread(s)
    Oh well I haven't gotten to those yet ^^;; Keeping it simple for now as i work on labels which is done except for error handling.

    One can chose how the label element is position either in front, behind or wraped
    Logic without the fatal effects.
    All code snippets are licensed under WTFPL.


  19. #19
    SitePoint Evangelist catweasel's Avatar
    Join Date
    Apr 2007
    Location
    Goldfields, VIC, Australia
    Posts
    518
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    All this is very similar to a form making class I wrote some time ago. This one takes the associative array from a 'show full columns' database query and builds appropriate form elements for each database column. An optional second associative array of values can be passed if you want the form fields to be filled out with values.. usually from $_POST or 'select * from tablename' query.

    I call it in my script like this -
    PHP Code:
    <html>
    <body>
    <?php
    require_once "class.AutoForm.php";
    require_once 
    "class.DBInterface.php";
    require_once 
    "class.DB.php";

    $db DB::getInstance();
    $columns $db->showColumns('tableName');
    $result $db->execute("select * from tableName where i=?",3);
    $row $result[0];
    $form = new AutoForm($columns,$row);
    printf("<form method='post' action='somescript.php'>
            %s
            <div class='formElem'>
            <input type='submit' value='Go'>
            </div>
            </form>"
    ,$form->buildForm());

    ?>
    </body>
    </html>
    If you want the class to ignore some fields you can use $form->addIgnore('fieldname');

    If you want the class to treat some fields differently you can extend the class and use the buildSpecial function.

    And the actual form maker script - (apologies for the length)
    PHP Code:
    <?php
    /**
    \author Jonathon Wallen info@cub3d.com
    \brief A class designed to generate HTML forms on the fly from a database table.

    \par Usage.
        Supposing we've inherited AutoForm in a new class called SomeForm.
        We can initiate the form object in one of two ways ...
        \code
        
        $form = new AutoForm($columns); // where columns is the associative array returned by a show full columns query.
        
        // OR
        
        $form = new AutoForm($columns,$values); // where values is the associative array of values the form is to be filled with. 
                                                // usually from POST or select * from tableName.
        
        // then..
        printf("
        <form action='someAction' method='post'>
        %s
        <div class='formElem'>
        <input type='submit' value='submit form'>
        </div>

        </form>",$form->buildForm());
        
        // Note you still must provide the <form></form> tags, and the <input type='submit'> tag.
        \endcode
    */
    class AutoForm {
        protected 
    $_properties = array();    //!< Array holding arrays of column properties for each column.
        
    protected $_baseElements = array();    //!< Array holding the default form elements for each column type.
        
    protected $_ignore = array();        //!< Array holding the columns to be ignored.
        
    protected $_special = array();        //!< Array holding the columns to be treated differently to the default.
        
    protected $filled;                    //!< 1 or 0: Denotes whether this form is to be filled out or provided blank.
        
    protected $_HTMLFormElems;            //!< Array of html form elements.
        
        /**
        
        \param Array columns - The associative array returned by show full columns query on a database table.
        \param Array values (optional) - The associative array of values for each form field. Either from a select * from tableName or from $_REQUEST array.
        */
        
    public function __construct(array $columns, array $values null) {
            
    $this->init();
            
            foreach (
    $columns as $row) {
                
    // printf("<pre>%s</pre>",print_r($row,1));
                
    $key $row[0];
                
    $this->_properties[$key] = array();
                
    $this->_properties[$key]['field'] = $row[0];
                
    $this->_properties[$key]['type'] = substr ($row[1],0,strcspn $row[1], "("));
                
    $this->_properties[$key]['default'] = $row[5];
                
    $this->_properties[$key]['extra'] = $row[6];
                
    $this->_properties[$key]['comment'] = $row[8];
                switch (
    $this->_properties[$key]['type']) {
                    case 
    'enum' $this->_properties[$key]['values'] = str_replace ("'","",trim(strstr($row[1], '('),'()'));
                    break;
                    case 
    'set' $this->_properties[$key]['values'] = str_replace ("'","",trim(strstr($row[1], '('),'()'));
                    break;
                    case 
    'date' $this->_properties[$key]['values'] = 'CURRENT_DATE';
                    break;
                    case 
    'datetime' $this->_properties[$key]['values'] = 'NOW()';
                    break;
                    case 
    'timestamp' $this->_properties[$key]['values'] = 'NOW()';
                    break;
                    default : {
                        
    $this->_properties[$key]['values'] = '';
                    }
                }
            }
            
    // printf("<hr><pre>%s</pre>",print_r($this->_properties,1));
            
            
    if (is_array($values)) {
                
    $this->filled 1;
                
    $this->fillValues($values);
            } else {
                
    $this->filled 0;
            }        
        }
        
        
    /**
        fillValues is used by the construct function to assign any values it may find in the table column or array arguments.
        */
        
    protected function fillValues($valuesArray) {
            foreach (
    $this->_properties as $row) {
                if (empty (
    $row['values'])) $this->_properties[$row['field']]['values'] = htmlentities(str_replace('<br />','',stripslashes ($valuesArray[$row['field']])), ENT_QUOTES);
                
                else if (
    $row['type'] == 'set' || $row['type'] == 'enum') {
                    if (!
    is_array ($valuesArray[$row['field']])) $valuesArray[$row['field']] = explode(',',$valuesArray[$row['field']]);
                    foreach (
    $valuesArray[$row['field']] as $candidate) {
                        
    $this->_properties[$row['field']]['values'] = str_replace($candidate$candidate."=ON"$this->_properties[$row['field']]['values']);
                    }
                }
            }
        }
        
        
    /**
        init is called by construct to set some basic rules.
        */
        
    protected function init() {
            
    $this->_baseElements['tinyint'] = "text";
            
    $this->_baseElements['smallint'] = "text";
            
    $this->_baseElements['mediumint'] = "text";
            
    $this->_baseElements['int'] = "text";
            
    $this->_baseElements['bigint'] = "text";
            
    $this->_baseElements['integer'] = "text";
            
    $this->_baseElements['real'] = "text";
            
    $this->_baseElements['double'] = "text";
            
    $this->_baseElements['decimal'] = "text";
            
    $this->_baseElements['float'] = "text";
            
    $this->_baseElements['numeric'] = "text";
            
    $this->_baseElements['char'] = "text";
            
    $this->_baseElements['varchar'] = "text";
            
    $this->_baseElements['date'] = "hidden";
            
    $this->_baseElements['time'] = "hidden";
            
    $this->_baseElements['datetime'] = "hidden";
            
    $this->_baseElements['timestamp'] = "hidden";
            
    $this->_baseElements['tinyblob'] = "text";
            
    $this->_baseElements['blob'] = "textarea";
            
    $this->_baseElements['mediumblob'] = "text";
            
    $this->_baseElements['longblob'] = "textarea";
            
    $this->_baseElements['tinytext'] = "text";
            
    $this->_baseElements['text'] = "textarea";
            
    $this->_baseElements['mediumtext'] = "text";
            
    $this->_baseElements['longtext'] = "textarea";
            
    $this->_baseElements['enum'] = "select";
            
    $this->_baseElements['set'] = "checkbox";

        }
        
        public function 
    filled() { return $this->filled; }
        
        public function 
    addIgnore($item) {
            
    $this->_ignore[] = $item;
        }
        
        public function 
    getElems() {
            return 
    $this->_HTMLFormElems;
        }
        
        
    /**
        buildForm cycles through the table columns building each element unless the column is in the _ignore or _special arrays.
        */
        
    public function buildForm() {
            
    $form '';
            
    $hidden '';
            foreach (
    $this->_properties as $row) {
                if (!
    in_array($row['field'],$this->_ignore)) {
                    if (
    in_array($row['field'],$this->_special))
                        
    $elem $this->buildSpecial($row);
                    elseif (
    $row['extra'] == 'auto_increment')
                        
    $elem $this->buildHidden($row);
                    else
                        
    $elem $this->buildElement($row);
                    
                    
    $this->_HTMLFormElems[$row['field']] = $elem;
                    
                    
    $row['comment'] != '' $comment $row['comment']."<br>"$comment '';
                    
                    if (
    $this->_baseElements[$row['type']] == 'hidden' || $row['extra'] == 'auto_increment')
                        
    $form .= $elem;
                    else 
                        
    $form .= sprintf("<div class='formElem'>\n%s<br>\n%s\n%s</div>\n",ucwords (str_replace ("_"," ",$row['field'])),$comment,$elem);
                }
            }
            return 
    $form;
        }
        
        
    /**
        buildElement is used by buildForm to switch between form element types in accordance with the column type.
        */
        
    protected function buildElement($row) {
            
    $elem '';
            switch (
    $this->_baseElements[$row['type']]) {
                case 
    'textarea' $elem $this->buildTextArea($row);
                break;
                case 
    'hidden' $elem $this->buildHidden($row);
                break;
                case 
    'select' $elem $this->buildSelect($row);
                break;
                case 
    'checkbox' $elem $this->buildCheckBox($row);
                break;
                case 
    'radio' $elem $this->buildRadio($row);
                break;
                default : 
    $elem $this->buildText($row);
                break;
                        
            }
            return 
    $elem;
        }
        
        
    /**
        Returns a html input element of text type.
        */
        
    protected function buildText($row) {
            
    $elem sprintf("<input type='%s' name='%s' value='%s'>",$this->_baseElements[$row['type']],$row['field'],$row['values']);
            return 
    $elem;
        }
        
        
    /**
        Returns a html input element of radio type.
        */
        
    protected function buildRadio($row) {
            if (!
    $this->filled) $$row['default'] = ' checked';
            
    $vals explode (',',$row['values']);
            foreach (
    $vals as $value) {
                if (
    $pos strpos($value,"=ON")) {
                    
    $value substr($value,0,$pos);
                    $
    $value ' checked';
                }
                
    $elem .= sprintf("<input type='radio' name='%s' value='%s'%s>%s<br>\n",$row['field'],$value,$$value,$value);
            }
            return 
    $elem;
        }
        
        
    /**
        Returns a html form element of check box type.
        */
        
    protected function buildCheckBox($row) {
            
    $vals explode (',',$row['values']);
            if (!
    $this->filled) $$row['default'] = ' checked';
                    
            foreach (
    $vals as $value) {
                if (
    $this->filled) {
                    if (
    $pos strpos($value,"=ON")) {
                        
    $value substr ($value,0,$pos);
                        $
    $value ' checked';
                    }
                }
                
    $elem .= sprintf("<input type='checkbox' name='%s' value='%s'%s>%s<br>\n",$row['field']."[]",$value,$$value,$value);
            }
            return 
    $elem;
        }
        
        
    /**
        Returns a html form element of select type.
        */
        
    protected function buildSelect($row) {
            
    $elem "<select name=".$row['field'].">";
            
    $vals explode (',',$row['values']);
            if (!
    $this->filled) $$row['default'] = ' selected';
            
            foreach (
    $vals as $value) {
                if (
    $this->filled) {
                    if (
    $pos strpos($value,"=ON")) {
                        
    $value substr ($value,0,$pos);
                        $
    $value ' selected';
                    }
                }
                
    $elem .= sprintf("<option value='%s'%s>%s</option>\n",$value,$$value,$value);
            }
            
    $elem .= "</select>";
            return 
    $elem;
        }
        
        
    /**
        Returns a html form element of hidden type.
        */
        
    protected function buildHidden($row) {
            
    $elem sprintf("<input type='hidden' name='%s' value='%s'>",$row['field'],$row['values']);
            return 
    $elem;
        }
        
        
    /**
        Returns a html text area element.
        */
        
    protected function buildTextArea($row) {
            
    $elem sprintf("<textarea name='%s' cols='30' rows='6'>%s</textarea>",$row['field'],$row['values']);
            return 
    $elem;
        }
        
        
    /**
        buildSpecial should be overridden to build any columns requiring special treatment differing to its default element.
        */
        
    protected function buildSpecial($row) {}
        

    }

    ?>

  20. #20
    . shoooo... silver trophy logic_earth's Avatar
    Join Date
    Oct 2005
    Location
    CA
    Posts
    9,013
    Mentioned
    8 Post(s)
    Tagged
    0 Thread(s)
    Continue more work on it, things going well

    The structure looks something like this
    Code:
    FormMaker/
    |   FormMaker.php
    |   Test.php
    |   
    \---FormMaker
        |   Element.php
        |   Exception.php
        |   Label.php
        |   
        \---Element
                Input.php
                Textarea.php
    and the way to use it at the moment.
    PHP Code:
    <?php

    require 'FormMaker.php';

    try {

        
    $form = new FormMaker('http://sandbox.loc/');

            
    $user $form->addInput('text''username');
            
    $user->addLabel(null'wrap');

            
    $form->insertBreak();

            
    $pass $form->addInput('password''password');
            
    $pass->addLabel();

            
    $form->insertBreak("<br>\n"); # Custom breaks;

            
    $text $form->addTextarea('testtext''some sample data');
            
    $text->addLabel('Some Text Area''wrap');

        
    var_dump($form);
        print 
    $form# same thing as $form->__toString()

    } catch (FormMaker_Exception $e) {
        
    var_dump($e);
    } catch (
    Exception $e) {
        
    var_dump($e);
    }
    Logic without the fatal effects.
    All code snippets are licensed under WTFPL.


  21. #21
    . shoooo... silver trophy logic_earth's Avatar
    Join Date
    Oct 2005
    Location
    CA
    Posts
    9,013
    Mentioned
    8 Post(s)
    Tagged
    0 Thread(s)
    Well damn....I was stupid...reinstalled windows and forgot to move my working directory with all my work onto my external...and now I've lost the work i've done on this script T_T

    *sigh* I knew deleting my backups would have been a bad idea.
    Logic without the fatal effects.
    All code snippets are licensed under WTFPL.


  22. #22
    Theoretical Physics Student bronze trophy Jake Arkinstall's Avatar
    Join Date
    May 2006
    Location
    Lancaster University, UK
    Posts
    7,062
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Oh well. I usually find that after losing some work and having to redo it, the end result is better.

    Anyway, thanks for the good display of technique on post #16, I'll try to incorporate that style into the class i'll make for the mysql class.
    Jake Arkinstall
    "Sometimes you don't need to reinvent the wheel;
    Sometimes its enough to make that wheel more rounded"-Molona

  23. #23
    SitePoint Zealot
    Join Date
    Jun 2006
    Posts
    177
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I don't understand this... Can someone explain to me how these form makers are different from writing out a form? Both seem to require manually entering all arguments and types of input necessary. One is just written in a different form than the other.

  24. #24
    Theoretical Physics Student bronze trophy Jake Arkinstall's Avatar
    Join Date
    May 2006
    Location
    Lancaster University, UK
    Posts
    7,062
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    It makes writing forms alot easier. I don't know about you, but I hate writing HTML in the middle of PHP code. Not only that, but it allows you to just enter one or two parameters, and the class writes the default values into the form manually - saving you the bother.
    Jake Arkinstall
    "Sometimes you don't need to reinvent the wheel;
    Sometimes its enough to make that wheel more rounded"-Molona

  25. #25
    SitePoint Wizard Hammer65's Avatar
    Join Date
    Nov 2004
    Location
    Lincoln Nebraska
    Posts
    1,161
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Doing it with a class,

    Enables you to more easily return values to a form, for editing or when validation has indicated that there is a problem with the form data, that the user needs to correct.

    Allows you to put together forms from recorded preferences, such as settings made in a CMS. They can easily be authored and changed by a non-technical user, using some sort of admin application.

    The markup for the form is always the same. No mistakes or improper markup. Just one more area where, once the class has been fully debugged and developed, you never have to worry about coding mistakes again. You have very predictable output each time. If you build in accessibility, that is somehting you don't have to think about again, it's just there.

    The chalenge with a form done this way is flexible layout, but if you can somehow lick that problem, you have just saved yourself a lot of effort.

    you won't do every form like this, but if it has to do heavy interaction with a database or other server side code, or be configured and changed by someone else, it does indeed save time and trouble.


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
  •