From 33254d5dad03009ecb64fe754bb52e6a247e21b6 Mon Sep 17 00:00:00 2001 From: Bizley Date: Thu, 12 Oct 2023 17:43:55 +0200 Subject: [PATCH 1/5] Update CHANGELOG.md 2.0.49.2 changelog --- framework/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index 35e8ebde9b7..e7a09902e16 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -1,7 +1,7 @@ Yii Framework 2 Change Log ========================== -2.0.50 under development +2.0.49.2 under development ------------------------ - Bug #19925: Improved PHP version check when handling MIME types (schmunk42) From 4f1735995ad1dfe5b8c51807d1e07ac1ee54a04d Mon Sep 17 00:00:00 2001 From: Bizley Date: Thu, 12 Oct 2023 17:46:26 +0200 Subject: [PATCH 2/5] release version 2.0.49.2 --- framework/BaseYii.php | 2 +- framework/CHANGELOG.md | 4 ++-- framework/helpers/mimeAliases.php | 3 +++ framework/helpers/mimeExtensions.php | 3 +++ framework/helpers/mimeTypes.php | 3 +++ 5 files changed, 12 insertions(+), 3 deletions(-) diff --git a/framework/BaseYii.php b/framework/BaseYii.php index 496f6aa121a..fe2301b0fdb 100644 --- a/framework/BaseYii.php +++ b/framework/BaseYii.php @@ -93,7 +93,7 @@ class BaseYii */ public static function getVersion() { - return '2.0.50-dev'; + return '2.0.49.2'; } /** diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index e7a09902e16..ecf64bb49a6 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -1,8 +1,8 @@ Yii Framework 2 Change Log ========================== -2.0.49.2 under development ------------------------- +2.0.49.2 October 12, 2023 +------------------------- - Bug #19925: Improved PHP version check when handling MIME types (schmunk42) diff --git a/framework/helpers/mimeAliases.php b/framework/helpers/mimeAliases.php index 4cd89888a77..a9e677adcbd 100644 --- a/framework/helpers/mimeAliases.php +++ b/framework/helpers/mimeAliases.php @@ -3,6 +3,9 @@ * MIME aliases. * * This file contains aliases for MIME types. + * + * All extra changes made to this file must be comitted to /build/controllers/MimeTypeController.php + * otherwise they will be lost on next build. */ return [ 'text/rtf' => 'application/rtf', diff --git a/framework/helpers/mimeExtensions.php b/framework/helpers/mimeExtensions.php index 946d61cd0c5..e4936030fd8 100644 --- a/framework/helpers/mimeExtensions.php +++ b/framework/helpers/mimeExtensions.php @@ -8,6 +8,9 @@ * Its content is generated from the apache http mime.types file. * https://svn.apache.org/viewvc/httpd/httpd/trunk/docs/conf/mime.types?view=markup * This file has been placed in the public domain for unlimited redistribution. + * + * All extra changes made to this file must be comitted to /build/controllers/MimeTypeController.php + * otherwise they will be lost on next build. */ return [ 'application/andrew-inset' => 'ez', diff --git a/framework/helpers/mimeTypes.php b/framework/helpers/mimeTypes.php index e91f80f95f8..f895e8d0728 100644 --- a/framework/helpers/mimeTypes.php +++ b/framework/helpers/mimeTypes.php @@ -7,6 +7,9 @@ * Its content is generated from the apache http mime.types file. * https://svn.apache.org/viewvc/httpd/httpd/trunk/docs/conf/mime.types?view=markup * This file has been placed in the public domain for unlimited redistribution. + * + * All extra changes made to this file must be comitted to /build/controllers/MimeTypeController.php + * otherwise they will be lost on next build. */ $mimeTypes = [ 123 => 'application/vnd.lotus-1-2-3', From 505fd5a2f827f99e34351045ace542676674fb77 Mon Sep 17 00:00:00 2001 From: Bizley Date: Thu, 12 Oct 2023 17:46:49 +0200 Subject: [PATCH 3/5] prepare for next release --- framework/BaseYii.php | 2 +- framework/CHANGELOG.md | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/framework/BaseYii.php b/framework/BaseYii.php index fe2301b0fdb..496f6aa121a 100644 --- a/framework/BaseYii.php +++ b/framework/BaseYii.php @@ -93,7 +93,7 @@ class BaseYii */ public static function getVersion() { - return '2.0.49.2'; + return '2.0.50-dev'; } /** diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index ecf64bb49a6..a2540e5d7f1 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -1,6 +1,12 @@ Yii Framework 2 Change Log ========================== +2.0.50 under development +------------------------ + +- no changes in this release. + + 2.0.49.2 October 12, 2023 ------------------------- From 02ed8080564339c95e9e2f489344c6551ee25758 Mon Sep 17 00:00:00 2001 From: PowerGamer1 Date: Thu, 13 Jul 2023 15:36:16 +0300 Subject: [PATCH 4/5] New methods: BaseActiveRecord::loadRelations() and BaseActiveRecord::loadRelationsFor(). --- framework/CHANGELOG.md | 2 +- framework/db/BaseActiveRecord.php | 53 +++++++++++++++++++++++++ tests/framework/db/ActiveRecordTest.php | 47 ++++++++++++++++++++++ 3 files changed, 101 insertions(+), 1 deletion(-) diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index a2540e5d7f1..a0269390530 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -4,7 +4,7 @@ Yii Framework 2 Change Log 2.0.50 under development ------------------------ -- no changes in this release. +- Enh #12743: Added new methods `BaseActiveRecord::loadRelations()` and `BaseActiveRecord::loadRelationsFor()` to eager load related models for existing primary model instances (PowerGamer1) 2.0.49.2 October 12, 2023 diff --git a/framework/db/BaseActiveRecord.php b/framework/db/BaseActiveRecord.php index 61cf3774094..ab5414416c5 100644 --- a/framework/db/BaseActiveRecord.php +++ b/framework/db/BaseActiveRecord.php @@ -1787,4 +1787,57 @@ private function isValueDifferent($newValue, $oldValue) return $newValue !== $oldValue; } + + /** + * Eager loads related models for the already loaded primary models. + * + * Helps to reduce the number of queries performed against database if some related models are only used + * when a specific condition is met. For example: + * + * ```php + * $customers = Customer::find()->where(['country_id' => 123])->all(); + * if (Yii:app()->getUser()->getIdentity()->canAccessOrders()) { + * Customer::loadRelationsFor($customers, 'orders.items'); + * } + * ``` + * + * @param array|ActiveRecordInterface[] $models array of primary models. Each model should have the same type and can be: + * - an active record instance; + * - active record instance represented by array (i.e. active record was loaded using [[ActiveQuery::asArray()]]). + * @param string|array $relationNames the names of the relations of primary models to be loaded from database. See [[ActiveQueryInterface::with()]] on how to specify this argument. + * @param bool $asArray whether to load each related model as an array or an object (if the relation itself does not specify that). + * @since 2.0.49 + */ + public static function loadRelationsFor(&$models, $relationNames, $asArray = false) + { + // ActiveQueryTrait::findWith() called below assumes $models array is non-empty. + if (empty($models)) { + return; + } + + static::find()->asArray($asArray)->findWith((array)$relationNames, $models); + } + + /** + * Eager loads related models for the already loaded primary model. + * + * Helps to reduce the number of queries performed against database if some related models are only used + * when a specific condition is met. For example: + * + * ```php + * $customer = Customer::find()->where(['id' => 123])->one(); + * if (Yii:app()->getUser()->getIdentity()->canAccessOrders()) { + * $customer->loadRelations('orders.items'); + * } + * ``` + * + * @param string|array $relationNames the names of the relations of this model to be loaded from database. See [[ActiveQueryInterface::with()]] on how to specify this argument. + * @param bool $asArray whether to load each relation as an array or an object (if the relation itself does not specify that). + * @since 2.0.49 + */ + public function loadRelations($relationNames, $asArray = false) + { + $models = [$this]; + static::loadRelationsFor($models, $relationNames, $asArray); + } } diff --git a/tests/framework/db/ActiveRecordTest.php b/tests/framework/db/ActiveRecordTest.php index b74803b94dd..e50cca3e024 100644 --- a/tests/framework/db/ActiveRecordTest.php +++ b/tests/framework/db/ActiveRecordTest.php @@ -2225,6 +2225,53 @@ public function testGetAttributeLabel($model) $attr = 'model2.doesNotExist.attr1'; $this->assertEquals($model->generateAttributeLabel($attr), $model->getAttributeLabel($attr)); } + + public function testLoadRelations() + { + // Test eager loading relations for multiple primary models using loadRelationsFor(). + /** @var Customer[] $customers */ + $customers = Customer::find()->all(); + Customer::loadRelationsFor($customers, ['orders.items']); + foreach ($customers as $customer) { + $this->assertTrue($customer->isRelationPopulated('orders')); + foreach ($customer->orders as $order) { + $this->assertTrue($order->isRelationPopulated('items')); + } + } + + // Test eager loading relations as arrays. + /** @var array $customers */ + $customers = Customer::find()->asArray(true)->all(); + Customer::loadRelationsFor($customers, ['orders.items' => function ($query) { $query->asArray(false); }], true); + foreach ($customers as $customer) { + $this->assertTrue(isset($customer['orders'])); + $this->assertTrue(is_array($customer['orders'])); + foreach ($customer['orders'] as $order) { + $this->assertTrue(is_array($order)); + $this->assertTrue(isset($order['items'])); + $this->assertTrue(is_array($order['items'])); + foreach ($order['items'] as $item) { + $this->assertFalse(is_array($item)); + } + } + } + + // Test eager loading relations for a single primary model using loadRelations(). + /** @var Customer $customer */ + $customer = Customer::find()->where(['id' => 1])->one(); + $customer->loadRelations('orders.items'); + $this->assertTrue($customer->isRelationPopulated('orders')); + foreach ($customer->orders as $order) { + $this->assertTrue($order->isRelationPopulated('items')); + } + + // Test eager loading previously loaded relation (relation value should be replaced with a new value loaded from database). + /** @var Customer $customer */ + $customer = Customer::find()->where(['id' => 2])->with(['orders' => function ($query) { $query->orderBy(['id' => SORT_ASC]); }])->one(); + $this->assertTrue($customer->orders[0]->id < $customer->orders[1]->id, 'Related models should be sorted by ID in ascending order.'); + $customer->loadRelations(['orders' => function ($query) { $query->orderBy(['id' => SORT_DESC]); }]); + $this->assertTrue($customer->orders[0]->id > $customer->orders[1]->id, 'Related models should be sorted by ID in descending order.'); + } } class LabelTestModel1 extends \yii\db\ActiveRecord From 9875ae6445b61bc117ae319bf00564f276c06663 Mon Sep 17 00:00:00 2001 From: Brad Bell Date: Fri, 13 Oct 2023 10:26:42 -0700 Subject: [PATCH 5/5] Fixed a bug where the yii serve command would break if a custom router was supplied and it had a space in the path --- framework/console/controllers/ServeController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/console/controllers/ServeController.php b/framework/console/controllers/ServeController.php index 68a7e50c286..d02c982042e 100644 --- a/framework/console/controllers/ServeController.php +++ b/framework/console/controllers/ServeController.php @@ -80,7 +80,7 @@ public function actionIndex($address = 'localhost') } $this->stdout("Quit the server with CTRL-C or COMMAND-C.\n"); - passthru('"' . PHP_BINARY . '"' . " -S {$address} -t \"{$documentRoot}\" $router"); + passthru('"' . PHP_BINARY . '"' . " -S {$address} -t \"{$documentRoot}\" \"$router\""); } /**