80775

How do i deal with multiple contructor arguments or class variables?

Question:

How do I know what to load in a constructor and what to set using the set methods later on?

For example, I have a question class which most of the time will call the following vars:

protected $question; protected $content; protected $creator; protected $date_added; protected $id; protected $category;

At the moment I have it so only the bare essentials $id, $question, and $content are set in the constructor so I don't start building up a huge list of constructor arguments. This however, means that when I make a new question object elsewhere, I have to set the other properties of that object straight after meaning 'setter code' getting duplicated all over the place.

Should I just pass them all into the constructor right away, do it the way I'm doing it already, or is there a better solution that I'm missing? Thanks.

Answer1:

Depending on the language you can have multiple constructors for any one class.

Answer2:

You could use an array as the parameter to the constructor or setter method.

Just example:

public function __construct($attributes = array()) { $this->setAttributes($attributes); } public function setAttributes($attributes = array()) { foreach ($attributes as $key => $value) { $this->{$key} = $value; } }

Answer3:

PHP doesn't support traditional constructor overloading (as other OO languages do). An option is to pass an array of arguments into the constructor:

public function __construct($params) { } // calling it $arr = array( 'question' => 'some question', 'content' => ' some content' ... ); $q = new Question($arr);

Using that, you're free to pass a variable number of arguments and there is no dependency on the order of arguments. Also within the constructor, you can set defaults so if a variable is not present, use the default instead.

Answer4:

I would pass an array to the constructor with the values I want to set.

public function __construct(array $values = null) { if (is_array($values)) { $this->setValues($values); } }

Then you need a method setValues to dynamicly set the values.

public function setValues(array $values) { $methods = get_class_methods($this); foreach ($values as $key => $value) { $method = 'set' . ucfirst($key); if (in_array($method, $methods)) { $this->$method($value); } } return $this; }

For this to work you need setter methods for your properties like setQuestion($value) etc.

Answer5:

A fluent interface is another solution.

class Foo { protected $question; protected $content; protected $creator; ... public function setQuestion($value) { $this->question = $value; return $this; } public function setContent($value) { $this->content = $value; return $this; } public function setCreator($value) { $this->creator = $value; return $this; } ... } $bar = new Foo(); $bar ->setQuestion('something') ->setContent('something else') ->setCreator('someone');

Or use inheritance...

class Foo { protected $stuff; public function __construct($stuff) { $this->stuff = $stuff; } ... } class bar extends Foo { protected $moreStuff; public function __construct($stuff, $moreStuff) { parent::__construct($stuff); $this->moreStuff = $moreStuff; } ... }

Or use optional parameters...

class Foo { protected $stuff; protected $moreStuff; public function __construct($stuff, $moreStuff = null) { $this->stuff = $stuff; $this->moreStuff = $moreStuff; } ... }

In any case, there are many good solutions. Please dont use a single array as params or func_get_args or _<em>get/</em>_set/__call magic, unless you have a really good reason to do so, and have exhausted all other options.

Recommend

  • In WPF,MVVM should ViewModel be involved in opening a window, e.g. About-window?
  • declaring device constant in terms of another constant
  • Objective C difference between self.variable and variable assignments
  • How to add an object in my collection by only using add method? [closed]
  • Why is new Number(8) not exactly equal to 8?
  • Validity Method for Reference Classes
  • Using an enum contained in a Cloud Endpoint model on a Android client
  • Validation fired but Red Border does not appear with User Control in Silverlight 4
  • custom string delimiters stringtemplate-4
  • What's wrong with my datatrigger binding?
  • NUnit 3.0 TestCase const custom object arguments
  • What does 'Language neutral' mean with regard to MAKELANGID?
  • jQuery ready not fired after rails link_to is clicked
  • Android activity accessing service's static reference before the service is ready
  • Do I need to reset a Perl hash index?
  • Yii2: Config params vs. const/define
  • Switching to Release Build causes runtime error in Web Reference
  • Algorithm for a smudge tool?
  • How to access EntityManager inside Entity class in EJB3
  • Repeat a vertical line on every page in Report Builder / SSRS
  • Android screen density dpi vs ppi
  • Bug in WPF DataGrid
  • Excel - Autoshape get it's name from cell (value)
  • Check if a string to interpolate provides expected placeholders
  • Rearranging Cells in UITableView Bug & Saving Changes
  • RestKit - RKRequestDelegate does not exist
  • Traverse Array and Display in markup
  • Windows forms listbox.selecteditem displaying “System.Data.DataRowView” instead of actual value
  • log4net write single file for each call to log.info
  • Benchmarking RAM performance - UWP and C#
  • Acquiring multiple attributes from .xml file in c#
  • Angular 2 constructor injection vs direct access
  • Why joiner is not used after Sequence generator or Update statergy
  • How to CLICK on IE download dialog box i.e.(Open, Save, Save As…)
  • Exception on Android 4.0 `android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode)`
  • File not found error Google Drive API
  • IndexOutOfRangeException on multidimensional array despite using GetLength check
  • How can I remove ASP.NET Designer.cs files?
  • Is it possible to post an object from jquery to bottle.py?
  • java string with new operator and a literal