Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Y
yii2
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
PSDI Army
yii2
Commits
179eea64
Commit
179eea64
authored
Jan 29, 2015
by
Nobuo Kihara
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
docs/guide-ja/structure-models.md - revised [ci skip]
parent
6e50783e
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
93 additions
and
102 deletions
+93
-102
structure-models.md
docs/guide-ja/structure-models.md
+93
-102
No files found.
docs/guide-ja/structure-models.md
View file @
179eea64
...
@@ -2,30 +2,29 @@
...
@@ -2,30 +2,29 @@
======
======
モデルは
[
MVC
](
http://ja.wikipedia.org/wiki/Model_View_Controller
)
アーキテクチャの一部を成すものです。
モデルは
[
MVC
](
http://ja.wikipedia.org/wiki/Model_View_Controller
)
アーキテクチャの一部を成すものです。
これは、
業務
のデータ、規則、ロジックを表現するオブジェクトです。
これは、
ビジネス
のデータ、規則、ロジックを表現するオブジェクトです。
モデルクラスは、
[
[yii\base\Model
]
] またはその子クラスを拡張することによって作成することが出来ます。
モデルクラスは、
[
[yii\base\Model
]
] またはその子クラスを拡張することによって作成することが出来ます。
基底クラス
[
[yii\base\Model
]
] は数多くの有用な機能をサポートしています。
基底クラス
[
[yii\base\Model
]
] は
、次のように、
数多くの有用な機能をサポートしています。
*
[
属性
](
#attributes
)
:
業務のデータを表現する。通常のオブジェクトプロパティや配列要素のようにしてアクセス出来る
。
*
[
属性
](
#attributes
)
:
ビジネスデータを表現します。通常のオブジェクトプロパティや配列要素のようにしてアクセスすることが出来ます
。
*
[
属性のラベル
](
#attribute-labels
)
: 属性の表示ラベルを
規定する
。
*
[
属性のラベル
](
#attribute-labels
)
: 属性の表示ラベルを
指定します
。
*
[
一括代入
](
#massive-assignment
)
: 一回のステップで複数の属性にデータを投入することをサポートしてい
る
。
*
[
一括代入
](
#massive-assignment
)
: 一回のステップで複数の属性にデータを投入することをサポートしてい
ます
。
*
[
検証規則
](
#validation-rules
)
: 宣言された検証規則に基いて入力されたデータ
を確認する
。
*
[
検証規則
](
#validation-rules
)
: 宣言された検証規則に基いて入力されたデータ
の有効性を保証します
。
*
[
データのエクスポート
](
#data-exporting
)
: カスタマイズ可能な
書式を使ってモデルのデータを配列の形式にエクスポートすることが出来る
。
*
[
データのエクスポート
](
#data-exporting
)
: カスタマイズ可能な
形式でモデルデータを配列にエクスポートすることが出来ます
。
`Model`
クラスは、
[
アクティブレコード
](
db-active-record.md
)
のような、更に高度なモデルの基底クラスでもあります。
`Model`
クラスは、
[
アクティブレコード
](
db-active-record.md
)
のような、更に高度なモデルの基底クラスでもあります。
そ
ういう
高度なモデルについての詳細は、関連するドキュメントを参照してください。
そ
れらの
高度なモデルについての詳細は、関連するドキュメントを参照してください。
> Info|情報: あなたのモデルクラスの基底クラスとして [[yii\base\Model]] を使うことは必須の条件ではありません。
> Info|情報: あなたのモデルクラスの基底として [[yii\base\Model]] を使うことが要求されている訳ではありません。
しかしながら、Yii のコンポーネントの多くが
[
[yii\base\Model
]
] をサポートするように作られていますので、
しかしながら、Yii のコンポーネントの多くが
[
[yii\base\Model
]
] をサポートするように作られていますので、通常は
[
[yii\base\Model
]
] がモデルの基底クラスとして推奨されます。
通常は
[
[yii\base\Model
]
] がモデルの基底クラスとして推奨されます。
## 属性<span id="attributes"></span>
## 属性
<span id="attributes"></span>
モデルは
業務の
データを
*属性*
の形式で表現します。
モデルは
ビジネス
データを
*属性*
の形式で表現します。
全ての属性はそれぞれパブリックにアクセス可能なモデルのプロパティと同様なものです。
全ての属性はそれぞれパブリックにアクセス可能なモデルのプロパティと同様なものです。
[
[yii\base\Model::attributes()
]
] メソッドが、モデルがどのような属性を持つかを
規
定します。
[
[yii\base\Model::attributes()
]
] メソッドが、モデルがどのような属性を持つかを
指
定します。
属性に対しては、通常のオブジェクトプロパティにアクセスするのと同じようにして、アクセスすることが出来ます。
属性に対しては、通常のオブジェクトプロパティにアクセスするのと同じようにして、アクセスすることが出来ます。
...
@@ -38,7 +37,7 @@ echo $model->name;
...
@@ -38,7 +37,7 @@ echo $model->name;
```
```
また、配列の要素にアクセスするようして、属性にアクセスすることも出来ます。
また、配列の要素にアクセスするようして、属性にアクセスすることも出来ます。
これは、
[
[yii\base\Model
]
] が
[
ArrayAccess インターフェイス
](
http://php.net/manual/ja/class.arrayaccess.php
)
と
[
ArrayIterator クラス
](
http://jp2.php.net/manual/ja/class.arrayiterator.php
)
をサポートしている
おかげ
です。
これは、
[
[yii\base\Model
]
] が
[
ArrayAccess インターフェイス
](
http://php.net/manual/ja/class.arrayaccess.php
)
と
[
ArrayIterator クラス
](
http://jp2.php.net/manual/ja/class.arrayiterator.php
)
をサポートしている
恩恵
です。
```
php
```
php
$model
=
new
\app\models\ContactForm
;
$model
=
new
\app\models\ContactForm
;
...
@@ -54,10 +53,10 @@ foreach ($model as $name => $value) {
...
@@ -54,10 +53,10 @@ foreach ($model as $name => $value) {
```
```
### 属性を定義する<span id="defining-attributes"></span>
### 属性を定義する
<span id="defining-attributes"></span>
あなたのモデルが
[
[yii\base\Model
]
] を直接に拡張するものである場合、
既定によって
、全ての
*static でない public な*
メンバ変数は属性となります。
あなたのモデルが
[
[yii\base\Model
]
] を直接に拡張するものである場合、
デフォルトでは
、全ての
*static でない public な*
メンバ変数は属性となります。
例えば、次に示す
`ContactForm`
モデルは
4
つの属性、すなわち、
`name`
、
`email`
、
`subject`
、そして、
`body`
を持ちます。
例えば、次に示す
`ContactForm`
モデルは
四
つの属性、すなわち、
`name`
、
`email`
、
`subject`
、そして、
`body`
を持ちます。
この
`ContactForm`
モデルは、HTML フォームから受け取る入力データを表現するために使われます。
この
`ContactForm`
モデルは、HTML フォームから受け取る入力データを表現するために使われます。
```
php
```
php
...
@@ -76,10 +75,9 @@ class ContactForm extends Model
...
@@ -76,10 +75,9 @@ class ContactForm extends Model
[
[yii\base\Model::attributes()
]
] をオーバーライドして、属性を異なる方法で定義することが出来ます。
[
[yii\base\Model::attributes()
]
] をオーバーライドして、属性を異なる方法で定義することが出来ます。
このメソッドはモデル
の中の
属性の名前を返さなくてはなりません。
このメソッドはモデル
が持つ
属性の名前を返さなくてはなりません。
例えば、
[
[yii\db\ActiveRecord
]
] は、関連付けられたデータベーステーブルのコラム名を属性の名前として返すことによって、属性を定義しています。
例えば、
[
[yii\db\ActiveRecord
]
] は、関連付けられたデータベーステーブルのコラム名を属性の名前として返すことによって、属性を定義しています。
これと同時に、定義された属性に対して通常のオブジェクトプロパティと同じようにアクセスすることが出来るように、
ただし、これと同時に、定義された属性に対して通常のオブジェクトプロパティと同じようにアクセスすることが出来るように、
`__get()`
や
`__set()`
などのマジックメソッドをオーバーライドする必要があるかもしれないことに注意してください。
`__get()`
や
`__set()`
などのマジックメソッドをオーバーライドする必要があるかもしれないことに注意してください。
### 属性のラベル <span id="attribute-labels"></span>
### 属性のラベル <span id="attribute-labels"></span>
...
@@ -96,7 +94,7 @@ $model = new \app\models\ContactForm;
...
@@ -96,7 +94,7 @@ $model = new \app\models\ContactForm;
echo
$model
->
getAttributeLabel
(
'name'
);
echo
$model
->
getAttributeLabel
(
'name'
);
```
```
既定
では、属性のラベルは属性の名前から自動的に生成されます。
デフォルト
では、属性のラベルは属性の名前から自動的に生成されます。
ラベルの生成は
[
[yii\base\Model::generateAttributeLabel()
]
] というメソッドによって行われます。
ラベルの生成は
[
[yii\base\Model::generateAttributeLabel()
]
] というメソッドによって行われます。
このメソッドは、キャメルケースの変数名を複数の単語に分割し、各単語の最初の文字を大文字にします。
このメソッドは、キャメルケースの変数名を複数の単語に分割し、各単語の最初の文字を大文字にします。
例えば、
`username`
は
`Username`
となり、
`firstName`
は
`First Name`
となります。
例えば、
`username`
は
`Username`
となり、
`firstName`
は
`First Name`
となります。
...
@@ -142,35 +140,35 @@ public function attributeLabels()
...
@@ -142,35 +140,35 @@ public function attributeLabels()
}
}
```
```
さらに進んで、条件に従って属性のラベルを定義しても構いません。例えば、モデルが使用される
条件に従って属性のラベルを定義することも出来ます。
[
シナリオ
](
#scenarios
)
に基づいて、同じ属性に対して違うラベルを返すことことが出来ます。
例えば、モデルが使用される
[
シナリオ
](
#scenarios
)
に基づいて、同じ属性に対して違うラベルを返すことことが出来ます。
> Info|情報: 厳密に言えば、属性のラベルは [ビュー](structure-views.md) の一部を成すものです。
> Info|情報: 厳密に言えば、属性のラベルは [ビュー](structure-views.md) の一部を成すものです。
しかし、たいていの場合、モデルの中でラベルを宣言する方が便利が良く、結果としてクリーンで再利用可能なコードになります。
しかし、たいていの場合、モデルの中でラベルを宣言する方が便利が良く、結果としてクリーンで再利用可能なコードになります。
## シナリオ<span id="scenarios"></span>
## シナリオ
<span id="scenarios"></span>
モデルはさまざまに異なる
*シナリオ*
で使用されます。
モデルはさまざまに異なる
*シナリオ*
で使用されます。
例えば、
`User`
モデルはユーザログインの入力を収集するために使われますが、同時に、ユーザ登録の目的でも使われます。
例えば、
`User`
モデルはユーザログインの入力を収集するために使われますが、同時に、ユーザ登録の目的でも使われます。
異なるシナリオの下では、モデルが使用する
業務のルールとロジックも異なるでしょう
。
異なるシナリオの下では、モデルが使用する
ビジネスルールとロジックも異なるものになり得ます
。
例えば、
`email`
属性はユーザ登録の際には必須とされるかも知れませんが、ログインの際にはそうではないでしょう。
例えば、
`email`
属性はユーザ登録の際には必須とされるかも知れませんが、ログインの際にはそうではないでしょう。
モデルは
[
[yii\base\Model::scenario
]
] プロパティを使って、自身が使われているシナリオを追跡します。
モデルは
[
[yii\base\Model::scenario
]
] プロパティを使って、自身が使われているシナリオを追跡します。
既定では、モデルは
`default`
という単一のシナリオのみ
をサポートします。
デフォルトでは、モデルは
`default`
という一つのシナリオだけ
をサポートします。
次のコードは、モデルのシナリオを設定する二つの方法を示すものです。
次のコードは、モデルのシナリオを設定する二つの方法を示すものです。
```
php
```
php
//
プロパティとしてシナリオをセット
する
//
シナリオをプロパティとして設定
する
$model
=
new
User
;
$model
=
new
User
;
$model
->
scenario
=
'login'
;
$model
->
scenario
=
'login'
;
// シナリオ
は設定情報でセットされ
る
// シナリオ
を設定情報で設定す
る
$model
=
new
User
([
'scenario'
=>
'login'
]);
$model
=
new
User
([
'scenario'
=>
'login'
]);
```
```
既定
では、モデルによってサポートされるシナリオは、モデルで宣言されている
[
検証規則
](
#validation-rules
)
によって決定されます。
デフォルト
では、モデルによってサポートされるシナリオは、モデルで宣言されている
[
検証規則
](
#validation-rules
)
によって決定されます。
しかし、次のように、
[
[yii\base\Model::scenarios()
]
] メソッドをオーバーライドして、この
動作
をカスタマイズすることが出来ます。
しかし、次のように、
[
[yii\base\Model::scenarios()
]
] メソッドをオーバーライドして、この
振る舞い
をカスタマイズすることが出来ます。
```
php
```
php
namespace
app\models
;
namespace
app\models
;
...
@@ -190,16 +188,14 @@ class User extends ActiveRecord
...
@@ -190,16 +188,14 @@ class User extends ActiveRecord
```
```
> Info|情報: 上記の例と後続の例では、モデルクラスは [[yii\db\ActiveRecord]] を拡張するものとなっています。
> Info|情報: 上記の例と後続の例では、モデルクラスは [[yii\db\ActiveRecord]] を拡張するものとなっています。
というのは、複数のシナリオ
の使用は、通常
、
[
アクティブレコード
](
db-active-record.md
)
クラスで発生するからです。
というのは、複数のシナリオ
を使用することは、通常は
、
[
アクティブレコード
](
db-active-record.md
)
クラスで発生するからです。
`seanarios()`
メソッドは、キーがシナリオの名前であり、値が対応する
*アクティブな属性*
である配列を返します。
`seanarios()`
メソッドは、キーがシナリオの名前であり、値が対応する
*アクティブな属性*
である配列を返します。
アクティブな属性とは、
[
一括代入
](
#massive-assignment
)
することが出来て、
[
検証
](
#validation-rules
)
の対象になる属性です。
アクティブな属性とは、
[
一括代入
](
#massive-assignment
)
することが出来て、
[
検証
](
#validation-rules
)
の対象になる属性です。
上記の例では、
`login`
シナリオにおいては
`username`
と
`password`
の属性がアクティブであり、一方、
上記の例では、
`login`
シナリオにおいては
`username`
と
`password`
の属性がアクティブであり、一方、
`register`
シナリオにおいては、
`username`
と
`password`
に加えて
`email`
もアクティブです。
`register`
シナリオにおいては、
`username`
と
`password`
に加えて
`email`
もアクティブです。
`scenarios()`
の既定の実装は、検証規則の宣言メソッドである
[
[yii\base\Model::rules()
]
] に現れる全てのシナリオを返すものです。
`scenarios()`
のデフォルトの実装は、検証規則の宣言メソッドである
[
[yii\base\Model::rules()
]
] に現れる全てのシナリオを返すものです。
`scenarios()`
をオーバーライドするときに、デフォルトのシナリオに加えて新しいシナリオを導入したい場合は、
`scenarios()`
をオーバーライドするときに、デフォルトのシナリオに加えて新しいシナリオを導入したい場合は、次のようなコードを書きます。
次のようなコードを書きます。
```
php
```
php
namespace
app\models
;
namespace
app\models
;
...
@@ -222,16 +218,17 @@ class User extends ActiveRecord
...
@@ -222,16 +218,17 @@ class User extends ActiveRecord
しかし、他の目的に使うことも可能です。例えば、現在のシナリオに基づいて異なる
[
属性のラベル
](
#attribute-labels
)
を宣言することも出来ます。
しかし、他の目的に使うことも可能です。例えば、現在のシナリオに基づいて異なる
[
属性のラベル
](
#attribute-labels
)
を宣言することも出来ます。
## 検証規則<span id="validation-rules"></span>
## 検証規則
<span id="validation-rules"></span>
モデルのデータをエンドユーザから受け取ったときは、データを検証して、それが一定の規則 (
*検証規則*
、あるいは、いわゆる
*ビジネスルール*
) を満たしていることを確認しなければなりません。
モデルのデータをエンドユーザから受け取ったときは、データを検証して、それが一定の規則 (
*検証規則*
、あるいは、いわゆる
*ビジネスルール*
) を満たしていることを確認しなければなりません。
`ContactForm`
モデルを例に挙げるなら、全ての属性が空ではなく、
`email`
属性が有効なメールアドレスを含んでいることを確認したいでしょう。
`ContactForm`
モデルを例に挙げるなら、全ての属性が空ではなく、
`email`
属性が有効なメールアドレスを含んでいることを確認したいでしょう。
いずれかの属性の値が対応するビジネスルールを満たしていないときは、ユーザがエラーを訂正するのを助ける適切なエラーメッセージが表示され
るべきです
。
いずれかの属性の値が対応するビジネスルールを満たしていないときは、ユーザがエラーを訂正するのを助ける適切なエラーメッセージが表示され
なければなりません
。
受信したデータを検証するために、
[
[yii\base\Model::validate()
]
] を呼ぶことが出来ます。
受信したデータを検証するために、
[
[yii\base\Model::validate()
]
] を呼ぶことが出来ます。
このメソッドは、
[
[yii\base\Model::rules()
]
] で宣言された検証規則を使って、該当するすべての属性を検証します。
このメソッドは、
[
[yii\base\Model::rules()
]
] で宣言された検証規則を使って、該当するすべての属性を検証します。
エラーが見つからなければ、メソッドは true を返します。そうでなければ、
[
[yii\base\Model::errors
]
]
エラーが見つからなければ、メソッドは true を返します。
にエラーを保存して、false を返します。例えば、
そうでなければ、
[
[yii\base\Model::errors
]
] にエラーを保存して、false を返します。
例えば、
```
php
```
php
$model
=
new
\app\models\ContactForm
;
$model
=
new
\app\models\ContactForm
;
...
@@ -264,8 +261,8 @@ public function rules()
...
@@ -264,8 +261,8 @@ public function rules()
}
}
```
```
一
個の規則は、一個
または複数の属性を検証するために使うことが出来ます。
一
つの規則は、一つ
または複数の属性を検証するために使うことが出来ます。
また、一
個の属性は、一個
または複数の規則によって検証することが出来ます。
また、一
つの属性は、一つ
または複数の規則によって検証することが出来ます。
検証規則をどのように宣言するかについての詳細は
[
入力を検証する
](
input-validation.md
)
の節を参照してください。
検証規則をどのように宣言するかについての詳細は
[
入力を検証する
](
input-validation.md
)
の節を参照してください。
時として、特定の
[
シナリオ
](
#scenarios
)
にのみ適用される規則が必要になるでしょう。
時として、特定の
[
シナリオ
](
#scenarios
)
にのみ適用される規則が必要になるでしょう。
...
@@ -287,16 +284,15 @@ public function rules()
...
@@ -287,16 +284,15 @@ public function rules()
`on`
プロパティを指定しない場合は、その規則は全てのシナリオに適用されることになります。
`on`
プロパティを指定しない場合は、その規則は全てのシナリオに適用されることになります。
現在の
[
[yii\base\Model::scenario|シナリオ
]
] に適用可能な規則は
*アクティブな規則*
と呼ばれます。
現在の
[
[yii\base\Model::scenario|シナリオ
]
] に適用可能な規則は
*アクティブな規則*
と呼ばれます。
属性が検証されるのは、それが
`scenarios()`
の中でアクティブな属性であると宣言されており、かつ、その属性が
`rules()`
属性が検証されるのは、それが
`scenarios()`
の中でアクティブな属性であると宣言されており、かつ、その属性が
`rules()`
の中で宣言されている一つまたは複数のアクティブな規則と結び付けられている場合であり、また、そのような場合だけです。
の中で宣言されている一つまたは複数のアクティブな規則と結び付けられている場合であり、また、そのような場合だけです。
## 一括代入<span id="massive-assignment"></span>
## 一括代入
<span id="massive-assignment"></span>
一括代入は、一行のコードを書くだけで、ユーザの入力したデータをモデルに投入できる便利な方法です。
一括代入は、一行のコードを書くだけで、ユーザの入力した
複数の
データをモデルに投入できる便利な方法です。
一括代入は、入力されたデータを
[
[yii\base\Model::$attributes
]
] に直接に代入することによって、モデルの属性にデータを投入します。
一括代入は、入力されたデータを
[
[yii\base\Model::$attributes
]
]
プロパティ
に直接に代入することによって、モデルの属性にデータを投入します。
次の二つのコード断片は等価であり、どちらもエンドユーザから送信されたフォームのデータを
`ContactForm`
モデルの属性に割り当てようとするものです。
次の二つのコード断片は等価であり、どちらもエンドユーザから送信されたフォームのデータを
`ContactForm`
モデルの属性に割り当てようとするものです。
明らかに、一括代入を使う前者の方が、後者よりも明
瞭
で間違いも起こりにくいでしょう。
明らかに、一括代入を使う前者の方が、後者よりも明
快
で間違いも起こりにくいでしょう。
```
php
```
php
$model
=
new
\app\models\ContactForm
;
$model
=
new
\app\models\ContactForm
;
...
@@ -313,11 +309,11 @@ $model->body = isset($data['body']) ? $data['body'] : null;
...
@@ -313,11 +309,11 @@ $model->body = isset($data['body']) ? $data['body'] : null;
```
```
### 安全な属性<span id="safe-attributes"></span>
### 安全な属性
<span id="safe-attributes"></span>
一括代入は、いわゆる
*安全な属性*
、すなわち、
[
[yii\base\Model::scenarios()
]
] においてモデルの現在の
[
[yii\base\Model::scenario|シナリオ
]
]
一括代入は、いわゆる
*安全な属性*
、すなわち、
[
[yii\base\Model::scenarios()
]
] においてモデルの現在の
[
[yii\base\Model::scenario|シナリオ
]
]
のためにリストされている属性に対してのみ適用されます。
のためにリストされている属性に対してのみ適用されま
す。
例えば、
`User`
モデルが次のようなシナリオ宣言を持っている場合において、現在のシナリオが
`login`
であるときは、
`username`
と
`password`
のみが一括代入が可能で
す。
例えば、
`User`
モデルが次のようなシナリオ宣言を持っている場合において、現在のシナリオが
`login`
であるときは、
`username`
と
`password`
のみが一括代入が可能です。
その他の属性はいっさい触れられません。
その他の属性はいっさい触れられません。
```
php
```
php
public
function
scenarios
()
public
function
scenarios
()
...
@@ -329,14 +325,14 @@ public function scenarios()
...
@@ -329,14 +325,14 @@ public function scenarios()
}
}
```
```
> Info|情報: 一括代入が安全な属性に対してのみ適用されるのは、どの属性がエンドユーザの入力データによって修正されうるかを制御する必要があるからです。
> Info|情報: 一括代入が安全な属性に対してのみ適用されるのは、エンドユーザの入力データがどの属性を修正することが出来るか、ということを制御する必要があるからです。
例えば、
`User`
モデルに、ユーザに割り当てられた権限を決定する
`permission`
という属性がある場合、
例えば、
`User`
モデルに、ユーザに割り当てられた権限を決定する
`permission`
という属性がある場合、この属性が修正できるのは、管理者がバックエンドのインターフェイスを通じてする時だけに制限したいでしょう。
この属性が修正できるのは、管理者がバックエンドのインターフェイスを通じてする時だけに制限したいでしょう。
[
[yii\base\Model::scenarios()
]
] の
既定
の実装は
[
[yii\base\Model::rules()
]
] に現われる全てのシナリオと属性を返すものです。
[
[yii\base\Model::scenarios()
]
] の
デフォルト
の実装は
[
[yii\base\Model::rules()
]
] に現われる全てのシナリオと属性を返すものです。
従って、このメソッドをオーバーライドしない場合は、アクティブな検証規則のどれかに出現する限り、その属性は安全である、ということになります。
従って、このメソッドをオーバーライドしない場合は、アクティブな検証規則のどれかに出現する限り、その属性は安全である、ということになります。
このため、実際に検証することなく属性を安全であると宣言できるように、
`safe`
というエイリアスを与えられた特別なバリデータが提供されています。例えば、次の規則は
`title`
と
`description`
の両方が安全な属性であると宣言しています。
このため、実際に検証することなく属性を安全であると宣言できるように、
`safe`
というエイリアスを与えられた特別なバリデータが提供されています。
例えば、次の規則は
`title`
と
`description`
の両方が安全な属性であると宣言しています。
```
php
```
php
public
function
rules
()
public
function
rules
()
...
@@ -348,13 +344,12 @@ public function rules()
...
@@ -348,13 +344,12 @@ public function rules()
```
```
### 安全でない属性<span id="unsafe-attributes"></span>
### 安全でない属性
<span id="unsafe-attributes"></span>
上記で説明したように、
[
[yii\base\Model::scenarios()
]
] メソッドは二つの目的を持っています。
上記で説明したように、
[
[yii\base\Model::scenarios()
]
] メソッドは二つの目的を持っています。
すなわち、どの属性が検証されるべきかを決めることと、どの属性が安全であるかを決めることです。
すなわち、どの属性が検証されるべきかを決めることと、どの属性が安全であるかを決めることです。
めったにない場合として、属性を検証する必要はあるが、安全であるという印は付けたくない、ということがあります。
めったにない場合として、属性を検証する必要はあるが、安全であるという印は付けたくない、ということがあります。
そういう時は、下の例の
`secret`
属性のように、
`scenarios()`
の中で宣言するときに属性の名前の前に感嘆符
そういう時は、下の例の
`secret`
属性のように、名前の前に感嘆符
`!`
を付けて
`scenarios()`
の中で宣言することが出来ます。
`!`
を前置することが出来ます。
```
php
```
php
public
function
scenarios
()
public
function
scenarios
()
...
@@ -365,8 +360,9 @@ public function scenarios()
...
@@ -365,8 +360,9 @@ public function scenarios()
}
}
```
```
このモデルが
`login`
シナリオにある場合、三つの属性は全て検証されます。しかし、
`username`
と
このモデルが
`login`
シナリオにある場合、三つの属性は全て検証されます。
`password`
の属性だけが一括代入が可能です。
`secret`
属性に入力値を割り当てるためには、下記のように明示的に代入を実行する必要があります。
しかし、
`username`
と
`password`
の属性だけが一括代入が可能です。
`secret`
属性に入力値を割り当てるためには、下記のように明示的に代入を実行する必要があります。
```
php
```
php
$model
->
secret
=
$secret
;
$model
->
secret
=
$secret
;
...
@@ -375,12 +371,13 @@ $model->secret = $secret;
...
@@ -375,12 +371,13 @@ $model->secret = $secret;
## データのエクスポート <span id="data-exporting"></span>
## データのエクスポート <span id="data-exporting"></span>
モデルを他の形式にエクスポートする必要が生じることはよくあります。
例えば、一群のモデルを JSON や
モデルを他の形式にエクスポートする必要が生じることはよくあります。
Excel 形式に変換したい場合があるでしょう。
例えば、モデルのコレクションを JSON や
Excel 形式に変換したい場合があるでしょう。
エクスポートのプロセスは二つの独立したステップに分割することが出来ます。
エクスポートのプロセスは二つの独立したステップに分割することが出来ます。
最初のステップで、モデルは配列に変換されます。そして第二のステップで、配列が目的の形式に変換されます。
最初のステップで、モデルは配列に変換されます。
あなたは最初のステップだけに注力しても構いません。と言うのは、第二のステップは汎用的なデータフォーマッタ、例えば
[
[yii\web\JsonResponseFormatter
]
]
そして第二のステップで、配列が目的の形式に変換されます。
によって達成できるからです。
あなたは最初のステップだけに注力することが出来ます。
と言うのは、第二のステップは汎用的なデータフォーマッタ、例えば
[
[yii\web\JsonResponseFormatter
]
] によって達成できるからです。
モデルを配列に変換する最も簡単な方法は、
[
[yii\base\Model::$attributes
]
] プロパティを使うことです。
モデルを配列に変換する最も簡単な方法は、
[
[yii\base\Model::$attributes
]
] プロパティを使うことです。
例えば、
例えば、
...
@@ -390,27 +387,24 @@ $post = \app\models\Post::findOne(100);
...
@@ -390,27 +387,24 @@ $post = \app\models\Post::findOne(100);
$array
=
$post
->
attributes
;
$array
=
$post
->
attributes
;
```
```
既定によって
、
[
[yii\base\Model::$attributes
]
] プロパティは
[
[yii\base\Model::attributes()
]
] で宣言されている
*全て*
の属性の値を返します。
デフォルトでは
、
[
[yii\base\Model::$attributes
]
] プロパティは
[
[yii\base\Model::attributes()
]
] で宣言されている
*全て*
の属性の値を返します。
モデルを配列に変換するためのもっと柔軟で強力な方法は、
[
[yii\base\Model::toArray()
]
] メソッドを使うことです。
モデルを配列に変換するためのもっと柔軟で強力な方法は、
[
[yii\base\Model::toArray()
]
] メソッドを使うことです。
このメソッドの既定の動作は
[
[yii\base\Model::$attributes
]
] のそれと同じものです。
このメソッドのデフォルトの動作は
[
[yii\base\Model::$attributes
]
] のそれと同じものです。
しかしながら、このメソッドを使うと、どのデータ項目 (
*フィールド*
と呼ばれます)
しかしながら、このメソッドを使うと、どのデータ項目 (
*フィールド*
と呼ばれます) を結果の配列に入れるか、そして、その項目にどのような書式を適用するかを選ぶことが出来ます。
を結果の配列に入れるか、そして、その項目にどのような書式を適用するかを選ぶことが出来ます。
実際、
[
レスポンス形式の設定
](
rest-response-formatting.md
)
で説明されているように、RESTful ウェブサービスの開発においては、これがモデルをエクスポートするデフォルトの方法となっています。
実際、
[
レスポンス形式の設定
](
rest-response-formatting.md
)
で説明されているように、RESTful
ウェブサービスの開発においては、これがモデルをエクスポートする既定の方法となっています。
### フィールド<span id="fields"></span>
### フィールド
<span id="fields"></span>
フィールドとは、単に、モデルの
[
[yii\base\Model::toArray()
]
] メソッドを呼ぶことによって取得される配列に含まれる名前付きの要素のことです。
フィールドとは、単に、モデルの
[
[yii\base\Model::toArray()
]
] メソッドを呼ぶことによって取得される配列に含まれる
、
名前付きの要素のことです。
既定では、フィールドの名前は属性の名前と等しいものになります。しかし、この既定の動作は、
[
[yii\base\Model::fields()|fields()
]
]
デフォルトでは、フィールドの名前は属性の名前と等しいものになります。
および/または
[
[yii\base\Model::extraFields()|extraFields()
]
] メソッドをオーバーライドして、変更することが出来ます。
しかし、このデフォルトの動作は、
[
[yii\base\Model::fields()|fields()
]
]
および/または
[
[yii\base\Model::extraFields()|extraFields()
]
] メソッドをオーバーライドして、変更することが出来ます。
どちらのメソッドも、フィールド定義のリストを返します。
どちらのメソッドも、フィールド定義のリストを返します。
`fields()`
によって定義されるフィールドは、デフォルトフィールドです。すなわち、
`toArray()`
はデフォルトでこれらのフィールドを返す、ということを意味します。
`fields()`
によって定義されるフィールドは、デフォルトフィールドです。すなわち、
`toArray()`
はデフォルトでこれらのフィールドを返す、ということを意味します。
`extraFields()`
メソッドは、
`$expand`
パラメータによって指定する限りにおいて
`toArray()`
によって返される追加のフィールドを定義するものです。
`extraFields()`
メソッドは、
`$expand`
パラメータによって指定する限りにおいて
`toArray()`
によって返される、追加のフィールドを定義するものです。
例として、次のコードは、
`fields()`
で定義された全てのフィールドと、
例として、次のコードは、
`fields()`
で定義された全てのフィールドと、(
`extraFields()`
で定義されていれば)
`prettyName`
と
`fullAddress`
フィールドを返すものです。
(
`extraFields()`
で定義されていれば)
`prettyName`
と
`fullAddress`
フィールドを返すものです。
```
php
```
php
$array
=
$model
->
toArray
([],
[
'prettyName'
,
'fullAddress'
]);
$array
=
$model
->
toArray
([],
[
'prettyName'
,
'fullAddress'
]);
...
@@ -423,8 +417,8 @@ $array = $model->toArray([], ['prettyName', 'fullAddress']);
...
@@ -423,8 +417,8 @@ $array = $model->toArray([], ['prettyName', 'fullAddress']);
例えば、
例えば、
```
php
```
php
// 明示的に全てのフィールドをリストする方法。(API の後方互換性を保つために) DB テーブルや
モデル属性の
// 明示的に全てのフィールドをリストする方法。(API の後方互換性を保つために) DB テーブルや
// 変更がフィールドの変更を引き起こさないことを保証したい場合に適している。
//
モデル属性の
変更がフィールドの変更を引き起こさないことを保証したい場合に適している。
public
function
fields
()
public
function
fields
()
{
{
return
[
return
[
...
@@ -441,7 +435,7 @@ public function fields()
...
@@ -441,7 +435,7 @@ public function fields()
];
];
}
}
// いくつかのフィールドを除
去
する方法。親の実装を継承しつつ、公開すべきでないフィールドは
// いくつかのフィールドを除
外
する方法。親の実装を継承しつつ、公開すべきでないフィールドは
// 除外したいときに適している。
// 除外したいときに適している。
public
function
fields
()
public
function
fields
()
{
{
...
@@ -454,17 +448,16 @@ public function fields()
...
@@ -454,17 +448,16 @@ public function fields()
}
}
```
```
> Warning|警告: 既定ではモデルの全ての属性がエクスポートされる配列に含まれるため、データを精査して、
> Warning|警告: デフォルトではモデルの全ての属性がエクスポートされる配列に含まれるため、データを精査して、公開すべきでない情報が含まれていないことを確認しなければなりません。
> 公開すべきでない情報が含まれていないことを確認すべきです。そういう情報がある場合は、
> そういう情報がある場合は、`fields()` をオーバーライドして、除外しなければなりません。
> `fields()` をオーバーライドして、除去すべきです。上記の例では、`auth_key`、`password_hash`
> 上記の例では、`auth_key`、`password_hash` および `password_reset_token` を除外しています。
> および `password_reset_token` を選んで除去しています。
## ベストプラクティス<span id="best-practices"></span>
## ベストプラクティス
<span id="best-practices"></span>
モデルは、
業務
のデータ、規則、ロジックを表わす中心的なオブジェクトです。
モデルは、
ビジネス
のデータ、規則、ロジックを表わす中心的なオブジェクトです。
モデルは、
さまざまな場所で再利用される必要がよく
あります。
モデルは、
たいてい、さまざまな場所で再利用される必要が
あります。
良く設計されたアプリケーションでは、通常、モデルは
[
コントローラ
](
structure-controllers.md
)
よりもはるかに
重い
ものになります。
良く設計されたアプリケーションでは、通常、モデルは
[
コントローラ
](
structure-controllers.md
)
よりもはるかに
太った
ものになります。
要約すると、モデルは、
要約すると、モデルは、
...
@@ -474,22 +467,20 @@ public function fields()
...
@@ -474,22 +467,20 @@ public function fields()
*
リクエスト、セッション、または他の環境データに直接アクセスするべきではありません。
*
リクエスト、セッション、または他の環境データに直接アクセスするべきではありません。
これらのデータは、
[
コントローラ
](
structure-controllers.md
)
によってモデルに注入されるべきです。
これらのデータは、
[
コントローラ
](
structure-controllers.md
)
によってモデルに注入されるべきです。
*
HTML を埋め込むなどの表示用のコードは避けるべきです - 表示は
[
ビュー
](
structure-views.md
)
で行う方が良いです。
*
HTML を埋め込むなどの表示用のコードは避けるべきです - 表示は
[
ビュー
](
structure-views.md
)
で行う方が良いです。
*
あまりに多くの
[
シナリオ
](
#scenarios
)
を
単一
のモデルで持つことは避けましょう。
*
あまりに多くの
[
シナリオ
](
#scenarios
)
を
一つ
のモデルで持つことは避けましょう。
大規模で複雑なシステムを開発するときには、たいてい、上記の最後にあげた推奨事項を考慮するのが良いでしょう。
大規模で複雑なシステムを開発するときには、たいてい、上記の最後にあげた推奨事項を考慮するのが良いでしょう。
そういうシステムでは、モデルは数多くの場所で使用され、それに従って、数多くの規則セットやビジネスロジックを含むため、非常に
大きくて重い
ものになり得ます。
そういうシステムでは、モデルは数多くの場所で使用され、それに従って、数多くの規則セットやビジネスロジックを含むため、非常に
太った
ものになり得ます。
コードの一ヶ所に触れるだけで数ヶ所の違った場所に影響が及ぶため、ついには、モデルのコードの保守が悪夢になってしまうこともよくあります。
コードの一ヶ所に触れるだけで数ヶ所の違った場所に影響が及ぶため、ついには、モデルのコードの保守が悪夢になってしまうこともよくあります。
モデルのコードの保守性を高めるために、以下の戦略をとることが出来ます。
モデルのコードの保守性を高めるために
は
、以下の戦略をとることが出来ます。
*
異なる
[
アプリケーション
](
structure-applications.md
)
や
[
モジュール
](
structure-modules.md
)
*
異なる
[
アプリケーション
](
structure-applications.md
)
または
[
モジュール
](
structure-modules.md
)
によって共有される一連の基底モデルクラスを定義します。
によって共有される一連の基底モデルクラスを定義します。
これらのモデルクラスは、すべてで共通に使用される最小限の規則セットとロジックのみを含むべきです。
これらのモデルクラスは、すべてで共通に使用される最小限の規則セットとロジックのみを含むべきです。
*
モデルを使用するそれぞれの
[
アプリケーション
](
structure-applications.md
)
または
[
モジュール
](
structure-modules.md
)
*
モデルを使用するそれぞれの
[
アプリケーション
](
structure-applications.md
)
または
[
モジュール
](
structure-modules.md
)
において、対応する基底モデルクラスから拡張した具体的なモデルクラスを定義します。
において、対応する基底モデルクラスから拡張した具体的なモデルクラスを定義します。
この具体的なモデルクラスが、そのアプリケーションやモジュールに固有の規則やロジックを含むべきです。
この具体的なモデルクラスが、そのアプリケーションやモジュールに固有の規則やロジックを含むべきです。
例えば、
[
アドバンストアプリケーションテンプレート
](
tutorial-advanced-app.md
)
の中で、基底モデルクラス
`common\models\Post`
例えば、
[
アドバンストアプリケーションテンプレート
](
tutorial-advanced-app.md
)
の中で、基底モデルクラス
`common\models\Post`
を定義することが出来ます。
を定義することが出来ます。次に、フロントエンドアプリケーションにおいては、
`common\models\Post`
から拡張した具体的なモデルクラス
次に、フロントエンドアプリケーションにおいては、
`common\models\Post`
から拡張した具体的なモデルクラス
`frontend\models\Post`
を定義して使います。
`frontend\models\Post`
を定義して使います。
また、バックエンドアプリケーションにおいても、同様に、
`backend\models\Post`
を定義します。
また、バックエンドアプリケーションにおいても、同様に、
`backend\models\Post`
を定義します。
この戦略を取ると、
`frontend\models\Post`
の中のコードはフロントエンドアプリケーション固有のものであると保証することが出来ます。
この戦略を取ると、
`frontend\models\Post`
の中のコードはフロントエンドアプリケーション固有のものであると保証することが出来ます。
そして、フロントエンドのコードにどのような変更を加えても、バックエンドアプリケーションを壊すかもしれないと心配する必要がなくなります。
そして、フロントエンドのコードにどのような変更を加えても、バックエンドアプリケーションを壊すかもしれないと心配する必要がなくなります。
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment