From 94dbf3034a838c6742a5798d6a39c4e6de53549a Mon Sep 17 00:00:00 2001 From: Anther Date: Thu, 14 Mar 2013 22:45:56 -0400 Subject: [PATCH 1/6] Changes to relationship to make loading relationships closer to 2N vs n^2 --- lib/Relationship.php | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/lib/Relationship.php b/lib/Relationship.php index 297d89438..526071160 100644 --- a/lib/Relationship.php +++ b/lib/Relationship.php @@ -184,24 +184,36 @@ protected function query_and_attach_related_models_eagerly(Table $table, $models $model_values_key = $inflector->variablize($model_values_key); $query_key = $inflector->variablize($query_key); + $all_related_with_value = null; foreach ($models as $model) { + if(!isset($all_related_with_value)) + { + $all_related_with_value = array(); + foreach ($related_models as $related) + { + $all_related_with_value[$related->$query_key][] = $related; + } + } $matches = 0; $key_to_match = $model->$model_values_key; - foreach ($related_models as $related) + if(array_key_exists($key_to_match,$all_related_with_value)) { - if ($related->$query_key == $key_to_match) + foreach ($all_related_with_value[$key_to_match] as $related) { - $hash = spl_object_hash($related); - - if (in_array($hash, $used_models)) - $model->set_relationship_from_eager_load(clone($related), $this->attribute_name); - else - $model->set_relationship_from_eager_load($related, $this->attribute_name); - - $used_models[] = $hash; - $matches++; + if ($related->$query_key == $key_to_match) + { + $hash = spl_object_hash($related); + + if (array_key_exists($hash, $used_models)) + $model->set_relationship_from_eager_load(clone($related), $this->attribute_name); + else + $model->set_relationship_from_eager_load($related, $this->attribute_name); + + $used_models[$hash] = null; + $matches++; + } } } From 0a18ce4cb2208d31920f3fc1978056842acaad5b Mon Sep 17 00:00:00 2001 From: Bogdan D Date: Mon, 13 Jan 2014 15:28:09 +0200 Subject: [PATCH 2/6] FIX jpfuentes2#361 Group association conditions in parentheses --- lib/Utils.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/Utils.php b/lib/Utils.php index af5840cd6..7e6e2559c 100644 --- a/lib/Utils.php +++ b/lib/Utils.php @@ -181,12 +181,13 @@ public static function add_condition(&$conditions=array(), $condition, $conjucti $conditions = array_flatten($condition); else { - $conditions[0] .= " $conjuction " . array_shift($condition); + $conditions[0] = "(" . $conditions[0]; + $conditions[0] .= ") $conjuction (" . array_shift($condition) . ")"; $conditions[] = array_flatten($condition); } } elseif (is_string($condition)) - $conditions[0] .= " $conjuction $condition"; + $conditions[0] = "(" . $conditions[0] . ") $conjuction ($condition)"; return $conditions; } @@ -367,4 +368,4 @@ public static function add_irregular($singular, $plural) { self::$irregular[$singular] = $plural; } -} \ No newline at end of file +} From 890969d55ac2a725358de51a9027f6f9893dae00 Mon Sep 17 00:00:00 2001 From: Koen Punt Date: Mon, 8 Dec 2014 23:20:27 +0100 Subject: [PATCH 3/6] make string buildup more readable update test to match query string --- lib/Utils.php | 7 +++---- test/RelationshipTest.php | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/Utils.php b/lib/Utils.php index 7e6e2559c..45bb0a459 100644 --- a/lib/Utils.php +++ b/lib/Utils.php @@ -173,7 +173,7 @@ public static function extract_options($options) return is_array(end($options)) ? end($options) : array(); } - public static function add_condition(&$conditions=array(), $condition, $conjuction='AND') + public static function add_condition(&$conditions=array(), $condition, $conjunction='AND') { if (is_array($condition)) { @@ -181,13 +181,12 @@ public static function add_condition(&$conditions=array(), $condition, $conjucti $conditions = array_flatten($condition); else { - $conditions[0] = "(" . $conditions[0]; - $conditions[0] .= ") $conjuction (" . array_shift($condition) . ")"; + $conditions[0] = "({$conditions[0]}) $conjunction (" . array_shift($condition) . ")"; $conditions[] = array_flatten($condition); } } elseif (is_string($condition)) - $conditions[0] = "(" . $conditions[0] . ") $conjuction ($condition)"; + $conditions[0] = "({$conditions[0]}) {$conjunction} ($condition)"; return $conditions; } diff --git a/test/RelationshipTest.php b/test/RelationshipTest.php index e726a6b71..65a640647 100644 --- a/test/RelationshipTest.php +++ b/test/RelationshipTest.php @@ -540,7 +540,7 @@ public function test_gh93_and_gh100_eager_loading_respects_association_options() Venue::$has_many = array(array('events', 'class_name' => 'Event', 'order' => 'id asc', 'conditions' => array('length(title) = ?', 14))); $venues = Venue::find(array(2, 6), array('include' => 'events')); - $this->assert_sql_has("WHERE length(title) = ? AND venue_id IN(?,?) ORDER BY id asc",ActiveRecord\Table::load('Event')->last_sql); + $this->assert_sql_has("WHERE (length(title) = ?) AND (venue_id IN(?,?)) ORDER BY id asc",ActiveRecord\Table::load('Event')->last_sql); $this->assert_equals(1, count($venues[0]->events)); } From 9b09a517788e6f4d2ab67e1737db079a01037ebe Mon Sep 17 00:00:00 2001 From: Kevin Foster Date: Sat, 13 Dec 2014 09:26:40 -0500 Subject: [PATCH 4/6] Refactor is_hash() --- lib/Utils.php | 8 +++++--- test/UtilsTest.php | 16 +++++++++++++++- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/lib/Utils.php b/lib/Utils.php index 45bb0a459..3db34514c 100644 --- a/lib/Utils.php +++ b/lib/Utils.php @@ -63,13 +63,15 @@ function array_flatten(array $array) /** * Somewhat naive way to determine if an array is a hash. */ -function is_hash(&$array) +function is_hash($array) { - if (!is_array($array)) + if (!is_array($array)) { return false; + } $keys = array_keys($array); - return @is_string($keys[0]) ? true : false; + + return isset($keys[0]) && is_string($keys[0]); } /** diff --git a/test/UtilsTest.php b/test/UtilsTest.php index 20074bbc9..37d8bf151 100644 --- a/test/UtilsTest.php +++ b/test/UtilsTest.php @@ -103,5 +103,19 @@ public function test_wrap_strings_in_arrays() $x = '1'; $this->assert_equals(array(array('1')),ActiveRecord\wrap_strings_in_arrays($x)); } -} + public function test_is_hash() + { + $hash = array('key' => 'value'); + $this->assert_true(ActiveRecord\is_hash($hash)); + + $notHash = array(0 => 'value'); + $this->assert_false(ActiveRecord\is_hash($notHash)); + } + + public function test_is_hash_empty_array() + { + $notHash = array(); + $this->assert_false(ActiveRecord\is_hash($notHash)); + } +}; From 34ac4e44da50612af842bc005bc482f4b4e5e6a5 Mon Sep 17 00:00:00 2001 From: Yoan Blanc Date: Sun, 10 Apr 2011 20:16:56 +0200 Subject: [PATCH 5/6] =?UTF-8?q?Auto=20setter=20for=20relations=20with=20te?= =?UTF-8?q?sts=20(thanks=20to=20Jan=20=E2=86=92).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Support for subclasses of the model specified. null is also a valid value to be set for relations --- lib/Model.php | 26 ++++++++++++++++++- test/RelationshipTest.php | 53 +++++++++++++++++++++++++++++++++++++++ test/models/SubVenue.php | 6 +++++ 3 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 test/models/SubVenue.php diff --git a/lib/Model.php b/lib/Model.php index 0c20ac9ab..c87019599 100644 --- a/lib/Model.php +++ b/lib/Model.php @@ -446,6 +446,30 @@ public function __set($name, $value) return $this->$item['to']->$delegated_name = $value; } + $table = static::table(); + if ($relationship = $table->get_relationship($name) + ) + { + if (is_null($value)) + { + $this->__relationships[$name] = $value; + return $this->assign_attribute($relationship->foreign_key[0], $value); + } + elseif (($value instanceof \ActiveRecord\Model) && + $value instanceof $relationship->class_name) + { + $this->__relationships[$name] = $value; + $pk = $value->get_primary_key(0); + return $this->assign_attribute( + $relationship->foreign_key[0], + $value->is_new_record() ? null : $value->{$pk[0]} + ); + } + else + { + throw new RelationshipException(); + } + } throw new UndefinedPropertyException(get_called_class(),$name); } @@ -837,7 +861,7 @@ public static function table() * @param boolean $guard_attributes Set to true to guard protected/non-accessible attributes * @return Model */ - public static function create($attributes, $validate=true, $guard_attributes=true) + public static function create(array $attributes=array(), $validate=true, $guard_attributes=true) { $class_name = get_called_class(); $model = new $class_name($attributes, $guard_attributes); diff --git a/test/RelationshipTest.php b/test/RelationshipTest.php index 65a640647..1b12c225c 100644 --- a/test/RelationshipTest.php +++ b/test/RelationshipTest.php @@ -732,4 +732,57 @@ public function test_dont_attempt_eager_load_when_record_does_not_exist() { Author::find(999999, array('include' => array('books'))); } + + public function test_gh_125_auto_setter_for_relation() + { + $event = new Event(array( + 'venue' => new Venue() + )); + + $this->assert_not_null($event->venue); + $this->assert_null($event->venue_id); + } + + public function test_gh_125_auto_setter_for_relation_with_id() + { + $event = new Event(array( + 'venue' => Venue::create() + )); + + $this->assert_not_null($event->venue); + $this->assert_not_null($event->venue_id); + $event->venue->delete(); + } + + /** + * @expectedException ActiveRecord\RelationshipException + */ + public function test_gh_125_auto_setter_for_relation_raises_exception() + { + $event = new Event(array( + 'venue' => new Book() + )); + } + + public function test_gh_125_auto_setter_for_relation_using_subclass() + { + $event = new Event(array( + 'venue' => new SubVenue() + )); + + $this->assert_not_null($event->venue); + $this->assert_null($event->venue_id); + } + + public function test_gh_125_unset_existing_relation() + { + $event = new Event(array( + 'venue' => Venue::create() + )); + + $event->venue->delete(); + $event->venue = null; + $this->assert_null($event->venue); + $this->assert_null($event->venue_id); + } } diff --git a/test/models/SubVenue.php b/test/models/SubVenue.php new file mode 100644 index 000000000..9de87a2c1 --- /dev/null +++ b/test/models/SubVenue.php @@ -0,0 +1,6 @@ + From 5b9acfd82faf4fdde4b581671bd68cee9f26b81d Mon Sep 17 00:00:00 2001 From: Koen Punt Date: Mon, 21 Jul 2014 11:16:51 +0200 Subject: [PATCH 6/6] HasMany relationship --- test/RelationshipTest.php | 7 +++++++ test/models/Venue.php | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/test/RelationshipTest.php b/test/RelationshipTest.php index 1b12c225c..8d1049462 100644 --- a/test/RelationshipTest.php +++ b/test/RelationshipTest.php @@ -785,4 +785,11 @@ public function test_gh_125_unset_existing_relation() $this->assert_null($event->venue); $this->assert_null($event->venue_id); } + + public function test_gh_125_add_model_to_has_many_relation() + { + $venue = Venue::find('first'); + $venue->events = null; + // $venue->events = array(new Event()); + } } diff --git a/test/models/Venue.php b/test/models/Venue.php index 3c13adeee..6d1e3f6ce 100644 --- a/test/models/Venue.php +++ b/test/models/Venue.php @@ -6,7 +6,7 @@ class Venue extends ActiveRecord\Model static $has_many = array( - 'events', + array('events'), array('hosts', 'through' => 'events') );