ホームページ >バックエンド開発 >PHPチュートリアル >Yii2 設定の基本概念
設定は、Yii で新しいオブジェクトを作成したり、既存のオブジェクトを初期化するために広く使用されます。設定には、通常、作成されたオブジェクトの クラス名 と、オブジェクトの プロパティ に割り当てられる一連の初期値が含まれます。ここでのプロパティは Yii2 の属性です。イベント ハンドラーをオブジェクトのイベントにバインドしたり、オブジェクトにビヘイビアーを付加したりすることもできます。したがって、オブジェクトの初期値を定義する際に、オブジェクトのランタイムの動的特性が完全に指定されます。
次のコードの設定は、データベース接続の作成と初期化に使用されます:
$config = [ 'class' => 'yii\db\Connection', 'dsn' => 'mysql:host=127.0.0.1;dbname=demo', 'username' => 'root', 'password' => '', 'charset' => 'utf8', ];$db = Yii::createObject($config);
Yii::createObject()
は、Yii2 でオブジェクトを作成するために最も一般的に使用されるメソッドであり、その内容DI コンテナから取得されるオブジェクトについては後の章で説明します。このメソッドは構成配列を受け取り、配列で指定されたクラス名に基づいてオブジェクトを作成します。オブジェクトがインスタンス化された後、残りのパラメーターを使用してオブジェクトのプロパティ、イベント、および動作が初期化されます。 Yii::createObject()
是Yii2中最常用的用来创建对象的方法,其内容是从DI Container中去取的对象,在后面的章节中我们会讲到。这个方法方法接受一个配置数组并根据数组中指定的类名创建对象,对象实例化后,剩余的参数被用来初始化对象的属性,事件和行为。
小编提醒:在Yii2.1中,配置数组中用来表示类名的键值由
class
变成了__class
,但是配置的原理是不变的。
对于已存在的对象,可以使用 Yii::configure() 方法根据配置去初始化其属性, 就像这样:
Yii::configure($object, $config);
请注意,如果配置一个已存在的对象,那么配置数组中不应该包含指定类名的 class 元素。
在编程中,有个非常重要的概念叫“委托”,就是一个对象A可以依靠另一个对象B去完成特定的功能,典型的应用就是策略模式了。要实现“委托”,要有这么个流程:在对象A实例化时注入另一个对象B;A持有对象B;对象A委托对象B去完成特定的功能。“注入”“持有”“委托”都是设计模式中的高频词汇,通过这些操作可以扩展类的功能。
我们看看在别的面向对象语言如Java或者PHP其他框架中经常使用的方式:
class Person { private $strategy = null; public function __construct(TravelStrategy $travel) { $this->strategy = $travel; } /** * 设置旅行的方式. */ public function setTravelStrategy(TravelStrategy $travel) { $this->strategy = $travel; } /** * 旅行. */ public function travel() { //这里实现了“委托”,委托给$this->strategy来实现旅行的具体方式 return $this->strategy->travelAlgorithm(); } }
在实例化或者初始化时,大概就是这么用的:
class Test{ public function run($argument) { // 乘坐火车旅行 $person = new Person(new TrainStrategy()); $person->travel(); // 改骑自行车 $person->setTravelStrategy(new BicycleStrategy()); $person->travel(); } }
Person
是一个想要旅行的人,它持有一个具体的交通方式类$strategy
,最后旅游就是委托给这个交通方式$strategy
来完成的——是骑车还是自驾游还是坐飞机。在使用时先new 一个对象,并且在构造器里面注入一种交通方式初始化旅行的方式,并且我还可以通过Person::setTravelStrategy
临时决定改变旅行方式——这是策略模式的应用场景。
我们看看这一行:
$person = new Person(new TrainStrategy());
这种写法大家再也熟悉不过了吧?其实这完成了两步操作:
实例化对象Person,方式是 new
注入外部实例new TrainStrategy()
并对$person
初始化。注入的可以是实例当然也可以是常量。
但是按照Yii2的风格,就应该是这样的:
class Person extends Component{ private $strategy = null; /** * 旅行. */ public function setTravelStrategy($travel) { if (!($travel instanceof TravelStrategy)) { $travel = Yii::createObject($travel); } $this->strategy = $travel; } /** * 旅行. */ public function travel() { return $this->strategy->travelAlgorithm(); } }
用法就大概是这样的风格:
//用配置创建对象并初始化,选择火车出行 $person = Yii::createObject([ 'class' => Person::class, 'travelStrategy' => [ 'class' => TrainStrategy::class ] ]); $person->travel();//用配置重新初始化对象,改骑自行车 $person = Yii::configure($person, [ 'travelStrategy' => [ 'class' => BicycleStrategy::class ] ]); $person->travel();
上面这个例子,应该可以帮助大家了解Yii2配置的作用和使用方式。其中创建对象的方式不是通过new关键词,而是去依赖注入容器(DI Container)中去获取的,后面我们会讲到。
Yii2框架似乎不太喜欢用“通用”的实例化和初始化的方式,在Yii2框架内部几乎都是通过配置来实现对象的实例化和初始化。这是Yii2的一个风格,当然这种风格看起来更为简洁(前提是你已经熟悉),使用起来则是更为方便。虽说看起来有差异,但是本质上还是一样的,只是注入的方式有一些差别罢了。
一个配置的格式可以描述为以下形式:
[ 'class' => 'ClassName', 'propertyName' => 'propertyValue', 'on eventName' => $eventHandler, 'as behaviorName' => $behaviorConfig, ]
其中,
class 元素指定了将要创建的对象的完整类名(用Object::class就可以实现)
propertyName 元素指定了对象可写属性的初始值
on eventName 元素指定了附加到对象事件上的处理器。 请注意,数组的键名由 on 前缀加事件名组成。on和事件名之间只能有一个空格
as behaviorName 元素指定了附加到对象的行为。 请注意,数组的键名由 as 前缀加行为名组成。as和行为名之间只能有一个空格。$behaviorConfig
編集者の注意: Yii2.1 では、設定配列内のクラス名を表すために使用されるキー値がclass
から__class
に変更されましたが、設定は原則は変わりません。
[ 'class' => 'app\components\SearchEngine', 'apiKey' => 'xxxxxxxx', 'on search' => function ($event) { Yii::info("搜索的关键词: " . $event->keyword); }, 'as indexer' => [ 'class' => 'app\components\IndexerBehavior', // ... 初始化属性值 ... ], ]既存のオブジェクトを設定すると、その設定は配列には、クラス名を指定するクラス要素を含めることはできません。 設定は Yii2 の機能です プログラミングには「削除」と呼ばれる非常に重要な概念があります。これは、オブジェクト A が特定の機能を完了するために別のオブジェクト B に依存できることを意味します。典型的なアプリケーションはストラテジ パターンです。 「委任」を実装するには、次のようなプロセスが必要です。オブジェクト A がインスタンス化されると、別のオブジェクト B が挿入され、オブジェクト A がオブジェクト B を保持して、特定の関数を完了します。 「注入」、「ホールド」、「デリゲート」はいずれもデザインパターンで使用頻度の高い単語であり、これらの操作によりクラスの機能を拡張することができます。
public function __construct($config = []){ if (!empty($config)) { Yii::configure($this, $config); } $this->init(); }インスタンス化または初期化中に、おそらく次のように使用されます: 🎜
// $object就是即将被配置的对象实例,$properties是配置数组public static function configure($object, $properties){ //遍历每个参数,将其设置为属性,这里可能调用setter等方法 foreach ($properties as $name => $value) { $object->$name = $value; } return $object; }🎜
人
特定の交通手段クラス $strategy
を保持する人です。最終的には、旅行はこの交通手段 $strategy
に委ねられます。 > 完了するには - はい サイクリング、車、飛行機での旅行。これを使用するときは、まず新しいオブジェクトを作成し、コンストラクターに移動メソッドを挿入して移動メソッドを初期化します。また、person::setTravelStrategy
を使用して移動メソッドを一時的に変更することもできます。これは次のとおりです。戦略パターンの適用シナリオ。 🎜🎜この行を見てみましょう: 🎜$config = [ 'id' => 'basic', 'basePath' => dirname(__DIR__), 'extensions' => require(__DIR__ . '/../vendor/yiisoft/extensions.php'), 'components' => [ 'cache' => [ 'class' => 'yii\caching\FileCache', ], 'mailer' => [ 'class' => 'yii\swiftmailer\Mailer', ], 'log' => [ 'class' => 'yii\log\Dispatcher', 'traceLevel' => YII_DEBUG ? 3 : 0, 'targets' => [ [ 'class' => 'yii\log\FileTarget', ], ], ], 'db' => [ 'class' => 'yii\db\Connection', 'dsn' => 'mysql:host=localhost;dbname=stay2', 'username' => 'root', 'password' => '', 'charset' => 'utf8', ], ], ];🎜この書き方は誰もがよく知っていますよね?実際、これで 2 段階の操作が完了します。 🎜🎜🎜🎜 new🎜🎜🎜🎜 で外部インスタンスを注入し、
$person
を初期化することにより、オブジェクト person をインスタンス化します。注入されるものはインスタンスまたは定数です。 🎜🎜🎜🎜しかし、Yii2 のスタイルによれば、次のようになります: 🎜(new yii\web\Application($config))->run();🎜 使用法はおおよそ次のようになります: 🎜
$config = [ 'id' => 'basic', 'basePath' => dirname(__DIR__), 'extensions' => require __DIR__ . '/../vendor/yiisoft/extensions.php', 'container' => [ 'definitions' => [ 'yii\widgets\LinkPager' => ['maxButtonCount' => 5] ], 'singletons' => [ // 依赖注入容器单例配置 ] ] ];🎜 上記の例は、誰もが Yii2 設定の役割と使用法を理解するのに役立つはずです。オブジェクトの作成方法は new キーワードではなく、後述する依存性注入コンテナ (DI コンテナ) から取得します。 🎜🎜 Yii2 フレームワークは、「普遍的な」インスタンス化および初期化メソッドの使用を好んでいないようです。Yii2 フレームワーク内では、オブジェクトのインスタンス化と初期化は、ほとんどの場合、設定を通じて実装されます。これは Yii2 のスタイルです。もちろん、このスタイルは (すでに慣れている場合に限り) よりシンプルに見え、より使いやすくなっています。見た目は違っても本質的には同じですが、注入方法にいくつかの違いがあります。 🎜🎜設定形式🎜🎜 設定形式は次の形式で記述できます:🎜
return [ 'id' => 'basic', 'basePath' => dirname(__DIR__), 'extensions' => require(__DIR__ . '/../vendor/yiisoft/extensions.php'), 'components' => require(__DIR__ . '/components.php'), ];🎜このうち、🎜🎜🎜🎜class要素は、作成されるオブジェクトの完全なクラス名を指定します(これは、Object::を使用して実現できます)。 class)🎜🎜 🎜🎜propertyName 要素は、オブジェクトの 🎜書き込み可能なプロパティ🎜🎜🎜🎜🎜on の初期値を指定します。eventName 要素は、オブジェクトのイベントにアタッチされるハンドラーを指定します。 配列のキー名は on プレフィックスとイベント名で構成されることに注意してください。 on とイベント名 🎜🎜🎜🎜 の間にスペースを 1 つだけ入れることができます。 behaviourName 要素は、オブジェクトに付加される動作を指定します。 配列キー名は、接頭辞 as とその後に続く行名で構成されていることに注意してください。 as とアクション名の間にはスペースを 1 つだけ入れることができます。
$behaviorConfig
値はビヘイビアーを作成するための構成情報を表し、その形式は前に説明した構成形式と同じです。 🎜🎜🎜🎜以下は、初期化属性値、イベントハンドラー、動作の設定例です: 🎜鉴于 components 配置也很复杂,上述代码把它们存储在单独的 components.php 文件中,并且包含在 web.php 里。 components.php 的内容如下:🎜設定実装の原則🎜🎜この規則に従い、設定配列を通じてオブジェクトをインスタンス化し、初期化できます: 🎜 🎜🎜🎜構成可能なインターフェース。BaseObject または Component を継承している限り、これで十分です。心配する必要はありません 🎜
子类重载__construct
方法时,把配置数组放到构造器的最后一个参数:__construct($param1, $param2, ..., $config)
子类在自己的__construct
最后,必须调用parent::__construct($config)
方法
到底是如何实现的呢?这还得从BaseObject中说起,看看BaseObject的构造器:
public function __construct($config = []){ if (!empty($config)) { Yii::configure($this, $config); } $this->init(); }
我们知道Yii::configure
是实现配置的。我们如果每个子类的__construct
都按照上面的规范写,那么到最后无异会调用BaseObject::__construct
,并且将子类的配置数组$config也传递过来,最终被Yii::configure
使用。我们再看看这个方法:
// $object就是即将被配置的对象实例,$properties是配置数组public static function configure($object, $properties){ //遍历每个参数,将其设置为属性,这里可能调用setter等方法 foreach ($properties as $name => $value) { $object->$name = $value; } return $object; }
这一句$object->$name = $value
可能会发生很多故事,可能会调用Component::__setter
或者BaseObject::__setter
(参看我们前面讲属性,行为,事件的章节)
Yii 中的配置可以用在很多场景,除了我们上面举的例子,最常见的莫过于Yii最大的实例Application的配置了。Application堪称最复杂的配置之一了, 因为 Application 类拥有很多可配置的属性和事件。 更重要的是它的 yii\web\Application::components 属性也可以接收配置数组并通过应用注册为组件,配置中还可以有配置。 以下是一个针对基础应用模板的应用配置概要:
$config = [ 'id' => 'basic', 'basePath' => dirname(__DIR__), 'extensions' => require(__DIR__ . '/../vendor/yiisoft/extensions.php'), 'components' => [ 'cache' => [ 'class' => 'yii\caching\FileCache', ], 'mailer' => [ 'class' => 'yii\swiftmailer\Mailer', ], 'log' => [ 'class' => 'yii\log\Dispatcher', 'traceLevel' => YII_DEBUG ? 3 : 0, 'targets' => [ [ 'class' => 'yii\log\FileTarget', ], ], ], 'db' => [ 'class' => 'yii\db\Connection', 'dsn' => 'mysql:host=localhost;dbname=stay2', 'username' => 'root', 'password' => '', 'charset' => 'utf8', ], ], ];
配置中没有 class 键的原因是这段配置应用在下面的入口脚本中, 类名已经指定了。
(new yii\web\Application($config))->run();
Application的配置中,比较重要的是components
属性的配置了。在components
里配置了的,都作为一个单例可以通过Yii::$app->component
来访问;
另外,自版本 2.0.11 开始,系统配置支持使用 container 属性来配置依赖注入容器 例如:
$config = [ 'id' => 'basic', 'basePath' => dirname(__DIR__), 'extensions' => require __DIR__ . '/../vendor/yiisoft/extensions.php', 'container' => [ 'definitions' => [ 'yii\widgets\LinkPager' => ['maxButtonCount' => 5] ], 'singletons' => [ // 依赖注入容器单例配置 ] ] ];
我们这里重点阐述的是配置的原理,并不对Application做过多的配置,只是加深下大家对配置用法的印象而已,关于Application的配置我们以后会有讲到。
当配置的内容十分复杂,通用做法是将其存储在一或多个 PHP 文件中, 这些文件被称为配置文件。一个配置文件返回的是 PHP 数组。 例如,像这样把应用配置信息存储在名为 web.php 的文件中:
return [ 'id' => 'basic', 'basePath' => dirname(__DIR__), 'extensions' => require(__DIR__ . '/../vendor/yiisoft/extensions.php'), 'components' => require(__DIR__ . '/components.php'), ];
鉴于 components 配置也很复杂,上述代码把它们存储在单独的 components.php 文件中,并且包含在 web.php 里。 components.php 的内容如下:
return [ 'cache' => [ 'class' => 'yii\caching\FileCache', ], 'mailer' => [ 'class' => 'yii\swiftmailer\Mailer', ], 'log' => [ 'class' => 'yii\log\Dispatcher', 'traceLevel' => YII_DEBUG ? 3 : 0, 'targets' => [ [ 'class' => 'yii\log\FileTarget', ], ], ], 'db' => [ 'class' => 'yii\db\Connection', 'dsn' => 'mysql:host=localhost;dbname=stay2', 'username' => 'root', 'password' => '', 'charset' => 'utf8', ], ];
如果数据库配置复杂了,你也可以单独拿出来——总之,简洁易维护就行。
仅仅需要 “require”,就可以取得一个配置文件的配置内容,像这样:
$config = require('path/to/web.php');(new yii\web\Application($config))->run();
Yii::createObject() 方法基于依赖注入容器实现,你可以通过 Yii::creatObject() 创建对象时实现配置,同样也可以直接调用 Yii::$container->set() 来实现:
\Yii::$container->set('yii\widgets\LinkPager', [ 'maxButtonCount' => 5, ]);
配置经常会随着环境的更改而更改,有哪些环境呢?——生产,开发,测试。不同的环境可能会提供不同的组件,因此我们可以先定义不同的环境变量。
为了便于切换使用环境,Yii 提供了一个定义在入口脚本中的 YII_ENV 常量。 如下:
defined('YII_ENV') or define('YII_ENV', 'dev');
你可以把 YII_ENV 定义成以下任何一种值:
prod:生产环境。常量 YII_ENV_PROD 将被看作 true,这是 YII_ENV 的默认值。
dev:开发环境。常量 YII_ENV_DEV 将被看作 true。
test:测试环境。常量 YII_ENV_TEST 将被看作 true。
有了这些环境常量,你就可以根据当下应用运行环境的不同,进行差异化配置。 例如,应用可以包含下述代码只在开发环境中开启 调试工具。
$config = [...];if (YII_ENV_DEV) { // 根据 `dev` 环境进行的配置调整 $config['bootstrap'][] = 'debug'; $config['modules']['debug'] = 'yii\debug\Module'; }return $config;
关于配置的东西,大概就是这么多了。
以上がYii2 設定の基本概念の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。