Skip to content

Commit

Permalink
Adding a constructor to Entity to hydrate the class directly
Browse files Browse the repository at this point in the history
Making it possible to set a single property in Entity::set()
  • Loading branch information
lorenzo committed Sep 16, 2013
1 parent 2034d1b commit d2d7792
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 17 deletions.
69 changes: 56 additions & 13 deletions Cake/ORM/Entity.php
Expand Up @@ -11,6 +11,22 @@ class Entity implements \ArrayAccess {
*/
protected $_properties = [];

/**
* Initializes the internal properties of this entity out of the
* keys in an array
*
* ### Example:
*
* ``$entity = new Entity(['id' => 1, 'name' => 'Andrew'])``
*
* @param array $properties hash of properties to set in this entity
* @param boolean $useSetters whether use internal setters for properties or not
* @return void
*/
public function __construct(array $properties = [], $useSetters = true) {
$this->set($properties, $useSetters);
}

/**
* Magic getter to access properties that has be set in this entity
*
Expand All @@ -33,8 +49,15 @@ public function __set($property, $value) {
}

/**
* Set a hashed array as properties in this entity by converting each
* key => value pair into properties in this object.
* Sets a single property inside this entity.
*
* ### Example:
*
* ``$entity->set('name', 'Andrew');``
*
* It is also possible to mass-assign multiple properties to this entity
* with one call by passing a hashed array as properties in the form of
* property => value pairs
*
* ## Example:
*
Expand All @@ -44,22 +67,42 @@ public function __set($property, $value) {
* echo $entity->id // prints 1
* }}
*
* @param array $properties list of properties to set
* Some times it is handy to bypass setter functions in this entity when assigning
* properties. You can achieve this by setting the third argument to false when
* assigning a single property or the second param when using an array of
* properties.
*
* ### Example:
*
* ``$entity->set('name', 'Andrew', false);``
*
* ``$entity->set(['name' => 'Andrew', 'id' => 1], false);``
*
* @param string|array $property the name of property to set or a list of
* properties with their respective values
* @param mixed|boolean $value the value to set to the property or a boolean
* signifying whether to use internal setter functions or not
* @param boolean $useSetters whether to use setter functions in this object
* or bypass them
* @return \Cake\ORM\Entity
*/
public function set(array $properties = [], $useSetters = true) {
public function set($property, $value = false, $useSetters = true) {
if (is_string($property)) {
$property = [$property => $value];
} else {
$useSetters = $value;
}

if (!$useSetters) {
$this->_properties = $properties + $this->_properties;
$this->_properties = $property + $this->_properties;
return $this;
}

foreach($properties as $property => $value) {
if (method_exists($this, 'set' . ucFirst($property))) {
$value = $this->{'set' . ucFirst($property)}($value);
foreach ($property as $p => $value) {
if (method_exists($this, 'set' . ucFirst($p))) {

This comment has been minimized.

Copy link
@markstory

markstory Sep 17, 2013

Member

We might want to build an in memory map of which functions exist as this could be executed many times per request.

This comment has been minimized.

Copy link
@lorenzo

lorenzo Sep 17, 2013

Author Member

Yeah, that is a good idea

This comment has been minimized.

Copy link
@jrbasso

jrbasso Sep 17, 2013

Member

👏

$value = $this->{'set' . ucFirst($p)}($value);
}
$this->_properties[$property] = $value;
$this->_properties[$p] = $value;
}
return $this;
}
Expand All @@ -72,11 +115,11 @@ public function set(array $properties = [], $useSetters = true) {
*/
public function &get($property) {
$method = 'get' . ucFirst($property);
$value = $this->_properties[$property];
if (method_exists($this, $method)) {
$value =& $this->{$method}();
} else {
$value =& $this->_properties[$property];
$this->_properties[$property] = $this->{$method}($value);
}
$value =& $this->_properties[$property];
return $value;
}

Expand All @@ -88,7 +131,7 @@ public function &get($property) {
*/
public function toArray() {
$result = [];
foreach($this->_properties as $property => $value) {
foreach ($this->_properties as $property => $value) {
$result[$property] = $this->get($property);
}
return $result;
Expand Down
4 changes: 2 additions & 2 deletions Cake/ORM/ResultSet.php
Expand Up @@ -273,14 +273,14 @@ protected function _groupResult($row) {
$results[$alias] = $this->_castValues($instance->target(), $results[$alias]);

if ($this->_hydrate && $assoc['canBeJoined']) {
$results[$alias] = (new $assoc['entityClass'])->set($results[$alias], false);
$results[$alias] = new $assoc['entityClass']($results[$alias], false);
}
$results = $instance->transformRow($results);
}

$results = $results[$defaultAlias];
if ($this->_hydrate && !($results instanceof Entity)) {
$results = (new $this->_entityClass)->set($results, false);
$results = new $this->_entityClass($results, false);
}
return $results;
}
Expand Down
4 changes: 2 additions & 2 deletions Cake/Test/TestCase/ORM/QueryTest.php
Expand Up @@ -1183,14 +1183,14 @@ public function testHydrateBelongsToMany() {
$expected = [
'id' => 1,
'name' => 'tag1',
'ArticleTag' => (new \Cake\ORM\Entity)->set(['article_id' => 1, 'tag_id' => 1])
'ArticleTag' => new \Cake\ORM\Entity(['article_id' => 1, 'tag_id' => 1])
];
$this->assertEquals($expected, $first->tags[0]->toArray());

$expected = [
'id' => 2,
'name' => 'tag2',
'ArticleTag' => (new \Cake\ORM\Entity)->set(['article_id' => 1, 'tag_id' => 2])
'ArticleTag' => new \Cake\ORM\Entity(['article_id' => 1, 'tag_id' => 2])
];
$this->assertEquals($expected, $first->tags[1]->toArray());
}
Expand Down

0 comments on commit d2d7792

Please sign in to comment.