class - PHP - best way to initialize an object with a large number of parameters and default values -


i'm designing class defines highly complex object ton (50+) of optional parameters, many of have defaults (eg: $type = 'foo'; $width = '300'; $interactive = false;). i'm trying determine best way set constructor , instance/class variables in order able to:

  • make easy use class
  • make easy auto-document class (ie: using phpdocumentor)
  • code elegantly

in light of above, don't want passing constructor ton of arguments. passing single hash contains initialization values, eg: $foo = new foo(array('type'=>'bar', 'width'=>300, 'interactive'=>false));

in terms of coding class, still feel rather have...

class foo {     private $_type = 'default_type';     private $_width = 100;     private $_interactive = true;      ... } 

...because believe facilitate documentation generation (you list of class' properties, lets api user know 'options' have work with), , "feels" right way it.

but run problem of mapping incoming parameters in constructor class variables, , without exploiting symbol table, "brute force" approach me defeats purpose (though i'm open other opinions). e.g.:

function __construct($args){     if(isset($args['type'])) $_type = $args['type']; // yuck! } 

i've considered creating single class variable associative array. initializing easy then, e.g.:

private $_instance_params = array(     'type' => 'default_type',     'width' => 100,     'interactive' => true );  function __construct($args){     foreach($args $key=>$value){         $_instance_params[$key] = $value;     } } 

but seems i'm not taking advantage of native features private class variables, , feels documentation generation not work approach.

thanks reading far; i'm asking lot here, i'm new php , looking idiomatic / elegant way of doing this. best practices?


addendum (details particular class)

it's quite class trying much, port of old perl library creating , processing forms. there's way of dividing configuration options take advantage of inheritance , polymorphism, may counter-productive.

by request, here partial listing of of parameters (perl code). should see these don't map sub-classes.

the class has getters , setters many of these properties user can over-ride them; objective of post (and original code nicely) provide compact way of instantiating these form objects required parameters set. makes readable code.

# form behaviour parameters         # --------------------------         $self->{id}; # id , name of <form> tag         $self->{name} = "webform"; # legacy - replaced {id}         $self->{user_id} = $global->{user_id}; # used make sure links have user id encoded in them. gets returned {'i'} user input parameter         $self->{no_form}; # if set, <form> tag omitted         $self->{readonly}; # if set, entire form read-only         $self->{autosave} = ''; # when set true, un-focusing field causes field data saved         $self->{scrubbed}; # if set "true" or non-null, places "changed" radio button on far right of row-per-record forms indicates record has been edited. used allow users edit multiple records @ same time , save results @ once. cool.         $self->{add_rowid}; # if set, each row in form have hidden "rowid" input field row_id of record (used scrubbable records). if 'scrubbed' parameter set, parameter automatically set. note work, select statement must pull out unique row id.          $self->{row_id_prefix} = "row_"; # each row gets unique id of form id="row_##" ## corresponds record's rowid. in case of multiple forms, if need identify specific row, can change "row_" prefix unique. default it's "row_"          $self->{validate_form}; # parses user_input , validates required fields , on form         $self->{target}; # adds target window form tag if specified         $self->{focus_on_field}; # if supplied, add <script> tag @ end of form set focus on named field once form loads.         $self->{on_submit}; # adds onsubmit event handler form tag if supplied         $self->{ctrl_s_button_name}; # if supplied name of savebutton, add onkeypress handler process ctrl-s way of saving form          # form paging parameters         # ----------------------         $self->{max_rows_per_page}; # when displaying complete form using printform() method, determines number of rows shown on screen @ time. if blank or undef, rows in query shown , no header/footer produced.         $self->{max_pages_in_nav} = 7; # when displaying navbar above , below list forms, determines how many page links shown. should odd number         $self->{current_offset}; # current page we're displaying         $self->{total_records}; # number of records returned query         $self->{hide_max_rows_selector} = ""; # hide <select> tag allowing users choose max_rows_per_page         $self->{force_selected_row} = ""; # if set, calls showpage() clear rowid hidden field on form, forcing first record displayed if none selected         $self->{paging_style} = "normal"; # options: "compact" 

we can, of course, allow ourselves drawn more lengthy debate around programming style. i'm hoping avoid it, sanity of involved! here (perl code, again) example of instantiating object pretty hefty set of parameters.

my $form = new valz::webform (             id                      => "dbform",             form_name               => "user_mailbox_recip_list_students",             user_input              => \%params,             user_id                 => $params{i},             no_form                 => "no_form",             selectable              => "checkbox",             selectable_row_prefix   => "student",             selected_row            => join (",", getrecipientidsbytype('student')),             this_page               => $params{c},             paging_style            => "compact",             hide_max_rows_selector  => 'true',             max_pages_in_nav        => 5         ); 

i can think of 2 ways of doing that. if want keep instance variables can iterate through array passed constructor , set instance variable dynamically:

    <?php      class foo {         private $_type = 'default_type';         private $_width = 100;         private $_interactive = true;          function __construct($args){             foreach($args $key => $val) {                 $name = '_' . $key;                 if(isset($this->{$name})) {                     $this->{$name} = $val;                 }             }         }     }      ?> 

when using array approach don't have abandon documentation. use @property annotations in class body:

<?php  /**  * @property string $type  * @property integer $width  * @property boolean $interactive  */ class foo {     private $_instance_params = array(         'type' => 'default_type',         'width' => 100,         'interactive' => true     );      function __construct($args){         $this->_instance_params = array_merge_recursive($this->_instance_params, $args);     }      public function __get($name)     {         return $this->_instance_params[$name];     }      public function __set($name, $value)     {         $this->_instance_params[$name] = $value;     } }  ?> 

that said, class 50 member variables either used configuration (which can split up) or doing , might want think refactoring it.


Comments

Popular posts from this blog

c# - how to write client side events functions for the combobox items -

exception - Python, pyPdf OCR error: pyPdf.utils.PdfReadError: EOF marker not found -