深入讲解PHP的Yii框架中的属性(Property),yiiproperty
在 PHP 中,类的成员变量也被称为属性(properties)。它们是类定义的一部分,用来表现一个实例的状态(也就是区分类的不同实例)。在具体实践中,常常会想用一个稍微特殊些的方法实现属性的读写。例如,如果有需求每次都要对 label 属性执行 trim 操作,就可以用以下代码实现:
$object->label = trim($label);
上述代码的缺点是只要修改 label 属性就必须再次调用 trim() 函数。若将来需要用其它方式处理 label 属性,比如首字母大写,就不得不修改所有给 label 属性赋值的代码。这种代码的重复会导致 bug,这种实践显然需要尽可能避免。
为解决该问题,Yii 引入了一个名为 yii\base\Object 的基类,它支持基于类内的 getter 和 setter(读取器和设定器)方法来定义属性。如果某类需要支持这个特性,只需要继承 yii\base\Object 或其子类即可。
补充:几乎每个 Yii 框架的核心类都继承自 yii\base\Object 或其子类。这意味着只要在核心类中见到 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 的属性,在这个例子里,它指向一个私有的内部属性 _label。)
getter/setter 定义的属性用法与类成员变量一样。两者主要的区别是:当这种属性被读取时,对应的 getter 方法将被调用;而当属性被赋值时,对应的 setter 方法就调用。如:
// 等效于 $label = $object->getLabel(); $label = $object->label; // 等效于 $object->setLabel('abc'); $object->label = 'abc';
只定义了 getter 没有 setter 的属性是只读属性。尝试赋值给这样的属性将导致 yii\base\InvalidCallException (无效调用)异常。类似的,只有 setter 方法而没有 getter 方法定义的属性是只写属性,尝试读取这种属性也会触发异常。使用只写属性的情况几乎没有。
通过 getter 和 setter 定义的属性也有一些特殊规则和限制:
这类属性的名字是不区分大小写的。如,$object->label 和 $object->Label 是同一个属性。因为 PHP 方法名是不区分大小写的。
如果此类属性名和类成员变量相同,以后者为准。例如,假设以上 Foo 类有个 label 成员变量,然后给 $object->label = 'abc' 赋值,将赋给成员变量而不是 setter setLabel() 方法。
这类属性不支持可见性(访问限制)。定义属性的 getter 和 setter 方法是 public、protected 还是 private 对属性的可见性没有任何影响。
这类属性的 getter 和 setter 方法只能定义为非静态的,若定义为静态方法(static)则不会以相同方式处理。
回到开头提到的问题,与其处处要调用 trim() 函数,现在我们只需在 setter setLabel() 方法内调用一次。如果 label 首字母变成大写的新要求来了,我们只需要修改setLabel() 方法,而无须接触任何其它代码。
实现属性的步骤
我们知道,在读取和写入对象的一个不存在的成员变量时, __get() __set() 会被自动调用。 Yii正是利用这点,提供对属性的支持的。从上面的代码中,可以看出,如果访问一个对象的某个属性, Yii会调用名为 get属性名() 的函数。如, SomeObject->Foo , 会自动调用 SomeObject->getFoo() 。如果修改某一属性,会调用相应的setter函数。 如, SomeObject->Foo = $someValue ,会自动调用 SomeObject->setFoo($someValue) 。
因此,要实现属性,通常有三个步骤:
- 继承自 yii\base\Object 。
- 声明一个用于保存该属性的私有成员变量。
- 提供getter或setter函数,或两者都提供,用于访问、修改上面提到的私有成员变量。 如果只提供了getter,那么该属性为只读属性,只提供了setter,则为只写。
如下的Post类,实现了可读可写的属性title:
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 为 ture 。那么只要类定义了成员变量,不管是public, private 还是 protected, 都认为是可写。
- Object和Component
yii\base\Component 继承自 yii\base\Object ,因此,他也具有属性等基本功能。
但是,由于Componet还引入了事件、行为,因此,它并非简单继承了Object的属性实现方式,而是基于同样的机制, 重载了 __get() __set() 等函数。但从实现机制上来讲,是一样的。这个不影响理解。
前面说过,官方将Yii定位于一个基于组件的框架。可见组件这一概念是Yii的基础。 如果你有兴趣阅读Yii的源代码或是API文档,你将会发现, Yii几乎所有的核心类都派生于(继承自) yii\base\Component 。
在Yii1.1时,就已经有了component了,那时是 CComponent。Yii2将Yii1.1中的CComponent拆分成两个类: yii\base\Object 和 yii\base\Component 。
其中,Object比较轻量级些,通过getter和setter定义了类的属性(property)。 Component派生自Object,并支持事件(event)和行为(behavior)。因此,Component类具有三个重要的特性:
- 属性(property)
- 事件(event)
- 行为(behavior)
相信你或多或少了解过,这三个特性是丰富和拓展类功能、改变类行为的重要切入点。 因此,Component在Yii中的地位极高。
在提供更多功能、更多便利的同时,Component由于增加了event和behavior这两个特性, 在方便开发的同时,也牺牲了一定的效率。 如果开发中不需要使用event和behavior这两个特性,比如表示一些数据的类。 那么,可以不从Component继承,而从Object继承。 典型的应用场景就是如果表示用户输入的一组数据,那么,使用Object。 而如果需要对对象的行为和能响应处理的事件进行处理,毫无疑问应当采用Component。 从效率来讲,Object更接近原生的PHP类,因此,在可能的情况下,应当优先使用Object。
您可能感兴趣的文章:
- PHP的Yii框架中移除组件所绑定的行为的方法
- PHP的Yii框架中行为的定义与绑定方法讲解
- 详解在PHP的Yii框架中使用行为Behaviors的方法
- PHP的Yii框架中使用数据库的配置和SQL操作实例教程
- 深入解析PHP的Yii框架中的event事件机制
- 全面解读PHP的Yii框架中的日志功能
- Yii使用find findAll查找出指定字段的实现方法
- 解析yii数据库的增删查改
- Yii PHP Framework实用入门教程(详细介绍)
- 详解PHP的Yii框架中组件行为的属性注入和方法注入

PHP는 전자 상거래, 컨텐츠 관리 시스템 및 API 개발에 널리 사용됩니다. 1) 전자 상거래 : 쇼핑 카트 기능 및 지불 처리에 사용됩니다. 2) 컨텐츠 관리 시스템 : 동적 컨텐츠 생성 및 사용자 관리에 사용됩니다. 3) API 개발 : 편안한 API 개발 및 API 보안에 사용됩니다. 성능 최적화 및 모범 사례를 통해 PHP 애플리케이션의 효율성과 유지 보수 성이 향상됩니다.

PHP를 사용하면 대화식 웹 컨텐츠를 쉽게 만들 수 있습니다. 1) HTML을 포함하여 컨텐츠를 동적으로 생성하고 사용자 입력 또는 데이터베이스 데이터를 기반으로 실시간으로 표시합니다. 2) 프로세스 양식 제출 및 동적 출력을 생성하여 htmlspecialchars를 사용하여 XSS를 방지합니다. 3) MySQL을 사용하여 사용자 등록 시스템을 작성하고 Password_Hash 및 전처리 명세서를 사용하여 보안을 향상시킵니다. 이러한 기술을 마스터하면 웹 개발의 효율성이 향상됩니다.

PHP와 Python은 각각 고유 한 장점이 있으며 프로젝트 요구 사항에 따라 선택합니다. 1.PHP는 웹 개발, 특히 웹 사이트의 빠른 개발 및 유지 보수에 적합합니다. 2. Python은 간결한 구문을 가진 데이터 과학, 기계 학습 및 인공 지능에 적합하며 초보자에게 적합합니다.

PHP는 여전히 역동적이며 현대 프로그래밍 분야에서 여전히 중요한 위치를 차지하고 있습니다. 1) PHP의 단순성과 강력한 커뮤니티 지원으로 인해 웹 개발에 널리 사용됩니다. 2) 유연성과 안정성은 웹 양식, 데이터베이스 작업 및 파일 처리를 처리하는 데 탁월합니다. 3) PHP는 지속적으로 발전하고 최적화하며 초보자 및 숙련 된 개발자에게 적합합니다.

PHP는 현대 웹 개발, 특히 컨텐츠 관리 및 전자 상거래 플랫폼에서 중요합니다. 1) PHP는 Laravel 및 Symfony와 같은 풍부한 생태계와 강력한 프레임 워크 지원을 가지고 있습니다. 2) Opcache 및 Nginx를 통해 성능 최적화를 달성 할 수 있습니다. 3) PHP8.0은 성능을 향상시키기 위해 JIT 컴파일러를 소개합니다. 4) 클라우드 네이티브 애플리케이션은 Docker 및 Kubernetes를 통해 배포되어 유연성과 확장 성을 향상시킵니다.

PHP는 특히 빠른 개발 및 동적 컨텐츠를 처리하는 데 웹 개발에 적합하지만 데이터 과학 및 엔터프라이즈 수준의 애플리케이션에는 적합하지 않습니다. Python과 비교할 때 PHP는 웹 개발에 더 많은 장점이 있지만 데이터 과학 분야에서는 Python만큼 좋지 않습니다. Java와 비교할 때 PHP는 엔터프라이즈 레벨 애플리케이션에서 더 나빠지지만 웹 개발에서는 더 유연합니다. JavaScript와 비교할 때 PHP는 백엔드 개발에서 더 간결하지만 프론트 엔드 개발에서는 JavaScript만큼 좋지 않습니다.

PHP와 Python은 각각 고유 한 장점이 있으며 다양한 시나리오에 적합합니다. 1.PHP는 웹 개발에 적합하며 내장 웹 서버 및 풍부한 기능 라이브러리를 제공합니다. 2. Python은 간결한 구문과 강력한 표준 라이브러리가있는 데이터 과학 및 기계 학습에 적합합니다. 선택할 때 프로젝트 요구 사항에 따라 결정해야합니다.

PHP는 서버 측에서 널리 사용되는 스크립팅 언어이며 특히 웹 개발에 적합합니다. 1.PHP는 HTML을 포함하고 HTTP 요청 및 응답을 처리 할 수 있으며 다양한 데이터베이스를 지원할 수 있습니다. 2.PHP는 강력한 커뮤니티 지원 및 오픈 소스 리소스를 통해 동적 웹 컨텐츠, 프로세스 양식 데이터, 액세스 데이터베이스 등을 생성하는 데 사용됩니다. 3. PHP는 해석 된 언어이며, 실행 프로세스에는 어휘 분석, 문법 분석, 편집 및 실행이 포함됩니다. 4. PHP는 사용자 등록 시스템과 같은 고급 응용 프로그램을 위해 MySQL과 결합 할 수 있습니다. 5. PHP를 디버깅 할 때 error_reporting () 및 var_dump ()와 같은 함수를 사용할 수 있습니다. 6. 캐싱 메커니즘을 사용하여 PHP 코드를 최적화하고 데이터베이스 쿼리를 최적화하며 내장 기능을 사용하십시오. 7


핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

VSCode Windows 64비트 다운로드
Microsoft에서 출시한 강력한 무료 IDE 편집기

드림위버 CS6
시각적 웹 개발 도구

WebStorm Mac 버전
유용한 JavaScript 개발 도구

안전한 시험 브라우저
안전한 시험 브라우저는 온라인 시험을 안전하게 치르기 위한 보안 브라우저 환경입니다. 이 소프트웨어는 모든 컴퓨터를 안전한 워크스테이션으로 바꿔줍니다. 이는 모든 유틸리티에 대한 액세스를 제어하고 학생들이 승인되지 않은 리소스를 사용하는 것을 방지합니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경
