Home  >  Article  >  Backend Development  >  Yii2 configuration basic concepts

Yii2 configuration basic concepts

小云云
小云云Original
2018-03-27 14:29:562066browse

Configuration is widely used to create new objects or initialize existing objects in Yii. The configuration usually contains the class name of the created object and a set of properties that will be assigned to the object. The initial value, the attribute here is the attribute of Yii2. You can also bind event handlers to events on an object, or attach behaviors to the object. Thus, while defining the initial value of the object, the dynamic characteristics of the object's runtime are fully specified.

The configuration in the following code is used to create and initialize a database connection:

$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() is the most commonly used method in Yii2 The method to create an object, its content is the object taken from the DI Container, which we will talk about in the following chapters. This method accepts a configuration array and creates an object based on the class name specified in the array. After the object is instantiated, the remaining parameters are used to initialize the object's properties, events, and behaviors.

Editor’s reminder: In Yii2.1, the key value used to represent the class name in the configuration array has changed from class to __class, but The principle of configuration remains unchanged.

For existing objects, you can use the Yii::configure() method to initialize its properties according to the configuration, like this:

Yii::configure($object, $config);

Please note that if you configure an existing object object, then the configuration array should not contain a class element with the specified class name.

Configuration is a feature of Yii2

In programming, there is a very important concept called "deletion", which means that an object A can rely on another object B to complete a specific function. Typical The application is the strategy pattern. To implement "delegation", there must be such a process: when object A is instantiated, another object B is injected; A holds object B; object A delegates object B to complete a specific function. "Inject", "hold" and "delegate" are all high-frequency words in design patterns. Through these operations, the functions of a class can be extended.

Let’s take a look at the methods often used in other object-oriented languages ​​such as Java or PHP and other frameworks:

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();
    }
}

When instantiating or initializing, this is probably how it is used:

class Test{
    public function run($argument)
    {
        // 乘坐火车旅行
        $person = new Person(new TrainStrategy());        $person->travel();        // 改骑自行车
        $person->setTravelStrategy(new BicycleStrategy());        $person->travel();
    }
}

Person is a person who wants to travel, it holds a specific transportation method class$strategy, and the final travel is entrusted to this transportation method$strategy To complete it - whether it is riding a bicycle, traveling by car or flying. When using it, first create a new object, and inject a transportation method into the constructor to initialize the travel method, and I can also temporarily decide to change the travel method through Person::setTravelStrategy - this is the strategy pattern. Application scenarios.

Let’s take a look at this line:

$person = new Person(new TrainStrategy());

Everyone is familiar with this way of writing, right? In fact, this completes a two-step operation:

  • Instantiate the object Person by using new

  • Inject an external instancenew TrainStrategy() and initialize $person. What is injected can be an instance or a constant.

But according to the style of Yii2, it should be like this:

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();
    }
}

The usage is roughly like this:

//用配置创建对象并初始化,选择火车出行
$person = Yii::createObject([    'class' => Person::class,
    'travelStrategy' => [        'class' => TrainStrategy::class
    ]
]);
$person->travel();//用配置重新初始化对象,改骑自行车
$person = Yii::configure($person, [    'travelStrategy' => [        'class' => BicycleStrategy::class
    ]
]);
$person->travel();

The above example, It should help everyone understand the role and use of Yii2 configuration. The way to create objects is not through the new keyword, but obtained from the dependency injection container (DI Container), which we will talk about later.

The Yii2 framework does not seem to like to use "universal" instantiation and initialization methods. Within the Yii2 framework, object instantiation and initialization are almost always implemented through configuration. This is a style of Yii2. Of course, this style looks simpler (provided you are already familiar with it) and is more convenient to use. Although it looks different, it is still essentially the same, but there are some differences in the way of injection.

Configuration format

The format of a configuration can be described in the following form:

[    'class' => 'ClassName',    'propertyName' => 'propertyValue',    'on eventName' => $eventHandler,    'as behaviorName' => $behaviorConfig,
]

Among them, the

  • class element specifies The complete class name of the object to be created (this can be achieved using Object::class)

  • The propertyName element specifies the initial value of the object's writable property

  • on The eventName element specifies the handler attached to the object's event. Please note that the key name of the array consists of the on prefix plus the event name. There can be only one space between on and the event name

  • as The behaviorName element specifies the behavior attached to the object. Note that the array key name consists of the as prefix followed by the row name. There can be only one space between as and the action name. $behaviorConfig The value represents the configuration information of the created behavior, and the format is the same as the configuration format we described before.

The following is an example of configuring initialization property values, event handlers and behaviors:

[    'class' => 'app\components\SearchEngine',    'apiKey' => 'xxxxxxxx',    'on search' => function ($event) {
        Yii::info("搜索的关键词: " . $event->keyword);
    },    'as indexer' => [        'class' => 'app\components\IndexerBehavior',
        // ... 初始化属性值 ...
    ],
]

The principle of configuration implementation

We follow this By convention, you can instantiate and initialize objects through the configuration array:

  • Implement the Configurable interface. As long as you inherit BaseObject or Component, this is sufficient - no need to worry

  • 子类重载__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;

关于配置的东西,大概就是这么多了。

The above is the detailed content of Yii2 configuration basic concepts. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn