Jump to content

Best way to deal with optional parameters for classes and functions


entheologist

Recommended Posts

I've been wasting time reinventing the wheel with this one so I'd greatly appreciate if people here could share how they deal with this. So heres an example class:

class VarDataClass {
	
	private $module = 'show_vars';
	public $category = 'DEFAULT CATEGORY';
	public $title = 'DEFAULT TITLE';
        public $option2 = 'DEFAULT VALUE';
        public $show = 'SOMETHING';
	public $output = 'box';
	
	public $_settings = array(
		'category' => 'DEFAULT CATEGORY',
		'title' => 'DEFAULT TITLE',
		'option2' => 'DEFAULT VALUE',
		'show' => 'SOMETHING',
		'output' => 'box'
	);

       public function __constructor($options = array()) {

       }
       //   some functions
}

So the $options parameter in the constructor contains all the custom settings for the class instance, lets say in this case they're all optional. Since they're all optional I made that $_settings array have default values. And for this example, I added another way I could do it, by adding the variables individually rather than as part of the settings array. So I'm wondering whats the best way to replace the default values with any values that the user happens to input. Is a list of variables easier, or is the $_settings array the way to go?

 

I think the settings array would be the way to do it, so I'm thinking I should make some option setter function, but whats the easiest way to do that? Should I loop through every key in the settings array, and check if that key is present in the $options variable that the user input? Or is there some kind of array_replace function I can use that will set all the options in one go without having to use a loop?

 

Another issue is its a pain in the ass for the user to input an associative array, its much easier to just to

$object = new VarDataClass('CATEGORY','TITLE');

etc. but then the problem is if they only want to set say the two last options, they'd have to do

VarDataClass('','','','SHOW','OUTPUT');

Basically I'm just looking for the most evolved way to handle these optional functions so I don't have to reinvent the wheel myself.

Edited by entheologist
Link to comment
Share on other sites

I'd get rid of the individual public variables and use __get/set instead, with an array containing the actual values. Then it's easy: $_settings is the array and you merge the $options into it.

/**
 * @property string $category
 * @property string $title
 * @property string $option2
 * @property string $show
 * @property string $output
 */
class VarDataClass {

	private $settings = array(
		'category' => 'DEFAULT CATEGORY',
		'title' => 'DEFAULT TITLE',
		'option2' => 'DEFAULT VALUE',
		'show' => 'SOMETHING',
		'output' => 'box'
	);

	public function __construct(array $options = array()) {
		// array_intersect_key so only recognized $options get merged in
		$this->settings = array_merge($this->settings, array_intersect_key($options, $this->settings));
	}

	public function __get($name) {
		return (isset($this->settings[$name]) ? $this->settings[$name] : null);
	}

	public function __set($name, $value) {
		if (isset($this->settings[$name])) {
			$this->settings[$name] = $value;
		}
	}

}
Link to comment
Share on other sites

Thanks a lot. I'll try out your method. I just found out there is an array_replace function, even an array_replace recursive function which would be perfect would replacing defaults with user input options. This will work perfect for when users input associative arrays, but won't account for numeric arrays. We need to make a universal options settter function/class/trait that will take care of all these possibilities.

Link to comment
Share on other sites

This is one of the extremely rare cases where something I tried worked first time, but it did:

trait optionSetterTrait {

	private $_diagnose = array();

	public function __construct(array $options = array()) {
		
		$this->_diagnose['options'] = $options;
		//	show numeric values of each setting
		$this->_diagnose['settingsKeys'] = array_keys($this->_settings);
		// array_intersect_key so only recognized $options get merged in
		$this->_settings = array_merge($this->_settings, array_intersect_key($options, $this->_settings));
		
		$this->_diagnose['settings'] = $this->_settings;
	}

	public function __get($name) {
		return (isset($this->_settings[$name]) ? $this->_settings[$name] : null);
	}

	public function __set($name, $value) {
		if (isset($this->_settings[$name])) {
			$this->_settings[$name] = $value;
		}
	}
	
	public function diagnose() {
		
		if (empty($subSection) || $subSection == 'all') { }
		
		$outputArray = print_r($this->_diagnose,true);
		
		$output = "<pre>$outputArray</pre>";
		echo $output;
		
	}
	
}

class linkFinder {
	
	private $_settings = array(
		'paths' => array('./'),
		'extenstions' => array('php','html'),
		'category' => 'blah'
	);
	
	use optionSetterTrait;
	
	private function linkGenerator() {
		$fileList['fullPath'] = glob("./*.php");
	}
	
}

$test = new linkFinder(array('category' => 'blah'));
$test->diagnose();

So from now on in every class I make I can just include that optionSetter trait, that will make life so much easier. Does anyone know of a trait like this been made before? If not I should put it up on github as a gist so people can improve it over time.

Edited by entheologist
Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.