There is only need for named parameters when doing procedural programming. I do a lot of work in PLSQL where they have them, PHP is going the other way into more common OOP practices. This code also relies on the global keyword. Dependencies should be passed, especially objects using type hinting. Else if the global object is null or a different type of object then a very unhelpful error could be thrown within the function with no hint what called it, now this could be guard with and instance of but that is more work than needs to be done.
<?php
error_reporting( E_ALL | E_STRICT );
ini_set('display_errors',1);
class InputAttributes{
private $attributes = array();
private $name;
function __construct( $name ){
$this->name = $name;
}
/**
* @return InputAttributes
*/
function Set( $name, $value ){
$this->attributes[$name] = $value;
return $this;
}
function GetAll(){
return $this->attributes;
}
function GetName(){
return $this->name;
}
}
echo "<br/><br/><br/>Jquery style using Set to return the instance so it can be appended to<br/>";
//
function inputText(InputAttributes $attributes){
$html = '<input type="text" name="' . htmlentities($attributes->GetName()). '" ';
foreach( $attributes->GetAll() as $attributeName => $attributeValue ){
$html.= $attributeName . '="' . htmlentities($attributeValue) . '" ';
}
$html .= " />\n";
return $html;
}
$attributes = new InputAttributes('inputName');
echo inputText( $attributes->Set( 'type' ,'text')
->Set( 'readonly' ,'readonly' )
->Set( 'class' ,'testClass' )
->Set( 'value' ,'testC"ddd\'dddd' ) );
$named = '';
echo "<br/><br/><br/>Start of inputTextGoodErrorUsingInstanceOfThatIsLessThanIdeal<br/> Exception trace <br/> ";
function inputTextGoodErrorUsingInstanceOfThatIsLessThanIdeal($inputName)
{
global $named;
if( !$named instanceof InputAttributes ){ // named and $name are too similar to be easily readable so now $inputName
throw new Exception( "Global Named is not an instance of named" );
}
}
try{
inputTextGoodErrorUsingInstanceOfThatIsLessThanIdeal( 'mooo' );
}catch( Exception $e ){
echo print_r(array_reverse($e->getTrace())); // shows [line] => 62 was the original caller useful for debugging, globals are inherentley bad for debugging
}
echo "<br/><br/><br/>Start of inputTextGoodErrorUsingTypeHintingIdeal, tells you <b>Fatal error</b>: Argument 2 passed to inputTextGoodErrorUsingTypeHintingIdeal() must be an object of class InputAttributes, called in PHPDocument1 on line 77 and defined in <b>PHPDocument1</b> on line <b>70</b><br />
as it is a fatal error. Something has right to declare it's interface to be strict, also cuts down on a lot of errors and makes debugging a lot easier. <br/> ";
function inputTextGoodErrorUsingTypeHintingIdeal($inputName, InputAttributes $attributes )
{
//Will bug out automatically if named is not passed
}
inputTextGoodErrorUsingTypeHintingIdeal( 'mooo', $named ); // shows 77 was the original caller(very useful information) and the called exists on 70
?>
In the orginal example lots of issets had to be done due to there is a lack of design of what the object will actually be composed of. Objects are about design at the point of writing.
As I have said I do a lot of PL/SQL and named parametes are there to make life bearable due to then enforced large parameter lists that can be required, they are definately not the best solution though.
The whole $named->maxlength = on an undeclared member is very bad practice. Anything can be in an object at any time and the object then cannot be trusted by anything it is passed to as it has slack interface design so has a slack contract. Tight contracts mean less buggy code.
The extra
$attributes = new InputAttributes('inputName');
line is a small price to pay for not being clever. There is a balance to be struck with number of parameters, horizontal line width and vertical line height in this case. As all PHP parameters that are not Type Hinted have to be treated as variants a lot of the leg work has to be done to prove they are not tainted, Type Hinting places blame fairly on the caller where it should be fixed in a very nice and easy fashion.
Classes can keep themselves clean, where arrays cannot. Clean defined dependancies create clean easy to read code. Classes can also be refactored, passed by interface and gain intelligent behaviour that variants and arrays cannot.
Globals are also very nasty things and there is never any need for them. They make bug hunting very hard when dealing with behavioural issues. If you see yourself using global ask in a forum for a better solution.
Anyway enough of me 🙂