diff --git a/examples/orders/models/Order.php b/examples/orders/models/Order.php index cdc1f99e..a6a35c16 100644 --- a/examples/orders/models/Order.php +++ b/examples/orders/models/Order.php @@ -4,16 +4,19 @@ class Order extends ActiveRecord\Model { // order belongs to a person public static array $belongs_to = [ - ['person']]; + 'person' => true + ]; // order can have many payments by many people // the conditions is just there as an example as it makes no logical sense - public static $has_many = [ - ['payments'], - ['people', + public static array $has_many = [ + 'payments' => true, + 'people' => [ 'through' => 'payments', 'select' => 'people.*, payments.amount', - 'conditions' => 'payments.amount < 200']]; + 'conditions' => 'payments.amount < 200' + ] + ]; // order must have a price and tax > 0 public static array $validates_numericality_of = [ diff --git a/examples/orders/models/Payment.php b/examples/orders/models/Payment.php index 80bd6387..6dc60d92 100644 --- a/examples/orders/models/Payment.php +++ b/examples/orders/models/Payment.php @@ -4,6 +4,7 @@ class Payment extends ActiveRecord\Model { // payment belongs to a person public static array $belongs_to = [ - ['person'], - ['order']]; + 'person' => true, + 'order' => true + ]; } diff --git a/examples/orders/models/Person.php b/examples/orders/models/Person.php index ac269783..c74fe7cb 100644 --- a/examples/orders/models/Person.php +++ b/examples/orders/models/Person.php @@ -3,9 +3,10 @@ class Person extends ActiveRecord\Model { // a person can have many orders and payments - public static $has_many = [ - ['orders'], - ['payments']]; + public static array $has_many = [ + 'orders' => true, + 'payments'=> true + ]; // must have a name and a state public static array $validates_presence_of = [ diff --git a/lib/Model.php b/lib/Model.php index fde5b4fa..bde26f2e 100644 --- a/lib/Model.php +++ b/lib/Model.php @@ -14,6 +14,7 @@ use ActiveRecord\Exception\UndefinedPropertyException; use ActiveRecord\Relationship\AbstractRelationship; use ActiveRecord\Relationship\HasAndBelongsToMany; +use ActiveRecord\Relationship\HasMany; use ActiveRecord\Serialize\JsonSerializer; use ActiveRecord\Serialize\Serialization; @@ -39,14 +40,20 @@ * * ```php * class Person extends ActiveRecord\Model { - * static array $belongs_to = array( - * array('parent', 'foreign_key' => 'parent_id', 'class_name' => 'Person') - * ); + * static array $belongs_to = [ + * 'parent' => [ + * 'foreign_key' => 'parent_id', + * 'class_name' => 'Person' + * ] + * ]; * - * static $has_many = array( - * array('children', 'foreign_key' => 'parent_id', 'class_name' => 'Person'), - * array('orders') - * ); + * static array $has_many = [ + * 'children' => [ + * 'foreign_key' => 'parent_id', + * 'class_name' => 'Person' + * ], + * 'orders' => true + * ]; * * static $validates_length_of = [ * 'first_name' => ['within' => [1,50]], @@ -56,7 +63,7 @@ * * class Order extends ActiveRecord\Model { * static array $belongs_to = [ - * 'person' + * 'person' => true * ]; * * static $validates_numericality_of = [ @@ -75,6 +82,8 @@ * For a more in-depth look at defining models, relationships, callbacks and many other things * please consult our {@link http://www.phpactiverecord.org/guides Guides}. * + * @phpstan-import-type HasManyOptions from Types + * @phpstan-import-type BelongsToOptions from Types * @phpstan-import-type SerializeOptions from Serialize\Serialization * @phpstan-import-type ValidationOptions from Validations * @phpstan-import-type ValidateInclusionOptions from Validations @@ -190,12 +199,12 @@ class Model public static array $validates_format_of; /** - * @var ValidateInclusionOptions + * @var array */ public static array $validates_inclusion_of; /** - * @var ValidateInclusionOptions + * @var array */ public static array $validates_exclusion_of; @@ -214,6 +223,16 @@ class Model */ public static array $validates_length_of; + /** + * @var array + */ + public static array $has_many; + + /** + * @var array + */ + public static array $belongs_to; + /** * Allows you to create aliases for attributes. * @@ -272,8 +291,11 @@ class Model * * ``` * class Person extends ActiveRecord\Model { - * static array $belongs_to = array(array('venue'),array('host')); - * static $delegate = array( + * static array $belongs_to = [ + * 'venue' => true, + * 'host' => true + * ]; + * static $delegate = array( * array('name', 'state', 'to' => 'venue'), * array('name', 'to' => 'host', 'prefix' => 'woot')); * } @@ -1722,7 +1744,6 @@ public static function last(/* ... */) * "all" static[] User::find("all", ["name"=>"Stephen"] * ...int|string static[] User::find(1, 3, 5, 8); * array static[] User::find([1,3,5,8]); - * array<"conditions", array> static[] User::find(["conditions"=>["name"=>"Kurt"]]); */ public static function find(/* $type, $options */): static|array|null { diff --git a/lib/PhpStan/FindDynamicMethodReturnTypeReflection.php b/lib/PhpStan/FindDynamicMethodReturnTypeReflection.php index 3f6751bc..b4e3965f 100644 --- a/lib/PhpStan/FindDynamicMethodReturnTypeReflection.php +++ b/lib/PhpStan/FindDynamicMethodReturnTypeReflection.php @@ -48,8 +48,7 @@ public function getTypeFromStaticMethodCall(MethodReflection $methodReflection, if (1 == $numArgs) { if (!($args[0] instanceof ConstantArrayType) - || ('conditions' != $args[0]->getKeyTypes()[0]->getValue() - && !$this->isNumericArray($args[0]))) { + || (!$this->isNumericArray($args[0]))) { $single = true; } } elseif ($numArgs > 1) { diff --git a/lib/Relationship/AbstractRelationship.php b/lib/Relationship/AbstractRelationship.php index f218f779..3eddbfdf 100644 --- a/lib/Relationship/AbstractRelationship.php +++ b/lib/Relationship/AbstractRelationship.php @@ -71,9 +71,9 @@ abstract class AbstractRelationship * * @param array $options Options for the relationship (see {@link valid_association_options}) */ - public function __construct($options = []) + public function __construct(string $attribute_name, $options = []) { - $this->attribute_name = $options[0]; + $this->attribute_name = $attribute_name; $this->options = $this->merge_association_options($options); $relationship = strtolower(denamespace(get_called_class())); diff --git a/lib/Relationship/BelongsTo.php b/lib/Relationship/BelongsTo.php index 676b9a27..3a2af949 100644 --- a/lib/Relationship/BelongsTo.php +++ b/lib/Relationship/BelongsTo.php @@ -5,6 +5,7 @@ use ActiveRecord\Inflector; use ActiveRecord\Model; use ActiveRecord\Table; +use ActiveRecord\Types; /** * Belongs to relationship. @@ -13,9 +14,9 @@ * class School extends ActiveRecord\Model {} * * class Person extends ActiveRecord\Model { - * static array $belongs_to = array( - * array('school') - * ); + * static array $belongs_to = [ + * 'school' => true + * ]; * } * ``` * @@ -25,16 +26,18 @@ * class School extends ActiveRecord\Model {} * * class Person extends ActiveRecord\Model { - * static array $belongs_to = array( - * array('school', 'primary_key' => 'school_id') - * ); + * static array $belongs_to = [ + * 'school' => [ + * 'primary_key' => 'school_id' + * ] + * ] * } * ``` * + * @phpstan-import-type BelongsToOptions from Types * @phpstan-import-type Attributes from Model * * @see valid_association_options - * @see http://www.phpactiverecord.org/guides/associations */ class BelongsTo extends AbstractRelationship { @@ -55,9 +58,9 @@ public function primary_key(): array return $this->primary_key; } - public function __construct($options = []) + public function __construct(string $attributeName, $options = []) { - parent::__construct($options); + parent::__construct($attributeName, $options); if (!$this->class_name) { $this->set_inferred_class_name(); diff --git a/lib/Relationship/HasAndBelongsToMany.php b/lib/Relationship/HasAndBelongsToMany.php index b054ecae..44811975 100644 --- a/lib/Relationship/HasAndBelongsToMany.php +++ b/lib/Relationship/HasAndBelongsToMany.php @@ -23,7 +23,7 @@ public function __construct($options = []) * uniq - if true duplicate assoc objects will be ignored * validate */ - parent::__construct($options); + parent::__construct($options[0], $options); } public function load(Model $model): mixed diff --git a/lib/Relationship/HasMany.php b/lib/Relationship/HasMany.php index 92ccac82..4b1d1d00 100644 --- a/lib/Relationship/HasMany.php +++ b/lib/Relationship/HasMany.php @@ -6,6 +6,7 @@ use ActiveRecord\Inflector; use ActiveRecord\Model; use ActiveRecord\Table; +use ActiveRecord\Types; /** * One-to-many relationship. @@ -19,9 +20,9 @@ * # Table: schools * # Primary key: id * class School extends ActiveRecord\Model { - * static $has_many = array( - * array('people') - * ); + * static array $has_many = [ + * 'people' => true + * ]; * }); * ``` * @@ -29,33 +30,23 @@ * * ```php * class Payment extends ActiveRecord\Model { - * static array $belongs_to = array( - * array('person'), - * array('order') - * ); + * static array $belongs_to = [ + * 'person'=>true, + * 'order'=>true + * ]; * } * * class Order extends ActiveRecord\Model { - * static $has_many = array( - * [ - * 'people', + * static array $has_many = [ + * 'people' => [ * 'through' => 'payments', * 'select' => 'people.*, payments.amount', - * 'conditions' => 'payments.amount < 200') * ]; - * } + * ] * ``` * * @phpstan-import-type Attributes from Model - * - * @phpstan-type HasManyOptions array{ - * limit?: int, - * offset?: int, - * primary_key?: string|array, - * group?: string, - * order?: string, - * through?: string - * } + * @phpstan-import-type HasManyOptions from Types * * @see http://www.phpactiverecord.org/guides/associations * @see valid_association_options @@ -90,11 +81,11 @@ class HasMany extends AbstractRelationship /** * Constructs a {@link HasMany} relationship. * - * @param HasManyOptions $options Options for the association + * @param HasManyOptions $options */ - public function __construct(array $options = []) + public function __construct(string $attribute, array $options = []) { - parent::__construct($options); + parent::__construct($attribute, $options); if (isset($this->options['through'])) { $this->through = $this->options['through']; diff --git a/lib/Table.php b/lib/Table.php index 83e3b0e2..895f8a9d 100644 --- a/lib/Table.php +++ b/lib/Table.php @@ -580,21 +580,21 @@ private function set_associations(): void continue; } - foreach (wrap_values_in_arrays($definitions) as $definition) { + foreach (wrap_values_in_arrays($definitions) as $attribute => $definition) { $relationship = null; $definition += ['namespace' => $namespace]; switch ($name) { case 'has_many': - $relationship = new HasMany($definition); + $relationship = new HasMany($attribute, $definition); break; case 'has_one': - $relationship = new HasOne($definition); + $relationship = new HasOne($definition[0], $definition); break; case 'belongs_to': - $relationship = new BelongsTo($definition); + $relationship = new BelongsTo($attribute, $definition); break; case 'has_and_belongs_to_many': diff --git a/lib/Types.php b/lib/Types.php index 38b82cc8..4f946203 100644 --- a/lib/Types.php +++ b/lib/Types.php @@ -11,6 +11,20 @@ * order?: string, * set?: string|array * } + * @phpstan-type HasManyOptions array{ + * limit?: int, + * offset?: int, + * primary_key?: string|array, + * group?: string, + * order?: string, + * through?: string + * } + * @phpstan-type BelongsToOptions array{ + * conditions?: array, + * foreign_key?: string, + * class_name?: class-string, + * primary_key?: string + * } * @phpstan-type DelegateOptions array{ * to: string, * prefix?: string, diff --git a/test/ActiveRecordFindTest.php b/test/ActiveRecordFindTest.php index f4565410..a0859875 100644 --- a/test/ActiveRecordFindTest.php +++ b/test/ActiveRecordFindTest.php @@ -417,7 +417,9 @@ public function testFindWithSelectNonSelectedFieldsShouldNotHaveAttributes() public function testJoinsOnModelWithAssociationAndExplicitJoins() { - JoinBook::$belongs_to = [['author']]; + JoinBook::$belongs_to = [ + 'author' => true + ]; JoinBook::first(['joins' => ['author', 'LEFT JOIN authors a ON(books.secondary_author_id=a.author_id)']]); $this->assert_sql_has('INNER JOIN authors ON(books.author_id = authors.author_id)', JoinBook::table()->last_sql); $this->assert_sql_has('LEFT JOIN authors a ON(books.secondary_author_id=a.author_id)', JoinBook::table()->last_sql); diff --git a/test/RelationshipTest.php b/test/RelationshipTest.php index 16481834..56375a17 100644 --- a/test/RelationshipTest.php +++ b/test/RelationshipTest.php @@ -25,7 +25,11 @@ class AuthorWithNonModelRelationship extends ActiveRecord\Model { public static string $pk = 'id'; public static string $table_name = 'authors'; - public static array $has_many = [['books', 'class_name' => 'NotModel']]; + public static array $has_many = [ + 'books' => [ + 'class_name' => 'NotModel' + ] + ]; } class RelationshipTest extends DatabaseTestCase @@ -37,11 +41,26 @@ public function setUp($connection_name=null): void { parent::setUp($connection_name); - Event::$belongs_to = [['venue'], ['host']]; - Venue::$has_many = [['events', 'order' => 'id asc'], ['hosts', 'through' => 'events', 'order' => 'hosts.id asc']]; + Event::$belongs_to = [ + 'venue' => true, + 'host'=>true + ]; + Venue::$has_many = [ + 'events' => [ + 'order' => 'id asc' + ], + 'hosts' => [ + 'through' => 'events', + 'order' => 'hosts.id asc' + ] + ]; Venue::$has_one = []; Employee::$has_one = [['position']]; - Host::$has_many = [['events', 'order' => 'id asc']]; + Host::$has_many = [ + 'events' => [ + 'order' => 'id asc' + ] + ]; foreach ($this->relationship_names as $name) { if (preg_match("/$name/", $this->name(), $match)) { @@ -158,25 +177,35 @@ public function testBelongsToReturnsNullWhenForeignKeyIsNull() public function testBelongsToWithExplicitClassName() { - Event::$belongs_to = [['explicit_class_name', 'class_name' => 'Venue']]; + Event::$belongs_to = [ + 'explicit_class_name' => [ + 'class_name' => 'Venue' + ] + ]; $this->assert_default_belongs_to($this->get_relationship(), 'explicit_class_name'); } public function testBelongsToWithExplicitForeignKey() { - $old = Book::$belongs_to; - Book::$belongs_to = [['explicit_author', 'class_name' => 'Author', 'foreign_key' => 'secondary_author_id']]; + Book::$belongs_to = [ + 'explicit_author' => [ + 'class_name' => 'Author', + 'foreign_key' => 'secondary_author_id' + ] + ]; $book = Book::find(1); $this->assertEquals(2, $book->secondary_author_id); $this->assertEquals($book->secondary_author_id, $book->explicit_author->author_id); - - Book::$belongs_to = $old; } public function testBelongsToWithSelect() { - Event::$belongs_to[0]['select'] = 'id, city'; + Event::$belongs_to = [ + 'venue' => [ + 'select' => 'id, city' + ] + ]; $event = $this->get_relationship(); $this->assert_default_belongs_to($event); @@ -190,7 +219,11 @@ public function testBelongsToWithSelect() public function testBelongsToWithReadonly() { - Event::$belongs_to[0]['readonly'] = true; + Event::$belongs_to = [ + 'venue' => [ + 'readonly' => true + ] + ]; $event = $this->get_relationship(); $this->assert_default_belongs_to($event); @@ -206,13 +239,21 @@ public function testBelongsToWithReadonly() public function testBelongsToWithPluralAttributeName() { - Event::$belongs_to = [['venues', 'class_name' => 'Venue']]; + Event::$belongs_to = [ + 'venues' => [ + 'class_name' => 'Venue' + ] + ]; $this->assert_default_belongs_to($this->get_relationship(), 'venues'); } public function testBelongsToWithConditionsAndNonQualifyingRecord() { - Event::$belongs_to[0]['conditions'] = "state = 'NY'"; + Event::$belongs_to = [ + 'venue' => [ + 'conditions' => "state = 'NY'" + ] + ]; $event = $this->get_relationship(); $this->assertEquals(5, $event->id); $this->assertNull($event->venue); @@ -220,7 +261,11 @@ public function testBelongsToWithConditionsAndNonQualifyingRecord() public function testBelongsToWithConditionsAndQualifyingRecord() { - Event::$belongs_to[0]['conditions'] = "state = 'PA'"; + Event::$belongs_to = [ + 'venue' => [ + 'conditions' => "state = 'PA'" + ] + ]; $this->assert_default_belongs_to($this->get_relationship()); } @@ -259,7 +304,12 @@ public function testBuildAssociationOverwritesGuardedForeignKeys() public function testBelongsToCanBeSelfReferential() { - Author::$belongs_to = [['parent_author', 'class_name' => 'Author', 'foreign_key' => 'parent_author_id']]; + Author::$belongs_to = [ + 'parent_author' => [ + 'class_name' => 'Author', + 'foreign_key' => 'parent_author_id' + ] + ]; $author = Author::find(1); $this->assertEquals(1, $author->id); $this->assertEquals(3, $author->parent_author->id); @@ -267,20 +317,33 @@ public function testBelongsToCanBeSelfReferential() public function testBelongsToWithAnInvalidOption() { - Event::$belongs_to[0]['joins'] = 'venue'; - $event = Event::first()->venue; + Event::$belongs_to = [ + 'host' => [ + 'joins' => 'venue' + ] + ]; $this->assert_sql_doesnt_has('INNER JOIN venues ON(events.venue_id = venues.id)', Event::table()->last_sql); } public function testHasManyWithExplicitClassName() { - Venue::$has_many = [['explicit_class_name', 'class_name' => 'Event', 'order' => 'id asc']]; + Venue::$has_many = [ + 'explicit_class_name' => [ + 'class_name' => 'Event', + 'order' => 'id asc' + ] + ]; $this->assert_default_has_many($this->get_relationship(), 'explicit_class_name'); } public function testHasManyWithSelect() { - Venue::$has_many[0]['select'] = 'title, type'; + Venue::$has_many = [ + 'events' => [ + 'select' => 'title, type' + ] + ]; + $venue = $this->get_relationship(); $this->assert_default_has_many($venue); @@ -294,7 +357,11 @@ public function testHasManyWithSelect() public function testHasManyWithReadonly() { - Venue::$has_many[0]['readonly'] = true; + Venue::$has_many = [ + 'events' => [ + 'readonly' => true + ] + ]; $venue = $this->get_relationship(); $this->assert_default_has_many($venue); @@ -310,21 +377,22 @@ public function testHasManyWithReadonly() public function testHasManyWithSingularAttributeName() { - Venue::$has_many = [['event', 'class_name' => 'Event', 'order' => 'id asc']]; + Venue::$has_many = [ + 'event' => [ + 'class_name' => 'Event', + 'order' => 'id asc' + ] + ]; $this->assert_default_has_many($this->get_relationship(), 'event'); } - public function testHasManyWithConditionsAndNonQualifyingRecord() - { - Venue::$has_many[0]['conditions'] = "title = 'pr0n @ railsconf'"; - $venue = $this->get_relationship(); - $this->assertEquals(2, $venue->id); - $this->assertTrue(empty($venue->events), is_array($venue->events)); - } - public function testHasManyWithConditionsAndQualifyingRecord() { - Venue::$has_many[0]['conditions'] = "title = 'Yeah Yeah Yeahs'"; + Venue::$has_many = [ + 'events' => [ + 'conditions' => "title = 'Yeah Yeah Yeahs'" + ] + ]; $venue = $this->get_relationship(); $this->assertEquals(2, $venue->id); $this->assertEquals($venue->events[0]->title, 'Yeah Yeah Yeahs'); @@ -332,11 +400,15 @@ public function testHasManyWithConditionsAndQualifyingRecord() public function testHasManyWithSqlClauseOptions() { - Venue::$has_many[0] = ['events', - 'select' => 'type', - 'group' => 'type', - 'limit' => 2, - 'offset' => 1]; + Venue::$has_many = [ + 'events' => [ + 'select' => 'type', + 'group' => 'type', + 'limit' => 2, + 'offset' => 1 + ] + ]; + Venue::first()->events; $this->assert_sql_has($this->connection->limit('SELECT type FROM events WHERE venue_id=? GROUP BY type', 1, 2), Event::table()->last_sql); } @@ -370,8 +442,14 @@ public function testGh16HasManyThroughInsideALoopShouldNotCauseAnException() public function testHasManyThroughNoAssociation() { $this->expectException(HasManyThroughAssociationException::class); - Event::$belongs_to = [['host']]; - Venue::$has_many[1] = ['hosts', 'through' => 'blahhhhhhh']; + Event::$belongs_to = [ + 'host' => true + ]; + Venue::$has_many = [ + 'hosts' => [ + 'through' => 'blahhhhhhh' + ] + ]; $venue = $this->get_relationship(); $n = $venue->hosts; @@ -380,8 +458,15 @@ public function testHasManyThroughNoAssociation() public function testHasManyThroughWithSelect() { - Event::$belongs_to = [['host']]; - Venue::$has_many[1] = ['hosts', 'through' => 'events', 'select' => 'hosts.*, events.*']; + Event::$belongs_to = [ + 'host' => true + ]; + Venue::$has_many = [ + 'hosts' => [ + 'through' => 'events', + 'select' => 'hosts.*, events.*' + ] + ]; $venue = $this->get_relationship(); $this->assertTrue(count($venue->hosts) > 0); @@ -390,8 +475,18 @@ public function testHasManyThroughWithSelect() public function testHasManyThroughWithConditions() { - Event::$belongs_to = [['host']]; - Venue::$has_many[1] = ['hosts', 'through' => 'events', 'conditions' => ['events.title != ?', 'Love Overboard']]; + Event::$belongs_to = [ + 'host' => true + ]; + Venue::$has_many = [ + 'hosts' => [ + 'through' => 'events', + 'conditions' => [ + 'events.title != ?', + 'Love Overboard' + ] + ] + ]; $venue = $this->get_relationship(); $this->assertTrue(1 === count($venue->hosts)); @@ -400,8 +495,16 @@ public function testHasManyThroughWithConditions() public function testHasManyThroughUsingSource() { - Event::$belongs_to = [['host']]; - Venue::$has_many[1] = ['hostess', 'through' => 'events', 'source' => 'host']; + Event::$belongs_to = [ + 'host' => true + ]; + + Venue::$has_many = [ + 'hostess' => [ + 'through' => 'events', + 'source' => 'host' + ] + ]; $venue = $this->get_relationship(); $this->assertTrue(count($venue->hostess) > 0); @@ -410,9 +513,15 @@ public function testHasManyThroughUsingSource() public function testHasManyThroughWithInvalidClassName() { $this->expectException(\ReflectionException::class); - Event::$belongs_to = [['host']]; + Event::$belongs_to = [ + 'host' => true + ]; Venue::$has_one = [['invalid_assoc']]; - Venue::$has_many[1] = ['hosts', 'through' => 'invalid_assoc']; + Venue::$has_many = [ + 'hosts' => [ + 'through' => 'invalid_assoc' + ] + ]; $this->get_relationship()->hosts; } @@ -425,8 +534,13 @@ public function testHasManyWithJoins() public function testHasManyWithExplicitKeys() { - $old = Author::$has_many; - Author::$has_many = [['explicit_books', 'class_name' => 'Book', 'primary_key' => 'parent_author_id', 'foreign_key' => 'secondary_author_id']]; + Author::$has_many = [ + 'explicit_books' => [ + 'class_name' => 'Book', + 'primary_key' => 'parent_author_id', + 'foreign_key' => 'secondary_author_id' + ] + ]; $author = Author::find(4); foreach ($author->explicit_books as $book) { @@ -434,7 +548,6 @@ public function testHasManyWithExplicitKeys() } $this->assertTrue(false !== strpos(ActiveRecord\Table::load(Book::class)->last_sql, 'secondary_author_id')); - Author::$has_many = $old; } public function testHasOneBasic() @@ -537,7 +650,12 @@ public function testRelationshipOnTableWithUnderscores() public function testHasOneThrough() { - Venue::$has_many = [['events'], ['hosts', 'through' => 'events']]; + Venue::$has_many = [ + 'events' => true, + 'hosts' => [ + 'through' => 'events' + ] + ]; $venue = Venue::first(); $this->assertTrue(count($venue->hosts) > 0); } @@ -550,7 +668,15 @@ public function testThrowErrorIfRelationshipIsNotAModel() public function testGh93AndGh100EagerLoadingRespectsAssociationOptions() { - Venue::$has_many = [['events', 'class_name' => 'Event', 'order' => 'id asc', 'conditions' => ['length(title) = ?', 14]]]; + Venue::$has_many = [ + 'events' => [ + 'class_name' => 'Event', + 'order' => 'id asc', + 'conditions' => [ + 'length(title) = ?', 14 + ] + ] + ]; $venues = Venue::find([2, 6], ['include' => 'events']); $this->assert_sql_has('WHERE length(title) = ? AND venue_id IN(?,?) ORDER BY id asc', ActiveRecord\Table::load(Event::class)->last_sql); @@ -583,7 +709,10 @@ public function testEagerLoadingHasManyWithNoRelatedRows() public function testEagerLoadingHasManyArrayOfIncludes() { - Author::$has_many = [['books'], ['awesome_people']]; + Author::$has_many = [ + 'books' => true, + 'awesome_people' => true + ]; $authors = Author::find([1, 2], ['include' => ['books', 'awesome_people']]); $assocs = ['books', 'awesome_people']; @@ -652,9 +781,20 @@ public function testEagerLoadingBelongsToArrayOfIncludes() public function testEagerLoadingBelongsToNested() { - Author::$has_many = [['awesome_people']]; + Author::$has_many = [ + 'awesome_people' => true, + ]; + Book::$belongs_to = [ + 'author' => true + ]; - $books = Book::find([1, 2], ['include' => ['author' => ['awesome_people']]]); + $books = Book::find([1, 2], [ + 'include' => [ + 'author' => [ + 'awesome_people' + ] + ] + ]); foreach ($books as $book) { $this->assertEquals($book->author_id, $book->author->author_id); @@ -708,11 +848,19 @@ public function testEagerLoadingClonesNestedRelatedObjects() public function testGh23RelationshipsWithJoinsToSameTableShouldAliasTableName() { - $old = Book::$belongs_to; Book::$belongs_to = [ - ['from_', 'class_name' => 'Author', 'foreign_key' => 'author_id'], - ['to', 'class_name' => 'Author', 'foreign_key' => 'secondary_author_id'], - ['another', 'class_name' => 'Author', 'foreign_key' => 'secondary_author_id'] + 'from_' => [ + 'class_name' => 'Author', + 'foreign_key' => 'author_id' + ], + 'to' => [ + 'class_name' => 'Author', + 'foreign_key' => 'secondary_author_id' + ], + 'another' => [ + 'class_name' => 'Author', + 'foreign_key' => 'secondary_author_id' + ] ]; $c = ActiveRecord\Table::load(Book::class)->conn; @@ -724,7 +872,6 @@ public function testGh23RelationshipsWithJoinsToSameTableShouldAliasTableName() $this->assertNotNull($book->from_author_name); $this->assertNotNull($book->to_author_name); $this->assertNotNull($book->another_author_name); - Book::$belongs_to = $old; } public function testGh40RelationshipsWithJoinsAliasesTableNameInConditions() diff --git a/test/SerializationTest.php b/test/SerializationTest.php index 27add6c5..9e723ed1 100644 --- a/test/SerializationTest.php +++ b/test/SerializationTest.php @@ -33,6 +33,10 @@ public function testOnlyNotArray() public function testOnlyShouldOnlyApplyToAttributes() { + Book::$belongs_to = [ + 'author' => true + ]; + $this->assertArrayHasKey('author', $this->_a(['only' => 'name', 'include' => 'author'])); $this->assertArrayHasKey('name', $this->_a(['only' => 'name', 'include' => 'author'])); $this->assertArrayHasKey('book_id', $this->_a(['only' => 'book_id', 'methods' => 'upper_name'])); diff --git a/test/helpers/foo.php b/test/helpers/foo.php index cffe2021..1850d78c 100644 --- a/test/helpers/foo.php +++ b/test/helpers/foo.php @@ -2,23 +2,29 @@ namespace foo\bar\biz; -class User extends \ActiveRecord\Model +use ActiveRecord\Model; + +class User extends Model { - public static $has_many = [ - ['user_newsletters'], - ['newsletters', 'through' => 'user_newsletters'] + public static array $has_many = [ + 'user_newsletters' => true, + 'newsletters' => [ + 'through' => 'user_newsletters' + ] ]; } -class Newsletter extends \ActiveRecord\Model +class Newsletter extends Model { - public static $has_many = [ - ['user_newsletters'], - ['users', 'through' => 'user_newsletters'], + public static array $has_many = [ + 'user_newsletters'=>true, + 'users' =>[ + 'through' => 'user_newsletters' + ], ]; } -class UserNewsletter extends \ActiveRecord\Model +class UserNewsletter extends Model { public static $belong_to = [ ['user'], diff --git a/test/models/Amenity.php b/test/models/Amenity.php index 7abc0f3f..ac2281bb 100644 --- a/test/models/Amenity.php +++ b/test/models/Amenity.php @@ -10,6 +10,6 @@ class Amenity extends Model public static string $primary_key = 'amenity_id'; public static array $has_many = [ - 'property_amenities' + 'property_amenities' => true ]; } diff --git a/test/models/Author.php b/test/models/Author.php index 00bce6dd..6a4757ad 100644 --- a/test/models/Author.php +++ b/test/models/Author.php @@ -9,7 +9,9 @@ class Author extends Model public static $pk = 'author_id'; // static $has_one = array(array('awesome_person', 'foreign_key' => 'author_id', 'primary_key' => 'author_id'), // array('parent_author', 'class_name' => 'Author', 'foreign_key' => 'parent_author_id')); - public static $has_many = ['books']; + public static array $has_many = [ + 'books' => true + ]; public static $has_one = [ ['awesome_person', 'foreign_key' => 'author_id', 'primary_key' => 'author_id'], ['parent_author', 'class_name' => 'Author', 'foreign_key' => 'parent_author_id']]; diff --git a/test/models/AuthorAttrAccessible.php b/test/models/AuthorAttrAccessible.php index ac8d4871..a1430f0e 100644 --- a/test/models/AuthorAttrAccessible.php +++ b/test/models/AuthorAttrAccessible.php @@ -8,8 +8,12 @@ class AuthorAttrAccessible extends Model { public static $pk = 'author_id'; public static string $table_name = 'authors'; - public static $has_many = [ - ['books', 'class_name' => 'BookAttrProtected', 'foreign_key' => 'author_id', 'primary_key' => 'book_id'] + public static array $has_many = [ + 'books' => [ + 'class_name' => 'BookAttrProtected', + 'foreign_key' => 'author_id', + 'primary_key' => 'book_id' + ] ]; public static $has_one = [ ['parent_author', 'class_name' => 'AuthorAttrAccessible', 'foreign_key' => 'parent_author_id', 'primary_key' => 'author_id'] diff --git a/test/models/AwesomePerson.php b/test/models/AwesomePerson.php index 0429d08b..3cd748b8 100644 --- a/test/models/AwesomePerson.php +++ b/test/models/AwesomePerson.php @@ -6,5 +6,7 @@ class AwesomePerson extends Model { - public static array $belongs_to = ['author']; + public static array $belongs_to = [ + 'author' => true + ]; } diff --git a/test/models/Book.php b/test/models/Book.php index 858a8e4c..c55ac0c4 100644 --- a/test/models/Book.php +++ b/test/models/Book.php @@ -6,7 +6,9 @@ class Book extends Model { - public static array $belongs_to = ['author']; + public static array $belongs_to = [ + 'author' => true + ]; public static $has_one = []; public function upper_name() diff --git a/test/models/BookAttrProtected.php b/test/models/BookAttrProtected.php index f2b639c6..3e187b6d 100644 --- a/test/models/BookAttrProtected.php +++ b/test/models/BookAttrProtected.php @@ -9,7 +9,10 @@ class BookAttrProtected extends Model // public static $pk = 'book_id'; public static string $table_name = 'books'; public static array $belongs_to = [ - ['author', 'class_name' => 'AuthorAttrAccessible', 'primary_key' => 'author_id'] + 'author' => [ + 'class_name' => 'AuthorAttrAccessible', + 'primary_key' => 'author_id' + ] ]; // No attributes should be accessible diff --git a/test/models/Event.php b/test/models/Event.php index 395f261f..71ebdc7a 100644 --- a/test/models/Event.php +++ b/test/models/Event.php @@ -7,8 +7,8 @@ class Event extends Model { public static array $belongs_to = [ - 'host', - 'venue' + 'host' => true, + 'venue' => true ]; public static array $delegate = [ diff --git a/test/models/Host.php b/test/models/Host.php index 2bd31e61..d440c258 100644 --- a/test/models/Host.php +++ b/test/models/Host.php @@ -6,8 +6,10 @@ class Host extends Model { - public static $has_many = [ - 'events', - ['venues', 'through' => 'events'] + public static array $has_many = [ + 'events' => true, + 'venues' => [ + 'through' => 'events' + ] ]; } diff --git a/test/models/Property.php b/test/models/Property.php index 2e48cfa5..acf6cbcb 100644 --- a/test/models/Property.php +++ b/test/models/Property.php @@ -9,8 +9,10 @@ class Property extends Model public static string $table_name = 'property'; public static string $primary_key = 'property_id'; - public static $has_many = [ - 'property_amenities', - ['amenities', 'through' => 'property_amenities'] + public static array $has_many = [ + 'property_amenities' => true, + 'amenities' => [ + 'through' => 'property_amenities' + ] ]; } diff --git a/test/models/PropertyAmenity.php b/test/models/PropertyAmenity.php index e26e1c6c..ddaab595 100644 --- a/test/models/PropertyAmenity.php +++ b/test/models/PropertyAmenity.php @@ -10,7 +10,7 @@ class PropertyAmenity extends Model public static string $primary_key = 'id'; public static array $belongs_to = [ - 'amenity', - 'property' + 'amenity' => true, + 'property' => true ]; } diff --git a/test/models/Venue.php b/test/models/Venue.php index 39cadd49..ad394ecd 100644 --- a/test/models/Venue.php +++ b/test/models/Venue.php @@ -10,8 +10,10 @@ class Venue extends Model public static bool $use_custom_set_state_setter = false; public static array $has_many = [ - 'events', - ['hosts', 'through' => 'events'] + 'events' => true, + 'hosts' => [ + 'through' => 'events' + ] ]; public static array $has_one; diff --git a/test/models/namespacetest/Book.php b/test/models/namespacetest/Book.php index 9314d262..3e634203 100644 --- a/test/models/namespacetest/Book.php +++ b/test/models/namespacetest/Book.php @@ -5,13 +5,23 @@ class Book extends \ActiveRecord\Model { public static array $belongs_to = [ - ['parent_book', 'class_name' => 'Book'], - ['parent_book_2', 'class_name' => '\test\models\namespacetest\Book'], - ['parent_book_3', 'class_name' => '\test\models\Book'], + 'parent_book' => [ + 'class_name' => 'Book' + ], + 'parent_book_2' => [ + 'class_name' => '\test\models\namespacetest\Book' + ], + 'parent_book_3' => [ + 'class_name' => '\test\models\Book' + ], ]; - public static $has_many = [ - ['pages', 'class_name' => '\test\models\namespacetest\subnamespacetest\Page'], - ['pages_2', 'class_name' => 'subnamespacetest\Page'], + public static array $has_many = [ + 'pages' => [ + 'class_name' => '\test\models\namespacetest\subnamespacetest\Page' + ], + 'pages_2' => [ + 'class_name' => 'subnamespacetest\Page' + ], ]; } diff --git a/test/phpstan/DynamicFInd.php b/test/phpstan/DynamicFInd.php index 2e88ded2..6549d4c8 100644 --- a/test/phpstan/DynamicFInd.php +++ b/test/phpstan/DynamicFInd.php @@ -42,6 +42,3 @@ $books = Book::find([1, 3, 8]); assert(0==count($books)); - -$books = Book::find(['conditions'=> ['name' => 'Kurt']]); -assert(0==count($books));