diff --git a/docs/guide-ja/tutorial-core-validators.md b/docs/guide-ja/tutorial-core-validators.md index 393e7921e5..552ef956f9 100644 --- a/docs/guide-ja/tutorial-core-validators.md +++ b/docs/guide-ja/tutorial-core-validators.md @@ -97,18 +97,23 @@ public function rules() ``` このバリデータは、入力値が正しい書式の date、time、または datetime であるかどうかをチェックします。 -オプションとして、入力値を UNIX タイムスタンプに変換して、[[yii\validators\DateValidator::timestampAttribute|timestampAttribute]] によって指定された属性に保存することも出来ます。 +オプションとして、入力値を UNIX タイムスタンプ (または、その他、機械による読み取りが可能な形式) に変換して、[[yii\validators\DateValidator::timestampAttribute|timestampAttribute]] によって指定された属性に保存することも出来ます。 - `format`: 検証される値が従っているべき日付/時刻の書式。 これには [ICU manual](http://userguide.icu-project.org/formatparse/datetime#TOC-Date-Time-Format-Syntax) で記述されている日付/時刻のパターンを使うことが出来ます。 あるいは、PHP の `Datetime` クラスによって認識される書式に接頭辞 `php:` を付けた文字列でも構いません。 サポートされている書式については、 を参照してください。 このプロパティが設定されていないときは、`Yii::$app->formatter->dateFormat` の値を取ります。 + - `timestampAttribute`: このバリデータが、入力された日付/時刻から変換した UNIX タイムスタンプを代入することが出来る属性の名前。 これは、検証される属性と同じ属性であってもかまいません。 その場合は、元の値は検証実行後にタイムスタンプで上書きされます。 [DatePicker で日付の入力を扱う](widget-jui#datepicker-date-input) に使用例がありますので、参照してください。 + バージョン 2.0.4 以降では、[[yii\validators\DateValidator::$timestampAttributeFormat|$timestampAttributeFormat]] と [[yii\validators\DateValidator::$timestampAttributeTimeZone|$timestampAttributeTimeZone]] を使って、この属性に対するフォーマットとタイムゾーンを指定することが出来ます。 + +- バージョン 2.0.4 以降では、タイムスタンプの [[yii\validators\DateValidator::$min|最小値]] または [[yii\validators\DateValidator::$max|最大値]] を指定することも出来ます。 + 入力が必須でない場合には、date バリデータに加えて、default バリデータ (デフォルト値フィルタ) を追加すれば、空の入力値が `NULL` として保存されることを保証することが出来ます。 そうしないと、データベースに `0000-00-00` という日付が保存されたり、デートピッカーの入力フィールドが `1970-01-01` になったりしてしまいます。 diff --git a/docs/guide-ja/tutorial-performance-tuning.md b/docs/guide-ja/tutorial-performance-tuning.md index 3092d2a87a..3ca8f468d1 100644 --- a/docs/guide-ja/tutorial-performance-tuning.md +++ b/docs/guide-ja/tutorial-performance-tuning.md @@ -5,53 +5,58 @@ あなたのウェブアプリケーションのパフォーマンスは二つの部分に基づいています。 一つはフレームワークのパフォーマンスであり、もう一つはアプリケーションそのものです。 -Yii は、そのままの状態でも、あなたのアプリケーションのパフォーマンスを劣化させる影響がかなり小さいものですが、本番環境のためには、さらに微調整することが可能です。 +Yii は、そのままの状態でも、パフォーマンスを劣化させる影響がかなり小さいものですが、本番環境のためには、さらに微調整することが可能です。 アプリケーションに関しては、ベストプラクティスのいくつかを提供すると共に、それを Yii に適用する方法を例示します。 -環境を準備する --------------- +## PHP 環境を最適化する -PHP アプリケーションを走らせるための環境を正しく構成することは本当に重要です。 +PHP 環境を正しく構成することは非常に重要です。 最大のパフォーマンスを得るためには、 -- 常に最新の安定した PHP バージョンを使うこと。 -PHP は、メジャーリリースのたびに、顕著なパフォーマンスの改善とメモリ使用の削減がなされています。 -- PHP 5.4 以下には [APC](http://ru2.php.net/apc)、または、PHP 5.5 以上には [Opcache](http://php.net/opcache) を使うこと。 -このことは、非常に良いパフォーマンス強化をもたらします。 +- 最新の安定した PHP バージョンを使うこと。 +使用する PHP のメジャーリリースを上げると、顕著なパフォーマンスの改善がもたらされることがあります。 +- [Opcache](http://php.net/opcache) (PHP 5.5 以降) または [APC](http://ru2.php.net/apc) (PHP 5.4 以前) を使って、バイトコードキャッシュを有効にすること。 + バイトコードキャッシュによって、リクエストが入ってくるたびに PHP スクリプトを解析してインクルードする時間の浪費を避けることが出来ます。 -フレームワークを本番用に準備する --------------------------------- +## デバッグモードを無効にする -### デバッグモードを無効化する +本番環境でアプリケーションを実行するときには、デバッグモードを無効にしなければなりません。 +Yii は、`YII_DEBUG` という名前の定数の値を使って、デバッグモードを有効にすべきか否かを示します。 +デバッグモードが有効になっているときは、Yii はデバッグ情報の生成と記録のために時間を余計に費やします。 -アプリケーションを本番環境に配備する前に行うべき最初のことは、デバッグモードの無効化です。 -Yii のアプリケーションは、`index.php` において定数 `YII_DEBUG` が `true` と定義されていると、デバッグモードで走ります。 -従って、デバッグモードを無効にするために、以下のコードが `index.php` になければなりません。 +[エントリスクリプト](structure-entry-scripts.md) の冒頭に次のコード行を置くことによってデバッグモードを無効にすることが出来ます。 ```php defined('YII_DEBUG') or define('YII_DEBUG', false); ``` -デバッグモードは開発段階において非常に役に立ちますが、いくつかのコンポーネントがデバッグモードにおいて追加の負荷を発生させるため、パフォーマンスを劣化させます。 -例えば、メッセージロガーは、ログに記録されるすべてのメッセージについて、追加のデバッグ情報を記録します。 +> Info|情報: `YII_DEBUG` のデフォルト値は false です。 + 従って、アプリケーションコードの他のどこかでこのデフォルト値を変更していないと確信できるなら、単に上記の行を削除してデバッグモードを無効にしても構いません。 -### PHP opcode キャッシュを有効にする +## キャッシュのテクニックを使う -PHP opcode キャッシュを有効にすると、すべての PHP アプリケーションで、顕著にパフォーマンスが向上し、メモリ使用量が削減されます。 -Yii も例外ではありません。 -Yii は [PHP 5.5 OPcache](http://php.net/manual/ja/book.opcache.php) と [APC PHP 拡張](http://php.net/manual/ja/book.apc.php) の両方でテストされています。 -どちらのキャッシュも、PHP 中間コードを最適化して、入ってくるリクエストごとに PHP スクリプトを解析するために時間を消費することを回避します。 +さまざまなキャッシュのテクニックを使うと、あなたのアプリケーションのパフォーマンスを目に見えて改善することが出来ます。 +たとえば、あなたのアプリケーションが Markdown 形式のテキスト入力をユーザに許可している場合、解析済みの Markdown のコンテントをキャッシュすることを考慮してください。 +そうすれば、リクエストごとに毎回同じ Markdown テキストの解析を繰り返すことを回避できるでしょう。 +Yii によって提供されているキャッシュのサポートについて学ぶためには [キャッシュ](caching-overview.md) の節を参照してください。 -### ActiveRecord のデータベーススキーマキャッシュを有効にする +## スキーマキャッシュを有効にする -アプリケーションがアクティブレコードを使用している場合は、スキーマキャッシュを有効にして、データベーススキーマを解析するための時間を節約すべきです。 -そうするためには、アプリケーションの構成情報 `config/web.php` において、`Connection::enableSchemaCache` プロパティを `true` に設定します。 +スキーマキャッシュは、[アクティブレコード](db-active-record.md) を使おうとする場合には、いつでも有効にすべき特別なキャッシュ機能です。 +ご存じのように、アクティブレコードは、賢いことに、あなたがわざわざ記述しなくても、DB テーブルに関するスキーマ情報 (カラムの名前、カラムのタイプ、外部キー制約など) を自動的に検出します。 +アクティブレコードはこの情報を取得するために追加の SQL クエリを実行しています。 +スキーマキャッシュを有効にすると、取得されたスキーマ情報はキャッシュに保存されて将来のクエリで再利用されるようになります。 + +スキーマキャッシュを有効にするためには、[アプリケーションの構成情報](concept-configurations.md) の中で、`cache` [アプリケーションコンポーネント](structure-application-components.md) にスキーマ情報を保存するように構成し、[[yii\db\Connection::enableSchemaCache]] を `true` に設定します。 ```php return [ // ... 'components' => [ // ... + 'cache' => [ + 'class' => 'yii\caching\FileCache', + ], 'db' => [ 'class' => 'yii\db\Connection', 'dsn' => 'mysql:host=localhost;dbname=mydatabase', @@ -60,28 +65,23 @@ return [ 'enableSchemaCache' => true, // スキーマキャッシュの持続時間 - // 'schemaCacheDuration' => 3600, + 'schemaCacheDuration' => 3600, - // 使用されるキャッシュコンポーネントの名前。デフォルトは 'cache'。 - //'schemaCache' => 'cache', - ], - 'cache' => [ - 'class' => 'yii\caching\FileCache', + // スキーマ情報を保存するのし使用されるキャッシュコンポーネントの名前 + 'schemaCache' => 'cache', ], ], ]; ``` -`cache` [アプリケーションコンポーネント](structure-application-components.md) が構成されていなければならないことに注意してください。 +## アセットを結合して最小化する -### アセットを結合して最小化する +複雑なウェブページでは、多数の CSS や JavaScript のアセットファイルをインクルードすることがよくあります。 +HTTP リクエストの回数、および、これらのアセットの全体としてのダウンロードサイズを削減するために、アセットを単一のファイルに結合して、それを圧縮することを考慮すべきです。 +これによって、ページのロードにかかる時間とサーバの負荷を大きく削減することが出来ます。 +詳細については、[アセット](structure-assets.md) の節を参照してください。 -アセットは、典型的には JavaScript と CSS ですが、結合して圧縮することが出来ます。 -これにより、ページの読み込みにかかる時間をわずかながら削減して、アプリケーションのエンドユーザにより良いユーザ体験をもたらすことが出来ます。 - -これをどのようにすれば達成できるかについて学ぶためには、ガイドの [アセット](structure-assets.md) の節を参照してください。 - -### セッションのためにより良いストレージを使用する +## セッションのためにより良いストレージを使用する デフォルトでは、PHP はセッションを処理するためにファイルを使います。 開発と小さなプロジェクトではそれでも構いませんが、リクエストを並列処理するとなると、データベースのような別のストレージに変更する方が良いでしょう。 @@ -111,101 +111,50 @@ return [ サーバに [Redis](http://redis.io/) がある場合は、それをセッションのストレージに使用することを強く推奨します。 -アプリケーションを改善する --------------------------- -### サーバ側のキャッシュテクニックを使う +## データベースを最適化する -キャッシュの節で説明されているように、Yii はウェブアプリケーションのパフォーマンスを著しく改善することが出来るキャッシュのソリューションをいくつか提供しています。 -データの生成に長い時間を要するものがある場合は、データキャッシュの手法を使用して、データを生成する頻度を削減することが出来ます。 -ページのある部分が比較的静的なものであり続ける場合は、フラグメントキャッシュの手法を使用して、その部分のレンダリングの頻度を削減することが出来ます。 -あるページ全体が比較的静的なものであり続ける場合は、ページキャッシュの手法を使用して、ページ全体のレンダリングのコストを節約することが出来ます。 - - -### HTTP キャッシュを利用して、処理時間と帯域を節約する - -HTTP キャッシュを利用すると、処理時間および帯域やリソースを著しく節約することが出来ます。 -HTTP キャッシュは、`ETag` または `Last-Modified` ヘッダをアプリケーションのレスポンスで送信することによって実装することが出来ます。 -ブラウザが HTTP の仕様に従って実装されていれば (ほとんどのブラウザがそうです)、コンテントは以前の状態と異なる場合にだけ取得されます。 - -正しいヘッダを作成することは手間のかかる仕事ですので、Yii は [[yii\filters\HttpCache]] というコントローラフィルタの形でショートカットを提供しています。 -これを使うことはとても簡単です。 -コントローラの中で `behaviors` メソッドを以下のように実装することが必要です。 - -```php -public function behaviors() -{ - return [ - 'httpCache' => [ - 'class' => \yii\filters\HttpCache::className(), - 'only' => ['list'], - 'lastModified' => function ($action, $params) { - $q = new Query(); - return strtotime($q->from('users')->max('updated_timestamp')); - }, - // 'etagSeed' => function ($action, $params) { - // return // egat のシードをここで生成 - //} - ], - ]; -} -``` - -上記のコードでは、`etagSeed` または `lastModified` のどちらかを使うことが出来ます。 -両方を実装する必要はありません。 -目的は、コンテントを取得してレンダリングするよりも安価な方法を使って、コンテントが修正されたかどうかを判断することです。 -`lastModified` はコンテントが最後に修正されたときの UNIX タイムスタンプを返さなければなりません。 -一方 `etagSeed` は `ETag` ヘッダの値を生成するために使われる文字列を返さなければなりません。 - - -### データベースの最適化 - -データベースからのデータ取得がウェブアプリケーションのパフォーマンスの主たるボトルネックになることがよくあります。 -[キャッシュ](caching.md#Query-Caching) の使用によってパフォーマンスの劣化を緩和することは出来ますが、問題を完全に解決することは出来ません。 +DB クエリの実行とデータベースからのデータ取得がウェブアプリケーションのパフォーマンスの主たるボトルネックになることがよくあります。 +[データキャッシュ](caching-data.md) の使用によってパフォーマンスの劣化を緩和することは出来ますが、問題を完全に解決することは出来ません。 データベースが膨大なデータを抱えている場合、キャッシュされたデータが無効化されたときに最新のデータを取得するためのコストは、データベースとクエリが適切に設計されていないと、法外なものになり得ます。 -データベースのインデックスを上手に設計しましょう。 -インデックスを付けると SELECT クエリを非常に速くすることが出来ます。ただし、INSERT、UPDATE、または DELTE のクエリは遅くなることがあります。 - -複雑なクエリに対しては、PHP コードの中からクエリを発行して DBMS にクエリを解析するように繰り返して求める代わりに、データベースビューを作成することを推奨します。 - -アクティブレコードを使い過ぎないでください。 -アクティブレコード は OOP 流にデータをモデリングするには便利ですが、クエリ結果の各行を表すために一つまたは複数のオブジェクトを作る必要があるため、パフォーマンスを現実に低下させます。 -膨大なデータを扱うアプリケーションでは、より低レベルの DAO や データベース API を使うのが良い選択でしょう。 +DB クエリのパフォーマンスを向上させるための一般的なテクニックは、フィルタの対象になるテーブルカラムにインデックスを作成することです。 +例えば、`username` によってユーザのレコードを検索する必要があるなら、`username` に対してインデックスを作成するべきです。 +ただし、インデックスを付けると SELECT クエリを非常に速くすることが出来る代りに、INSERT、UPDATE、または DELTE のクエリが遅くなることに注意してください。 最後にもう一つ大事なことですが、SELECT クエリで LIMIT を使ってください。 こうすることで、大量のデータが返されて、PHP のために確保されたメモリを使い尽くすということがなくなります。 -### asArray を使う +## プレーンな配列を使う -読み出し専用のページにおいて、メモリと処理時間を節約する良い方法に、アクティブレコードの `asArray` メソッドを使うという方法があります。 +[アクティブレコード](db-active-record.md) は非常に使い勝手のよいものですが、データベースから大量のデータを取得する必要がある場合は、プレーンな配列を使うほどには効率的ではありません。 +そういう場合は、アクティブレコードを使ってデータを取得する際に `asArray()` を呼んで、取得したデータがかさばるアクティブレコードのオブジェクトではなく配列として表現されるようにすることを考慮するのが良いでしょう。 +例えば、 ```php class PostController extends Controller { public function actionIndex() { - $posts = Post::find()->orderBy('id DESC')->limit(100)->asArray()->all(); + $posts = Post::find()->limit(100)->asArray()->all(); + return $this->render('index', ['posts' => $posts]); } } ``` -ビューにおいては、`$posts` の個々のレコードのフィールドを配列としてアクセスしなければなりません。 +上記において、`$posts` は、テーブル行の配列としてデータを代入されることになります。 +各行はプレーンな配列になります。 +`$i` 番目の行の `title` カラムにアクセスするためには、`$posts[$i]['title']` という式を使うことが出来ます。 -```php -foreach ($posts as $post) { - echo $post['title'] . "
"; -} -``` +クエリを構築するのに [DAO](db-dao.md) を使って、データをプレーンな配列に取得することも出来ます。 -`asArray` が指定されていなくても配列記法を使用してフィールドにアクセスすることが出来ますが、その場合は AR オブジェクトを扱っていることに注意してください。 -### Composer オートローダを最適化する +## Composer オートローダを最適化する 全体としてのパフォーマンスを改善するために、`composer dumpautoload -o` を実行して、Composer のオートローダを最適化することが出来ます。 -### バックグラウンドでデータを処理する +## バックグラウンドでデータを処理する ユーザのリクエストに素早く応答したい場合、リクエストの重い部分は、それについて即座にレスポンスを返す必要がなければ、後から処理することが出来ます。 @@ -216,19 +165,19 @@ foreach ($posts as $post) { このソリューションでたいていの場合は OK ですが、一つ大きな欠点があります。 データベースを検索するまでは処理すべきデータの有無を知ることが出来ません。 -そのため、データベースをかなり頻繁に検索するか、または、各処理の間に若干の遅延を生じさせるかのどちらかになります。 +そのため、データベースをかなり頻繁に検索するか、または、データの作成と処理の間に若干の遅延を生じさせるかのどちらかになります。 この問題は、キューやジョブサーバ (RabbitMQ、ActiveMQ、Amazon SQS、その他いろいろ) によって解決することが出来ます。 この場合は、持続的ストレージにデータを書き込む代りに、キューやジョブサーバによって提供される API を通じてデータをキューに入れます。 処理はたいていはジョブハンドラのクラスに渡されます。 キューに入れられたジョブは、先行するジョブが全て完了した直後に実行されます。 -### 何をしても効果がない場合 +## 何をしても効果がない場合 何をしても効果がない場合は、何がパフォーマンスの問題を解決するかについての思い込みを排することです。 代りに、いつでも、何かを変更する前にはコードをプロファイルしてください。 次のツールが役に立つでしょう。 -- [Yii のデバッグツールバーとデバッガ](https://github.com/yiisoft/yii2-debug/blob/master/docs/guide/README.md) +- [Yii のデバッグツールバーとデバッガ](https://github.com/yiisoft/yii2-debug/blob/master/docs/guide-ja/README.md) - [XDebug プロファイラ](http://xdebug.org/docs/profiler) -- [XHProf](http://www.php.net/manual/en/book.xhprof.php) +- [XHProf](http://www.php.net/manual/ja/book.xhprof.php)