yii 组件_Yii组件架构的内幕,第1部分

yii 组件

There’s been a lot of buzz surrounding the use of frameworks for quite a while now and there are many great PHP frameworks to choose from. I was blown away by the simplicity and power of the base CComponent class in the Yii framework. What does the class do?

相当长一段时间以来,围绕框架的使用一直存在大量讨论,并且有许多很棒PHP框架可供选择。 Yii框架中基本CComponent类的简单性和强大功能使我震惊。 这个班做什么?

  • Properties – adds getter and setter properties to classes

    属性 –将getter和setter属性添加到类

  • Configuration – enables an elegant class and application level cascading configuration system

    配置 –启用优雅的类和应用程序级联配置系统

  • Events – adds the ability to raise and call custom events

    事件 -增加了引发和调用自定义事件的能力

  • Behaviors – adds the ability to use behaviors (also called mix-ins)

    行为 –增加了使用行为的能力(也称为混合)

Every class in the framework extends from the CComponent class, which means that all subclasses work as components and can raise and handle events as well as be reusable and configurable. This packs a lot of punch for such a little class!

框架中的每个类都从CComponent类扩展而来,这意味着所有子类都可以作为组件工作,并且可以引发和处理事件以及可重用和可配置。 这样的一堂课给这本书带来了很多麻烦!

I’d like to share with you the core component that is at the heart of the Yii framework, and I’ve organized the tour of the CComponent class into three articles. In this article I’ll discuss how Yii utilizes PHP magic methods to create class properties and an elegant configuration system. In the next article I’ll discuss how you can use event-based programming and how the Yii component class implements this to make raising and handling events easy. The final article will walk through using behaviors (also called mix-ins), what they are, how you can use them, and how Yii implements them.

我想与您分享位于Yii框架核心的核心组件,并且我将CComponent类的浏览分为三篇文章。 在本文中,我将讨论Yii如何利用PHP魔术方法创建类属性和优雅的配置系统。 在下一篇文章中,我将讨论如何使用基于事件的编程以及Yii组件类如何实现此功能以使引发和处理事件变得容易。 最后一篇文章将逐步介绍行为的使用(也称为混合),它们是什么,如何使用它们以及Yii如何实现它们。

So let’s get started on our first topic.

因此,让我们开始第一个主题。

物产 (Properties)

A property defines a configurable aspect of a class; it exposes the class’ interface enabling you to manipulate it to do your bidding. For example, properties on an image uploader class might be the “file path”, and the “maximum allowed file size”. These properties can be exposed and manipulated by writing setter and getter methods such as setFilePath() and getFilePath(), or simply by adding a public property on the class like public $filePath.

属性定义了类的可配置方面; 它公开了类的界面,使您可以操纵它进行出价。 例如,图像上载器类的属性可能是“文件路径”和“最大允许文件大小”。 这些属性可以通过编写setter和getter方法(例如setFilePath()getFilePath()或通过在类上添加诸如public $filePath之类的公共属性来公开和操纵。

However, there is a small problem with this. If you define properties as public variables you potentially have many areas in your application that can refer to the property directly and you have no control over what other parts of the application may assign to it. When setting the filePath property I may want to check if it’s a valid path first and throw an error message if it’s not. In order to do this I need to create a setFilePath() method. Using $uploaderObject->filePath = "/file/path/" just doesn’t cut it.

但是,这有一个小问题。 如果将属性定义为公共变量,则您的应用程序中可能有很多区域可以直接引用该属性,而您无法控制应用程序的其他部分可以分配给它。 设置filePath属性时,我可能首先要检查它是否是有效路径,如果不是,则抛出错误消息。 为此,我需要创建一个setFilePath()方法。 使用$uploaderObject->filePath = "/file/path/"只是不会剪切它。

Yii’s component class implements the magic __get() and __set() functions which implements a devilishly simple convention allowing you to create getter and setter methods but still access properties as if they were public variables. Basically, Yii assumes a method starting with “get” or “set” is referring to a property with the same name as the method without the “get” or “set” prefix. This lets you easily expand your code at a later date. You can go ahead and add your public variables when you first start building your class; don’t worry about adding getter and setter methods. Then you can add getter and setter methods and make the original property private but you don’t have to refactor the rest of your code.

Yii的组件类实现了神奇的__get()__set()函数,该函数实现了一个非常简单的约定,允许您创建getter和setter方法,但仍然可以像访问公共变量一样访问属性。 基本上,Yii假定以“ get”或“ set”开头的方法所引用的属性与没有“ get”或“ set”前缀的方法同名。 这使您可以在以后轻松地扩展代码。 您可以在第一次开始构建类时继续添加公共变量。 不必担心添加getter和setter方法。 然后,您可以添加getter和setter方法并将原始属性设为私有,但不必重构其余代码。

<?php
echo $uploaderObject->filePath;

will actually call:

实际上会调用:

<?php
echo $uploader->getFilePath();

and using…

并使用...

<?php
$uploaderObject->filePath = "my/path";

will call:

将会通知:

<?php
$uploaderObject->setFilePath("my/path");

Of course you can still call the getFilePath() or setFilePath() directly too if you wanted to.

当然,如果您愿意,您仍然可以直接调用getFilePath()setFilePath()

Let’s take a look at how Yii achieves this.

让我们看看Yii如何实现这一目标。

Yii的魔术 (Yii’s Magic)

Diving into the CComponent class of Yii you’ll find the two magic methods responsible for this wizardry. Let’s start with the first __get() function.

深入到Yii的CComponent类中,您将找到负责此向导的两种魔术方法。 让我们从第一个__get()函数开始。

<?php
public function __get($name){
    $getter = "get" . $name;
    if (method_exists($this, $getter)) {
        return $this->$getter();
    }
    throw new CException("Property '$name' is not defined.");
}

When you call echo $uploader->filePath;, PHP looks for the public filePath property. If it doesn’t find it (or if it’s private), PHP will delegate to the magic method __get(). PHP calls the __get() function and passes it the name of the property. In this example, $name will store the value “filePath”. Then Yii does the following:

当你调用echo $uploader->filePath; ,PHP查找公共的filePath属性。 如果找不到它(或者它是私有的),PHP将委托给魔术方法__get() 。 PHP调用__get()函数并将其名称传递给它。 在此示例中, $name将存储值“ filePath”。 然后Yii执行以下操作:

  • Prepends the text “get” to the value of the $name variable and assigns this to the $getter variable, making $getter equal to “getfilePath” (remember, function names in PHP are case insensitive).

    将文本“ get”添加到$name变量的值之前,并将其分配给$getter变量,使$getter等于“ getfilePath”(请记住,PHP中的函数名称不区分大小写)。

  • Checks if there is a method called getfilePath() defined within this object.

    检查此对象中是否定义了名为getfilePath()的方法。

  • Calls the method if it exists. The code $this->$getter(); is really a call to $this->getfilePath() in this example.

    调用该方法(如果存在)。 代码$this->$getter(); 在此示例中,实际上是对$this->getfilePath()的调用。

  • If the method isn’t found then an exception will be thrown complaining, you guessed it, the property can’t be found.

    如果找不到该方法,那么您会猜到它会引发异常并抱怨,找不到该属性。

The same process is applied with the magic __set() function. When you assign setFilePath a value like so:

魔术__set()函数应用了相同的过程。 在为setFilePath分配一个值时,如下所示:

<?php
$uploader->filePath = 'my/path';

PHP searches first for the public property. If it doesn’t exist (or it’s private), PHP calls the magic __set() function. The __set() function works in a similar way to __get(), though PHP also passes the value you are setting, so $value would store “my/path” in the example.

PHP首先搜索公共属性。 如果它不存在(或者是私有的),PHP将调用魔术__set()函数。 __set()函数的工作方式与__get()相似,尽管PHP还会传递您所设置的值,因此$value将在示例中存储“ my / path”。

<?php
public function __set($name, $value) {
    $setter = "set" . $name;
    if (method_exists($this, $setter)) {
        return $this->$setter($value);
    }
    
    if (method_exists($this, "get" . $name)) {
        throw new CException("Property '$name' is read only.");
    }
    else {
        throw new CException("Property '$name' is not defined.");
    }
}

The implementation of the __set() function:

__set()函数的实现:

  • Prepends the value of $name with “set” and assigns this to $setter variable which becomes “setfilePath”.

    $name的值添加“ set”,并将其分配给$setter变量,该变量成为“ setfilePath”。

  • Checks if a method exists with the name setfilePath.

    检查是否存在名称为setfilePath

  • If the method exists, then it’s called like $this->setfilePath("my/path");.

    如果该方法存在,则称为$this->setfilePath("my/path");

  • If the set method doesn’t exist then a check is made if there is a getter method for the property. If there is then the property is read-only and an exception is thrown stating as much. If there is no getter and no setter method then an exception is thrown stating the property does not exist.

    如果set方法不存在,则检查该属性是否有getter方法。 如果存在,则该属性为只读,并抛出异常,说明异常。 如果没有getter且没有setter方法,则会引发异常,指出该属性不存在。

In only a few lines of code Yii has implemented a very nice property system based on using the PHP’s magic __get() and __set() functions.

Yii仅用几行代码就实现了非常好的属性系统,该系统基于使用PHP的魔术__get()__set()函数。

组态 (Configuration)

Another advantage to using this method of defining properties is that you can easily use arrays to configure your classes if you so desire:

使用这种定义属性的方法的另一个优点是,您可以根据需要轻松地使用数组来配置类:

<?php
$config = array(
    "myProperty" => 1234,
    "anotherProperty" => 5678);

You could configure your component class with the above array simply by doing the following:

您只需执行以下操作即可使用上述数组配置组件类:

<?php
foreach ($config as $property => $value) {
    $this->$property = $value;
}

The code uses the array keys as properties setting them to be equal to the value defined in the array. This is amazingly simple and is how Yii itself handles its application-level configuration. Here’s an example of a very basic demo Yii configuration file:

该代码使用数组键作为属性,将它们设置为等于数组中定义的值。 这非常简单,这就是Yii本身如何处理其应用程序级配置的方式。 这是一个非常基本的演示Yii配置文件的示例:

<?php
return array(
    "name" => "My Amazing App",
    "timezone" => "Europe/London",
    "components" => array(
        "db" => array(
            "username" => "root",
            "password" => ""
        ),
        "user" => array(
            "allowAutoLogin" => true
        )
    )
);

The array is passed to the Yii application class which then loops through each configuration key. The application class must have properties defined for “name”, “timezone”, and “components”.

该数组传递给Yii应用程序类,然后该类循环遍历每个配置键。 应用程序类必须具有为“名称”,“时区”和“组件”定义的属性。

<?php
class MyApplication extends CComponent
{
    public $name;
    public $timezone;

    public function setComponents(array $components) {
        // handle the array of components
    }
}

The components key calls a setComponents() function that expects an array. This function loads in each class and passes it its own array of configuration and so on until everything has its configuration properties set up. It’s Incredibly fast, completely non intrusive, and there’s no need for separate configuration methods scattered throughout your code.

组件键调用需要数组的setComponents()函数。 此函数在每个类中加载并传递其自己的配置数组,依此类推,直到所有内容都设置了其配置属性。 它的速度非常快,完全是非侵入性的,不需要在整个代码中散布单独的配置方法。

At a later date you can expand your class using setter and getter methods instead, if required.

日后,您可以根据需要使用setter和getter方法扩展类。

<?php
class MyApplication extends CComponent
{
    private $name;
    private $timezone;

    public setName($name) {
        // do something with the $name
    }

    public setTimezone($timezone) {
        // do something with $timezone
    }

    // TODO: Add getter functions 

    public function setComponents(array $components) {
        // handle the array of components
    }
}

摘要 (Summary)

In this article I’ve given you a quick snapshot of how magic methods are used in Yii’s component class to create properties and a simple but powerful configuration system. Of course Yii doesn’t stop there. It also implements the magic __isset() and __unset() methods, which means you can use isset() to determine if a property has a value and use unset() to destroy the property.

在本文中,我为您简要介绍了如何在Yii的组件类中使用魔术方法创建属性以及一个简单但功能强大的配置系统。 当然,Yii并不止于此。 它还实现了魔术__isset()__unset()方法,这意味着您可以使用isset()来确定属性是否具有值,并可以使用unset()销毁该属性。

In Part 2 I’ll talk about events, another key principle in creating highly reusable code in a component based architecture. I’ll show you how you can use event-based programming in PHP and how the Yii enables its subclasses of the component to raise and handle events.

在第2部分中,我将讨论事件,这是在基于组件的体系结构中创建高度可重用的代码的另一个关键原则。 我将向您展示如何在PHP中使用基于事件的编程,以及Yii如何启用组件的子类来引发和处理事件。

Image via Filipchuk Oleg Vasiliovich / Shutterstock

图片来自Filipchuk Oleg Vasiliovich / Shutterstock

翻译自: https://www.sitepoint.com/yii-under-the-hood-1/

yii 组件

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值