note 118791 added to reflectionclass.newinstancewithoutconstructor
| From: | 260atciemnosc | Date: | Sat, 06 Feb 2016 14:11:30 +0000 |
| Subject: | note 118791 added to reflectionclass.newinstancewithoutconstructor | ||
| Groups: | php.notes | ||
| Request: | Send a blank email to php-notes+get-204887@lists.php.net to get a copy of this message | ||
sorry for replying to such an old comment, but there's something i wanted to point out.
@ tom at r dot je:
While I agree with what you said in general, there *are* cases where it's not true, and since
PHP doesn't allow for multiple constructors there's no other good way around it.
> The problem? It breaks encapsulation.
> An object can exist in the application but may not be able to fulfill its
> responsibility because it's missing dependencies.
> The use of this method makes it possible for an incomplete object
> to exist in the system;
> the object can exist in a state that its author never intended.
If you're using this method from some factory method, to manually init the object in other way
that the constructor that, this point is no longer valid.
Consider the example, where you use constructor to set-up the object after getting it from database
(e.g. you need to pull some array from other table, basing on some id parameter). But you want to
also be able to create object manually (for inserting to the database, for example).
The best thing to do would be to have two different constructors, but since it is not possible in
php you need some other way to create the object.
example:
<?php
// this usually would be a static cache in some class, or array returned by method getMeta($id),
etc.
$meta = array(1337 => array('key1' => 'value1', 'key2' =>
'value2'));
class Test {
public $id;
public $data;
public $meta;
public function __construct() {
global $meta;
if(is_int($this->id)) $this->meta = $meta[$this->id];
}
public static function create_empty() {
$r = new ReflectionClass(__CLASS__);
return $r->newInstanceWithoutConstructor();
}
}
echo "emulating PDO::FETCH_CLASS behavior: ";
$t = Test::create_empty();
$t->meta = 1337;
$t->__construct();
var_dump($t);
echo "empty class: ";
$testItem = Test::create_empty();
// ... here you can start setting up the item, e.g. from XML
var_dump($testItem);
$testItem->id = 0;
$testItem->data = "some data";
$testItem->meta = array("somekey" => "somevalue");
echo "after setup:";
var_dump($testItem);
?>
Of course, you can instead make empty constructor, and create some init() method, but then you have
to remember to call init() everywhere.
You can also create some other way of adding the item to database, but then you'd have to
classes to handle the same data - one for retrieving and other for storing.
If you instead use some factory class (or just a factory method, like in the simplified example
above) having a way to create totally empty object is useful. With full factory approach you would
first use some TestFactory->prepare() method, then you'd call methods to set what you need,
and the factory would set all uninitialized variables to some default values upon calling
TestFactory->get() to retrieve prepared object.
----
Server IP: 72.52.91.14
Probable Submitter: 159.205.7.72
----
Manual Page -- http://php.net/manual/en/reflectionclass.newinstancewithoutconstructor.php
Edit -- https://master.php.net/note/edit/118791
Del: integrated -- https://master.php.net/note/delete/118791/integrated
Del: useless -- https://master.php.net/note/delete/118791/useless
Del: bad code -- https://master.php.net/note/delete/118791/bad+code
Del: spam -- https://master.php.net/note/delete/118791/spam
Del: non-english -- https://master.php.net/note/delete/118791/non-english
Del: in docs -- https://master.php.net/note/delete/118791/in+docs
Del: other reasons-- https://master.php.net/note/delete/118791
Reject -- https://master.php.net/note/reject/118791
Search -- https://master.php.net/manage/user-notes.php