Yii는 대규모 웹 애플리케이션 개발을 위한 고성능 구성 요소 기반 PHP 프레임워크입니다. Yii는 엄격한 OOP로 작성되었으며 완전한 라이브러리 참조와 포괄적인 튜토리얼을 갖추고 있습니다. MVC, DAO/ActiveRecord, 위젯, 캐싱, 계층적 RBAC, 웹 서비스부터 테마 설정, I18N 및 L10N까지 Yii는 오늘날의 Web 2.0 애플리케이션 개발에 필요한 거의 모든 것을 제공합니다. 실제로 Yii는 가장 효율적인 PHP 프레임워크 중 하나입니다.
Yii는 고성능 PHP5 웹 애플리케이션 개발 프레임워크입니다. 간단한 명령줄 도구인 yiic은 웹 애플리케이션 코드 프레임워크를 신속하게 생성할 수 있습니다. 개발자는 생성된 코드 프레임워크를 기반으로 비즈니스 로직을 추가하여 애플리케이션 개발을 신속하게 완료할 수 있습니다.
PHP에서는 클래스의 멤버 변수를 속성이라고도 합니다. 이는 클래스 정의의 일부이며 인스턴스의 상태를 나타내는 데 사용됩니다(즉, 클래스의 다른 인스턴스를 구별하기 위해). 특정 실습에서는 속성을 읽고 쓰기 위해 약간 특별한 방법을 사용하려는 경우가 많습니다. 예를 들어, label 속성에 대해 매번 트림 작업을 수행해야 하는 경우 다음 코드를 사용하여 이를 수행할 수 있습니다.
$object->label = trim($label);
위 코드의 단점은 label 속성이 수정되는 한 트림( ) 함수를 다시 호출해야 합니다. 앞으로 첫 글자를 대문자로 표기하는 등 다른 방식으로 label 속성을 처리해야 한다면 label 속성에 값을 할당하는 코드를 모두 수정해야 할 것입니다. 이러한 코드 중복은 버그로 이어질 수 있으므로 가능하면 이러한 관행을 피해야 합니다.
이 문제를 해결하기 위해 Yii는 클래스 내의 getter 및 setter(판독기와 설정기) 메서드를 기반으로 속성 정의를 지원하는 yiibaseObject라는 기본 클래스를 도입합니다. 클래스가 이 기능을 지원해야 하는 경우 yiibaseObject 또는 해당 하위 클래스만 상속하면 됩니다.
보충 사항: Yii 프레임워크의 거의 모든 핵심 클래스는 yiibaseObject 또는 해당 하위 클래스에서 상속됩니다. 즉, 핵심 클래스에서 getter 또는 setter 메서드를 볼 때마다 이를 속성처럼 호출할 수 있습니다.
Getter 메서드는 이름이 get으로 시작하는 메서드이고, setter 메서드 이름은 set으로 시작하는 메서드입니다. 메소드 이름에서 get 또는 set 뒤의 부분이 속성의 이름을 정의합니다. 다음 코드에 표시된 대로 getter 메소드 getLabel() 및 setter 메소드 setLabel()은 label 속성에 대해 작동합니다.
namespace app\components; use yii\base\Object; class Foo extend Object { private $_label; public function getLabel() { return $this->_label; } public function setLabel($value) { $this->_label = trim($value); } }
(자세한 설명: getter 및 setter 메소드는 label이라는 속성을 생성합니다. 이 예에서는 Points 개인 내부 속성 _label.)
getters/setters로 정의된 속성은 클래스 멤버 변수와 동일한 방식으로 사용됩니다. 둘 사이의 주요 차이점은 이 속성을 읽을 때 해당 getter 메서드가 호출되고 속성에 값이 할당되면 해당 setter 메서드가 호출된다는 것입니다. 예:
// 等效于 $label = $object->getLabel(); $label = $object->label; // 等效于 $object->setLabel('abc'); $object->label = 'abc';
getter만 정의하고 setter는 정의하지 않는 속성은 읽기 전용 속성입니다. 이러한 속성에 할당을 시도하면 yiibaseInvalidCallException(잘못된 호출) 예외가 발생합니다. 마찬가지로, getter 메서드 없이 setter 메서드만 사용하여 정의된 속성은 쓰기 전용 속성이며, 이러한 속성을 읽으려고 하면 예외가 발생합니다. 쓰기 전용 속성을 사용하는 경우는 거의 없습니다.
getter 및 setter를 통해 정의된 속성에는 몇 가지 특별한 규칙과 제한 사항도 있습니다.
그러한 속성의 이름은 대소문자를 구분하지 않습니다. 예를 들어 $object->label과 $object->Label은 동일한 속성입니다. PHP 메소드 이름은 대소문자를 구분하지 않기 때문입니다.
이 유형의 속성 이름이 클래스 멤버 변수와 동일한 경우 후자가 우선합니다. 예를 들어, 위의 Foo 클래스에 label 멤버 변수가 있고 $object->label = 'abc'에 값을 할당하면 setter setLabel() 메서드 대신 멤버 변수에 할당된다고 가정합니다.
이 유형의 속성은 가시성(액세스 제한)을 지원하지 않습니다. 속성의 getter 및 setter 메서드가 공개, 보호 또는 비공개인지 여부는 속성의 가시성에 영향을 주지 않습니다.
이 속성 유형의 getter 및 setter 메서드는 비정적으로만 정의할 수 있습니다. 정적 메서드(정적)로 정의하면 동일한 방식으로 처리되지 않습니다.
처음에 언급한 질문으로 돌아가서, 어디서나 Trim() 함수를 호출하는 대신 이제 setter setLabel() 메서드 내에서 한 번만 호출하면 됩니다. 레이블의 첫 글자를 대문자로 사용해야 하는 새로운 요구 사항이 있는 경우 다른 코드를 건드리지 않고 setLabel() 메서드만 수정하면 됩니다.
속성 구현 단계
우리는 객체의 존재하지 않는 멤버 변수를 읽고 쓸 때 __get() __set()이 자동으로 호출된다는 것을 알고 있습니다. Yii는 이를 활용하여 속성에 대한 지원을 제공합니다. 위 코드에서 객체의 특정 속성에 액세스하면 Yii가 getpropertyname()이라는 함수를 호출하는 것을 볼 수 있습니다. 예를 들어 SomeObject->Foo는 자동으로 SomeObject->getFoo()를 호출합니다. 속성이 수정되면 해당 setter 함수가 호출됩니다. 예를 들어 SomeObject->Foo = $someValue는 자동으로 SomeObject->setFoo($someValue)를 호출합니다.
그래서 속성을 구현하려면 일반적으로 세 단계를 거쳐야 합니다.
yiibaseObject에서 상속됩니다.
이 속성을 저장하려면 전용 멤버 변수를 선언하세요.
위에 언급된 비공개 멤버 변수에 액세스하고 수정하기 위한 getter, setter 함수 또는 둘 다를 제공하세요. getter만 제공되면 속성은 읽기 전용이고, setter만 제공하면 속성은 쓰기 전용입니다.
다음 Post 클래스는 읽기 및 쓰기 가능한 속성 제목을 구현합니다.
class Post extends yii\base\Object // 第一步:继承自 yii\base\Object { private $_title; // 第二步:声明一个私有成员变量 public function getTitle() // 第三步:提供getter和setter { return $this->_title; } public function setTitle($value) { $this->_title = trim($value); } }
从理论上来讲,将 private $_title 写成 public $title ,也是可以实现对 $post->title 的读写的。但这不是好的习惯,理由如下:
失去了类的封装性。 一般而言,成员变量对外不可见是比较好的编程习惯。 从这里你也许没看出来,但是假如有一天,你不想让用户修改标题了,你怎么改? 怎么确保代码中没有直接修改标题? 如果提供了setter,只要把setter删掉,那么一旦有没清理干净的对标题的写入,就会抛出异常。 而使用 public $title 的方法的话,你改成 private $title 可以排查写入的异常,但是读取的也被禁止了。
对于标题的写入,你想去掉空格。 使用setter的方法,只需要像上面的代码段一样在这个地方调用 trim() 就可以了。 但如果使用 public $title 的方法,那么毫无疑问,每个写入语句都要调用 trim() 。 你能保证没有一处遗漏?
因此,使用 public $title 只是一时之快,看起来简单,但今后的修改是个麻烦事。 简直可以说是恶梦。这就是软件工程的意义所在,通过一定的方法,使代码易于维护、便于修改。 一时看着好像没必要,但实际上吃过亏的朋友或者被客户老板逼着修改上一个程序员写的代码,问候过他亲人的, 都会觉得这是十分必要的。
但是,世事无绝对。由于 __get() 和 __set() 是在遍历所有成员变量,找不到匹配的成员变量时才被调用。 因此,其效率天生地低于使用成员变量的形式。在一些表示数据结构、数据集合等简单情况下,且不需读写控制等, 可以考虑使用成员变量作为属性,这样可以提高一点效率。
另外一个提高效率的小技巧就是:使用 $pro = $object->getPro() 来代替 $pro = $object->pro , 用 $objcect->setPro($value) 来代替 $object->pro = $value 。 这在功能上是完全一样的效果,但是避免了使用 __get() 和 __set() ,相当于绕过了遍历的过程。
这里估计有人该骂我了,Yii好不容易实现了属性的机制,就是为了方便开发者, 结果我却在这里教大家怎么使用原始的方式,去提高所谓的效率。 嗯,确实,开发的便利性与执行高效率存在一定的矛盾。我个人的观点更倾向于以便利为先, 用好、用足Yii为我们创造的便利条件。至于效率的事情,更多的是框架自身需要注意的, 我们只要别写出格外2的代码就OK了。
不过你完全可以放心,在Yii的框架中,极少出现 $app->request 之类的代码,而是使用 $app->getRequest() 。 换句话说,框架自身还是格外地注重效率的,至于便利性,则留给了开发者。 总之,这里只是点出来有这么一个知识点,至于用不用,怎么用,完全取决于你了。
值得注意的是:
由于自动调用 __get() __set() 的时机仅仅发生在访问不存在的成员变量时。 因此,如果定义了成员变量 public $title 那么,就算定义了 getTitle() setTitle() , 他们也不会被调用。因为 $post->title 时,会直接指向该 pulic $title , __get() __set() 是不会被调用的。从根上就被切断了。
由于PHP对于类方法不区分大小写,即大小写不敏感, $post->getTitle() 和 $post->gettitle() 是调用相同的函数。 因此, $post->title 和 $post->Title 是同一个属性。即属性名也是不区分大小写的。
由于 __get() __set() 都是public的, 无论将 getTitle() setTitle() 声明为 public, private, protected, 都没有意义,外部同样都是可以访问。所以,所有的属性都是public的。
由于 __get() __set() 都不是static的,因此,没有办法使用static 的属性。
Object的其他与属性相关的方法
除了 __get() __set() 之外, yii\base\Object 还提供了以下方法便于使用属性:
__isset() 用于测试属性值是否不为 null ,在 isset($object->property) 时被自动调用。 注意该属性要有相应的getter。
__unset() 用于将属性值设为 null ,在 unset($object->property) 时被自动调用。 注意该属性要有相应的setter。
hasProperty() 用于测试是否有某个属性。即,定义了getter或setter。 如果 hasProperty() 的参数 $checkVars = true (默认为true), 那么只要具有同名的成员变量也认为具有该属性,如前面提到的 public $title 。
canGetProperty() 测试一个属性是否可读,参数 $checkVars 的意义同上。只要定义了getter,属性即可读。 同时,如果 $checkVars 为 true 。那么只要类定义了成员变量,不管是public, private 还是 protected, 都认为是可读。
canSetProperty()는 속성이 쓰기 가능한지 테스트합니다. $checkVars 매개변수의 의미는 위와 동일합니다. setter가 정의되어 있으면 속성을 쓸 수 있습니다. 동시에 $checkVars는 true입니다. 그런 다음 클래스가 멤버 변수를 정의하는 한 공개, 비공개 또는 보호 여부에 관계없이 쓰기 가능한 것으로 간주됩니다.
Object 및 Component
yiibaseComponent는 yiibaseObject를 상속하므로 속성과 같은 기본 기능도 갖습니다.
그러나 Component도 이벤트와 동작을 도입하므로 단순히 Object의 속성 구현 방법을 상속하는 것이 아니라 동일한 메커니즘을 기반으로 __get(), __set()과 같은 함수를 오버로드합니다. 그러나 구현 메커니즘 측면에서는 동일합니다. 이는 이해에 영향을 미치지 않습니다.
앞서 언급했듯이 Yii는 공식적으로 컴포넌트 기반 프레임워크로 자리잡고 있습니다. 눈에 보이는 구성 요소의 개념은 Yii의 기초입니다. Yii의 소스 코드나 API 문서를 읽는 데 관심이 있다면 Yii의 거의 모든 핵심 클래스가 yiibaseComponent에서 파생(상속)된다는 것을 알 수 있습니다.
Yii1.1에는 이미 CComponent라는 컴포넌트가 있었습니다. Yii2는 Yii1.1의 CComponent를 yiibaseObject와 yiibaseComponent의 두 클래스로 분할합니다.
그 중 Object는 상대적으로 가볍고 getter와 setter를 통해 클래스의 속성을 정의합니다. 구성 요소는 개체에서 파생되며 이벤트와 동작을 지원합니다. 따라서 Component 클래스에는 세 가지 중요한 기능이 있습니다.
property
event
behavior
이 세 가지 기능은 클래스 변경의 중요한 진입점인 클래스 기능을 풍부하게 하고 확장하는 것입니다. 행동. 따라서 Yii에서는 컴포넌트의 위상이 매우 높습니다.
컴포넌트는 더 많은 기능과 편의성을 제공하는 동시에 이벤트와 동작의 두 가지 기능을 추가하여 개발을 촉진하는 동시에 효율성을 희생했습니다. 일부 데이터를 나타내는 클래스 등 개발 중에 이벤트와 동작의 두 가지 기능을 사용할 필요가 없는 경우. 그런 다음 Component 대신 Object에서 상속할 수 있습니다. 일반적인 애플리케이션 시나리오는 사용자가 입력한 데이터 집합을 나타내는 경우 Object를 사용하는 것입니다. 그리고 객체의 동작과 처리에 응답할 수 있는 이벤트를 처리해야 한다면 Component를 사용해야 한다는 것은 의심의 여지가 없습니다. 효율성 측면에서는 Object가 기본 PHP 클래스에 더 가깝기 때문에 가능하면 Object를 먼저 사용해야 합니다.
관련 추천:
Yii2.0 프레임워크 소개 및 실제 프로젝트 개발 동영상 튜토리얼
위 내용은 PHP Yii 프레임워크의 속성의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!