Commit c9b3f505 by Nobuo Kihara

docs/guide-ja/db-active-record.md - WIP [ci skip]

parent 2b2c43df
...@@ -331,72 +331,68 @@ $customer->loadDefaultValues(); ...@@ -331,72 +331,68 @@ $customer->loadDefaultValues();
// ... $customer の HTML フォームを表示する ... // ... $customer の HTML フォームを表示する ...
``` ```
If you want to set some initial values for the attributes yourself you can override the `init()` method 属性に対して何かの初期値を自分自身で設定したい場合は、アクティブレコードクラスの `init()` メソッドをオーバーライドして、そこで値を設定することが出来ます。
of the active record class and set the values there. For example to set the default value for the `status` attribute: 例えば、`status` 属性のデフォルト値を設定したい場合は、
```php ```php
public function init() public function init()
{ {
parent::init(); parent::init();
$this->status = 'active'; $this->status = self::STATUS_ACTIVE;
} }
``` ```
Active Record Life Cycles アクティブレコードのライフサイクル
------------------------- ----------------------------------
It is important to understand the life cycles of Active Record when it is used to manipulate data in database. アクティブレコードがデータベースのデータの操作に使われるときのライフサイクルを理解しておくことは重要なことです。
These life cycles are typically associated with corresponding events which allow you to inject code そのライフサイクルは、概して、対応するイベントと関連付けられており、それらのイベントに対して干渉したり反応したりするコードを注入できるようになっています。
to intercept or respond to these events. They are especially useful for developing Active Record [behaviors](concept-behaviors.md). これらのイベントは特にアクティブレコードの [ビヘイビア](concept-behaviors.md) を開発するときに役に立ちます。
When instantiating a new Active Record instance, we will have the following life cycles: アクティブレコードの新しいインスタンスを作成する場合は、次のライフサイクルを経ます。
1. constructor 1. コンストラクタ
2. [[yii\db\ActiveRecord::init()|init()]]: will trigger an [[yii\db\ActiveRecord::EVENT_INIT|EVENT_INIT]] event 2. [[yii\db\ActiveRecord::init()|init()]]: [[yii\db\ActiveRecord::EVENT_INIT|EVENT_INIT]] イベントをトリガ
When querying data through the [[yii\db\ActiveRecord::find()|find()]] method, we will have the following life cycles [[yii\db\ActiveRecord::find()|find()]] メソッドによってデータを検索する場合は、新しくデータを投入されるアクティブレコードの全てが、それぞれ、次のライフサイクルを経ます。
for EVERY newly populated Active Record instance:
1. constructor 1. コンストラクタ
2. [[yii\db\ActiveRecord::init()|init()]]: will trigger an [[yii\db\ActiveRecord::EVENT_INIT|EVENT_INIT]] event 2. [[yii\db\ActiveRecord::init()|init()]]: [[yii\db\ActiveRecord::EVENT_INIT|EVENT_INIT]] イベントをトリガ
3. [[yii\db\ActiveRecord::afterFind()|afterFind()]]: will trigger an [[yii\db\ActiveRecord::EVENT_AFTER_FIND|EVENT_AFTER_FIND]] event 3. [[yii\db\ActiveRecord::afterFind()|afterFind()]]: [[yii\db\ActiveRecord::EVENT_AFTER_FIND|EVENT_AFTER_FIND]] イベントをトリガ
When calling [[yii\db\ActiveRecord::save()|save()]] to insert or update an ActiveRecord, we will have [[yii\db\ActiveRecord::save()|save()]] を呼んで、アクティブレコードを挿入または更新する場合は、次のライフサイクルを経ます。
the following life cycles:
1. [[yii\db\ActiveRecord::beforeValidate()|beforeValidate()]]: will trigger an [[yii\db\ActiveRecord::EVENT_BEFORE_VALIDATE|EVENT_BEFORE_VALIDATE]] event 1. [[yii\db\ActiveRecord::beforeValidate()|beforeValidate()]]: [[yii\db\ActiveRecord::EVENT_BEFORE_VALIDATE|EVENT_BEFORE_VALIDATE]] イベントをトリガ
2. [[yii\db\ActiveRecord::afterValidate()|afterValidate()]]: will trigger an [[yii\db\ActiveRecord::EVENT_AFTER_VALIDATE|EVENT_AFTER_VALIDATE]] event 2. [[yii\db\ActiveRecord::afterValidate()|afterValidate()]]: [[yii\db\ActiveRecord::EVENT_AFTER_VALIDATE|EVENT_AFTER_VALIDATE]] イベントをトリガ
3. [[yii\db\ActiveRecord::beforeSave()|beforeSave()]]: will trigger an [[yii\db\ActiveRecord::EVENT_BEFORE_INSERT|EVENT_BEFORE_INSERT]] or [[yii\db\ActiveRecord::EVENT_BEFORE_UPDATE|EVENT_BEFORE_UPDATE]] event 3. [[yii\db\ActiveRecord::beforeSave()|beforeSave()]]: [[yii\db\ActiveRecord::EVENT_BEFORE_INSERT|EVENT_BEFORE_INSERT]] または [[yii\db\ActiveRecord::EVENT_BEFORE_UPDATE|EVENT_BEFORE_UPDATE]] イベントをトリガ
4. perform the actual data insertion or updating 4. 実際のデータ挿入または更新を実行
5. [[yii\db\ActiveRecord::afterSave()|afterSave()]]: will trigger an [[yii\db\ActiveRecord::EVENT_AFTER_INSERT|EVENT_AFTER_INSERT]] or [[yii\db\ActiveRecord::EVENT_AFTER_UPDATE|EVENT_AFTER_UPDATE]] event 5. [[yii\db\ActiveRecord::afterSave()|afterSave()]]: [[yii\db\ActiveRecord::EVENT_AFTER_INSERT|EVENT_AFTER_INSERT]] または [[yii\db\ActiveRecord::EVENT_AFTER_UPDATE|EVENT_AFTER_UPDATE]] イベントをトリガ
And finally, when calling [[yii\db\ActiveRecord::delete()|delete()]] to delete an ActiveRecord, we will have 最後に、[[yii\db\ActiveRecord::delete()|delete()]] を呼んで、アクティブレコードを削除する場合は、次のライフサイクルを経ます。
the following life cycles:
1. [[yii\db\ActiveRecord::beforeDelete()|beforeDelete()]]: will trigger an [[yii\db\ActiveRecord::EVENT_BEFORE_DELETE|EVENT_BEFORE_DELETE]] event 1. [[yii\db\ActiveRecord::beforeDelete()|beforeDelete()]]: [[yii\db\ActiveRecord::EVENT_BEFORE_DELETE|EVENT_BEFORE_DELETE]] イベントをトリガ
2. perform the actual data deletion 2. 実際のデータ削除を実行
3. [[yii\db\ActiveRecord::afterDelete()|afterDelete()]]: will trigger an [[yii\db\ActiveRecord::EVENT_AFTER_DELETE|EVENT_AFTER_DELETE]] event 3. [[yii\db\ActiveRecord::afterDelete()|afterDelete()]]: [[yii\db\ActiveRecord::EVENT_AFTER_DELETE|EVENT_AFTER_DELETE]] イベントをトリガ
Working with Relational Data リレーショナルデータを扱う
---------------------------- --------------------------
You can use ActiveRecord to also query a table's relational data (i.e., selection of data from Table A can also pull テーブルのリレーショナルデータもアクティブレコードを使ってクエリすることが出来ます
in related data from Table B). Thanks to ActiveRecord, the relational data returned can be accessed like a property (すなわち、テーブル A のデータを選択すると、テーブル B の関連付けられたデータも一緒に取り込むことが出来ます)。
of the ActiveRecord object associated with the primary table. アクティブレコードのおかげで、返されるリレーショナルデータは、プライマリテーブルと関連付けられたアクティブレコードオブジェクトのプロパティのようにアクセスすることが出来ます。
For example, with an appropriate relation declaration, by accessing `$customer->orders` you may obtain 例えば、適切なリレーションが宣言されていれば、`$customer->orders` にアクセスすることによって、指定された顧客が発行した注文を表す `Order` オブジェクトの配列を取得することが出来ます。
an array of `Order` objects which represent the orders placed by the specified customer.
To declare a relation, define a getter method which returns an [[yii\db\ActiveQuery]] object that has relation リレーションを宣言するためには、[[yii\db\ActiveQuery]] オブジェクトを返すゲッターメソッドを定義します。そして、その [[yii\db\ActiveQuery]] オブジェクトは、リレーションのコンテキストに関する情報を持ち、従って関連するレコードだけをクエリするものとします。
information about the relation context and thus will only query for related records. For example, 例えば、
```php ```php
class Customer extends \yii\db\ActiveRecord class Customer extends \yii\db\ActiveRecord
{ {
public function getOrders() public function getOrders()
{ {
// Customer has_many Order via Order.customer_id -> id // Customer は Order.customer_id -> id によって、複数の Order を持つ
return $this->hasMany(Order::className(), ['customer_id' => 'id']); return $this->hasMany(Order::className(), ['customer_id' => 'id']);
} }
} }
...@@ -405,47 +401,44 @@ class Order extends \yii\db\ActiveRecord ...@@ -405,47 +401,44 @@ class Order extends \yii\db\ActiveRecord
{ {
public function getCustomer() public function getCustomer()
{ {
// Order has_one Customer via Customer.id -> customer_id // Order は Customer.id -> customer_id によって、一つの Customer を持つ
return $this->hasOne(Customer::className(), ['id' => 'customer_id']); return $this->hasOne(Customer::className(), ['id' => 'customer_id']);
} }
} }
``` ```
The methods [[yii\db\ActiveRecord::hasMany()]] and [[yii\db\ActiveRecord::hasOne()]] used in the above 上記の例で使用されている [[yii\db\ActiveRecord::hasMany()]] と [[yii\db\ActiveRecord::hasOne()]] のメソッドは、リレーショナルデータベースにおける多対一と一対一の関係を表現するために使われます。
are used to model the many-one relationship and one-one relationship in a relational database. 例えば、顧客 (customer) は複数の注文 (order) を持ち、注文 (order) は一つの顧客 (customer)を持つ、という関係です。
For example, a customer has many orders, and an order has one customer. これらのメソッドはともに二つのパラメータを取り、[[yii\db\ActiveQuery]] オブジェクトを返します。
Both methods take two parameters and return an [[yii\db\ActiveQuery]] object:
- `$class`: the name of the class of the related model(s). This should be a fully qualified class name. - `$class`: 関連するモデルのクラス名。これは完全修飾のクラス名でなければなりません。
- `$link`: the association between columns from the two tables. This should be given as an array. - `$link`: 二つのテーブルに属するカラム間の関係。これは配列として与えられなければなりません。
The keys of the array are the names of the columns from the table associated with `$class`, 配列のキーは、`$class` と関連付けられるテーブルにあるカラムの名前であり、配列の値はリレーションを宣言しているクラスのテーブルにあるカラムの名前です。
while the values of the array are the names of the columns from the declaring class. リレーションをテーブルの外部キーに基づいて定義するのが望ましい慣行です。
It is a good practice to define relationships based on table foreign keys.
After declaring relations, getting relational data is as easy as accessing a component property リレーションを宣言した後は、リレーショナルデータを取得することは、対応するゲッターメソッドで定義されているコンポーネントのプロパティを取得するのと同じように、とても簡単なことになります。
that is defined by the corresponding getter method:
```php ```php
// get the orders of a customer // 顧客の注文を取得する
$customer = Customer::findOne(1); $customer = Customer::findOne(1);
$orders = $customer->orders; // $orders is an array of Order objects $orders = $customer->orders; // $orders は Order オブジェクトの配列
``` ```
Behind the scenes, the above code executes the following two SQL queries, one for each line of code: 舞台裏では、上記のコードは、各行について一つずつ、次の二つの SQL クエリを実行します。
```sql ```sql
SELECT * FROM customer WHERE id=1; SELECT * FROM customer WHERE id=1;
SELECT * FROM order WHERE customer_id=1; SELECT * FROM order WHERE customer_id=1;
``` ```
> Tip: If you access the expression `$customer->orders` again, it will not perform the second SQL query again. > Tip|情報: `$customer->orders` という式に再びアクセスした場合は、第二の SQL クエリはもう実行されません。
The SQL query is only performed the first time when this expression is accessed. Any further 第二の SQL クエリは、この式が最初にアクセスされた時だけ実行されます。
accesses will only return the previously fetched results that are cached internally. If you want to re-query 二度目以降のアクセスでは、内部的にキャッシュされている以前に読み出した結果が返されるだけです。
the relational data, simply unset the existing expression first: `unset($customer->orders);`. リレーショナルデータを再クエリしたい場合は、単純に、まず既存の式を未設定状態に戻して (`unset($customer->orders);`) から、再度、`$customer->orders` にアクセスします。
Sometimes, you may want to pass parameters to a relational query. For example, instead of returning 場合によっては、リレーショナルクエリにパラメータを渡したいことがあります。
all orders of a customer, you may want to return only big orders whose subtotal exceeds a specified amount. 例えば、顧客の注文を全て返す代りに、小計が指定した金額を超える大きな注文だけを返したいことがあるでしょう。
To do so, declare a `bigOrders` relation with the following getter method: そうするためには、次のようなゲッターメソッドで `bigOrders` リレーションを宣言します。
```php ```php
class Customer extends \yii\db\ActiveRecord class Customer extends \yii\db\ActiveRecord
...@@ -459,32 +452,28 @@ class Customer extends \yii\db\ActiveRecord ...@@ -459,32 +452,28 @@ class Customer extends \yii\db\ActiveRecord
} }
``` ```
Remember that `hasMany()` returns an [[yii\db\ActiveQuery]] object which allows you to customize the query by `hasMany()` が 返す [[yii\db\ActiveQuery]] は、[[yii\db\ActiveQuery]] のメソッドを呼ぶことでクエリをカスタマイズ出来るものであることを覚えておいてください。
calling the methods of [[yii\db\ActiveQuery]].
With the above declaration, if you access `$customer->bigOrders`, it will only return the orders 上記の宣言によって、`$customer->bigOrders` にアクセスした場合は、小計が 100 以上である注文だけが返されることになります。
whose subtotal is greater than 100. To specify a different threshold value, use the following code: 異なる閾値を指定するためには、次のコードを使用します。
```php ```php
$orders = $customer->getBigOrders(200)->all(); $orders = $customer->getBigOrders(200)->all();
``` ```
> Note: A relation method returns an instance of [[yii\db\ActiveQuery]]. If you access the relation like > Note|注意: リレーションメソッドは [[yii\db\ActiveQuery]] のインスタンスを返します。
an attribute (i.e. a class property), the return value will be the query result of the relation, which could be an instance of [[yii\db\ActiveRecord]], リレーションを属性 (すなわち、クラスのプロパティ) としてアクセスした場合は、返り値はリレーションのクエリ結果となります。
an array of that, or null, depending on the multiplicity of the relation. For example, `$customer->getOrders()` returns クエリ結果は、リレーションが複数のレコードを返すものか否かに応じて、[[yii\db\ActiveRecord]] の一つのインスタンス、またはその配列、または null となります。
an `ActiveQuery` instance, while `$customer->orders` returns an array of `Order` objects (or an empty array if 例えば、`$customer->getOrders()``ActiveQuery` のインスタンスを返し、`$customer->orders``Order` オブジェクトの配列 (またはクエリ結果が無い場合は空の配列) を返します。
the query results in nothing).
Relations with Junction Table 連結テーブルを使うリレーション
----------------------------- ------------------------------
Sometimes, two tables are related together via an intermediary table called a [junction table][]. To declare such relations, 場合によっては、二つのテーブルが [連結テーブル][] と呼ばれる中間的なテーブルによって関連付けられていることがあります。
we can customize the [[yii\db\ActiveQuery]] object by calling its [[yii\db\ActiveQuery::via()|via()]] or そのようなリレーションを宣言するために、[[yii\db\ActiveQuery::via()|via()]] または [[yii\db\ActiveQuery::viaTable()|viaTable()]] メソッドを呼んで、[[yii\db\ActiveQuery]] オブジェクトをカスタマイズすることが出来ます。
[[yii\db\ActiveQuery::viaTable()|viaTable()]] method.
For example, if table `order` and table `item` are related via the junction table `order_item`, 例えば、テーブル `order` とテーブル `item` が連結テーブル `order_item` によって関連付けられている場合、`Order` クラスにおいて `items` リレーションを次のように宣言することが出来ます。
we can declare the `items` relation in the `Order` class like the following:
```php ```php
class Order extends \yii\db\ActiveRecord class Order extends \yii\db\ActiveRecord
...@@ -497,9 +486,8 @@ class Order extends \yii\db\ActiveRecord ...@@ -497,9 +486,8 @@ class Order extends \yii\db\ActiveRecord
} }
``` ```
The [[yii\db\ActiveQuery::via()|via()]] method is similar to [[yii\db\ActiveQuery::viaTable()|viaTable()]] except that [[yii\db\ActiveQuery::via()|via()]] メソッドは、最初のパラメータとして、結合テーブルの名前ではなく、アクティブレコードクラスで宣言されているリレーションの名前を取ること以外は、[[yii\db\ActiveQuery::viaTable()|viaTable()]] と同じです。
the first parameter of [[yii\db\ActiveQuery::via()|via()]] takes a relation name declared in the ActiveRecord class 例えば、上記の `items` リレーションは次のように宣言しても等値です。
instead of the junction table name. For example, the above `items` relation can be equivalently declared as follows:
```php ```php
class Order extends \yii\db\ActiveRecord class Order extends \yii\db\ActiveRecord
...@@ -517,7 +505,7 @@ class Order extends \yii\db\ActiveRecord ...@@ -517,7 +505,7 @@ class Order extends \yii\db\ActiveRecord
} }
``` ```
[junction table]: https://en.wikipedia.org/wiki/Junction_table "Junction table on Wikipedia" [連結テーブル]: https://en.wikipedia.org/wiki/Junction_table "Junction table on Wikipedia"
Lazy and Eager Loading Lazy and Eager Loading
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment