-
-
Save mfields/1006626 to your computer and use it in GitHub Desktop.
<?php | |
/* | |
* Send all required arguments. | |
*/ | |
$test = new My_Object( array( | |
'one' => 1, | |
'two' => 2, | |
'three' => 3, | |
) ); | |
print '<pre>'; | |
gettype( $test ); // Should be "My_Object" | |
var_dump( empty( $test ) ); // false as expected. | |
var_dump( $test ); | |
print '</pre>'; | |
/* | |
* This object is missing one required argument. | |
*/ | |
$test = new My_Object( array( | |
'one' => 1, | |
'two' => 2, | |
) ); | |
print '<pre>'; | |
gettype( $test ); // Would be neat if this could return some sort of error object. | |
var_dump( empty( $test ) ); // Even though all properties have been removed, this still returns false? | |
var_dump( $test ); | |
print '</pre>'; | |
class My_Object { | |
public $one = null; | |
public $two = null; | |
public $three = null; | |
public function __construct( $args = array() ) { | |
$diff = array_diff_key( get_object_vars( $this ), $args ); | |
if ( ! empty( $diff ) ) { | |
/* Let them know they're doing it wrong. */ | |
trigger_error( 'Could not construct object.' ); | |
/* It's possible to kill all of the properties. */ | |
foreach( array_keys( get_object_vars( $this ) ) as $property ) { | |
unset( $this->$property ); | |
} | |
/* Anyway to change type of object before return? */ | |
return; | |
} | |
$this->one = (int) $args['one']; | |
$this->two = (int) $args['two']; | |
$this->three = (int) $args['three']; | |
} | |
} |
Actually, I did just find some reference to using settype( $this, 'null );
as a deconstructor for objects. You might be able to use a similar setup inside __construct()
to re-cast your object as an error object, as null, as a Boolean, or whatever. But I can't test at the moment on this machine ...
Thanks for the feedback! I'm kind of in this named argument phase and I don't see it going away anytime soon quite honestly. I fear ever having to read documentation again just to know the purpose of the values that I'm passig to a function. Makes me angry :) ... or :( ... yeah, that's more like it.
I thought about doing #1. And this is what I will probably do in the end. Just thinking about alternative to doing this, but it really makes a lot of sense.
#2 really has no effect. Although I did not see it stated in the docs, I think that __constructor() returns void. Anything that I've tried along these lines has failed. I can never access the return value.
#3 This is pretty cool - I did not know that that function existed. Will definitely come in handy in the future! Unfortunately, it's a bit strict as it stops the script. Would much rather generate a notice and let the script continue.
settype inside the constructor did not seem to do anything ... started to get excited about this one, but no luck.
#1 is the winner so far!!!
I also had another idea and was wondering what you thought:
What if I were to create a boolean static method named check_args(). This could be called on the args before individual objects are created?
What if I were to create a boolean static method named check_args(). This could be called on the args before individual objects are created?
Kind of like pre-validation? I think that would work ... but you'd need to document it well so others using the code would remember to use it before they instantiate their object.
if ( My_Object::check_args( $args ) ) {
$test = new My_Object( $args );
} else {
// die in fiery brillaince
}
Cool! Other people using the object is totally not permitted. My intention is to only use it internally in a plugin. Basically there would be a configuration array for "Icon Sets" that is filterable. This array would be looped over and a new Icon_Set object will be created only if it is configured properly.
I meant "others using the code" as in anyone who forks your project or uses it as a base/inspiration for their own system.
Now that I know what you're trying to do (rather than mucking around with My_Object
s and $test
s), have you considered using a factory method?
Basically:
$test = create_my_object( $args );
function create_my_object( $args = array() ) {
if ( Icon_Set::check_args( $args ) ) {
return new Icon_Set( $args );
} else {
return new My_Error( "You're doing it wrong!" );
}
}
Then $test
will either be an instance of Icon_Set or some custom error object if it was configured improperly.
(OK, it's not a real factory method ... but similar enough ...)
Hmm ... I wouldn't pass $args as an array. I'd build the constructor as:
This allows you to instantiate the object a little more cleanly:
$test = new My_Object( 1, 2, 3 );
Inside of
__construct()
you can test the size of$args
to make sure they sent enough variables, then test the type of each element of$args
to make sure they sent the right stuff. But every time you instantiate the object, whether construction fails or succeeds, gettype() will always return 'My_Object'You really have three options:
1 - Set some property inside the object based on whether or not construction succeeded and check it later:
2 - Return
false
on failure:3 - Throw an exception inside
__construct()
if the args are invalid.throw new InvalidArgumentException()
works well here.But changing the type of object before the return? I'm pretty sure you can't actually do that. PHP only has so many types available, and custom objects are all really just extensions of
stdObject
anyway. You could usesettype()
outside the object to cast it as something else, but nothing internal ...