cari
Rumahpembangunan bahagian belakangtutorial phpYii中的属性(Property)详解

Yii中的属性(Property)详解

Dec 29, 2017 pm 07:04 PM
propertyharta bendaPenjelasan terperinci

本文主要介绍了PHP的Yii框架中的属性(Property),详细地说明了实现属性的步骤,需要的朋友可以参考下。希望对大家有所帮助。

在 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。

相关推荐:

Yii运行机制及路由详解

Yii如何隐藏URL中index.php

PHP Yii框架之数据库查询操作总结

Atas ialah kandungan terperinci Yii中的属性(Property)详解. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Apakah beberapa masalah biasa yang boleh menyebabkan sesi PHP gagal?Apakah beberapa masalah biasa yang boleh menyebabkan sesi PHP gagal?Apr 25, 2025 am 12:16 AM

Sebab -sebab kegagalan phpsession termasuk kesilapan konfigurasi, isu cookie, dan tamat tempoh sesi. 1. Ralat Konfigurasi: Semak dan tetapkan session.save_path yang betul. Masalah 2.Cookie: Pastikan kuki ditetapkan dengan betul. 3.Session Expires: Laraskan Nilai Sesi.GC_MAXLifetime untuk melanjutkan masa sesi.

Bagaimanakah anda menyebarkan isu berkaitan sesi dalam PHP?Bagaimanakah anda menyebarkan isu berkaitan sesi dalam PHP?Apr 25, 2025 am 12:12 AM

Kaedah untuk masalah sesi debug dalam PHP termasuk: 1. Periksa sama ada sesi dimulakan dengan betul; 2. Sahkan penghantaran ID sesi; 3. Semak penyimpanan dan bacaan data sesi; 4. Semak konfigurasi pelayan. Dengan mengeluarkan ID dan data sesi, melihat kandungan fail sesi, dan lain-lain, anda boleh mendiagnosis dan menyelesaikan masalah yang berkaitan dengan sesi.

Apa yang berlaku jika session_start () dipanggil beberapa kali?Apa yang berlaku jika session_start () dipanggil beberapa kali?Apr 25, 2025 am 12:06 AM

Pelbagai panggilan ke session_start () akan menghasilkan mesej amaran dan kemungkinan penggantian data. 1) PHP akan mengeluarkan amaran, menyebabkan sesi telah dimulakan. 2) Ia boleh menyebabkan penggantian data sesi yang tidak dijangka. 3) Gunakan session_status () untuk memeriksa status sesi untuk mengelakkan panggilan berulang.

Bagaimana anda mengkonfigurasi seumur hidup sesi di PHP?Bagaimana anda mengkonfigurasi seumur hidup sesi di PHP?Apr 25, 2025 am 12:05 AM

Mengkonfigurasi kitaran hayat sesi dalam PHP boleh dicapai dengan menetapkan sesi.gc_maxlifetime dan session.cookie_lifetime. 1) session.gc_maxlifetime mengawal masa survival data sesi pelayan, 2) session.cookie_lifetime mengawal kitaran hayat kuki klien. Apabila ditetapkan ke 0, kuki tamat apabila penyemak imbas ditutup.

Apakah kelebihan menggunakan pangkalan data untuk menyimpan sesi?Apakah kelebihan menggunakan pangkalan data untuk menyimpan sesi?Apr 24, 2025 am 12:16 AM

Kelebihan utama menggunakan sesi penyimpanan pangkalan data termasuk kegigihan, skalabilitas, dan keselamatan. 1. Kegigihan: Walaupun pelayan dimulakan semula, data sesi tidak dapat berubah. 2. Skalabiliti: Berkenaan dengan sistem yang diedarkan, memastikan data sesi disegerakkan di antara pelbagai pelayan. 3. Keselamatan: Pangkalan data menyediakan storan yang disulitkan untuk melindungi maklumat sensitif.

Bagaimana anda melaksanakan pengendalian sesi tersuai di PHP?Bagaimana anda melaksanakan pengendalian sesi tersuai di PHP?Apr 24, 2025 am 12:16 AM

Melaksanakan pemprosesan sesi tersuai dalam PHP boleh dilakukan dengan melaksanakan antara muka sessionHandlerInterface. Langkah -langkah khusus termasuk: 1) mewujudkan kelas yang melaksanakan sessionHandlerInterface, seperti CustomSessionHandler; 2) kaedah penulisan semula dalam antara muka (seperti terbuka, rapat, membaca, menulis, memusnahkan, gc) untuk menentukan kitaran hayat dan kaedah penyimpanan data sesi; 3) Daftar pemproses sesi tersuai dalam skrip PHP dan mulakan sesi. Ini membolehkan data disimpan dalam media seperti MySQL dan REDIS untuk meningkatkan prestasi, keselamatan dan skalabiliti.

Apakah ID Sesi?Apakah ID Sesi?Apr 24, 2025 am 12:13 AM

SesionID adalah mekanisme yang digunakan dalam aplikasi web untuk mengesan status sesi pengguna. 1. Ia adalah rentetan yang dijana secara rawak yang digunakan untuk mengekalkan maklumat identiti pengguna semasa pelbagai interaksi antara pengguna dan pelayan. 2. Pelayan menjana dan menghantarnya kepada klien melalui kuki atau parameter URL untuk membantu mengenal pasti dan mengaitkan permintaan ini dalam pelbagai permintaan pengguna. 3. Generasi biasanya menggunakan algoritma rawak untuk memastikan keunikan dan ketidakpastian. 4. Dalam pembangunan sebenar, pangkalan data dalam memori seperti REDIS boleh digunakan untuk menyimpan data sesi untuk meningkatkan prestasi dan keselamatan.

Bagaimanakah anda mengendalikan sesi dalam persekitaran tanpa kerakyatan (mis., API)?Bagaimanakah anda mengendalikan sesi dalam persekitaran tanpa kerakyatan (mis., API)?Apr 24, 2025 am 12:12 AM

Menguruskan sesi dalam persekitaran tanpa kerakyatan seperti API boleh dicapai dengan menggunakan JWT atau cookies. 1. JWT sesuai untuk ketiadaan dan skalabilitas, tetapi ia adalah saiz yang besar ketika datang ke data besar. 2.Cookies lebih tradisional dan mudah dilaksanakan, tetapi mereka perlu dikonfigurasikan dengan berhati -hati untuk memastikan keselamatan.

See all articles

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

Video Face Swap

Video Face Swap

Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Alat panas

Penyesuai Pelayan SAP NetWeaver untuk Eclipse

Penyesuai Pelayan SAP NetWeaver untuk Eclipse

Integrasikan Eclipse dengan pelayan aplikasi SAP NetWeaver.

DVWA

DVWA

Damn Vulnerable Web App (DVWA) ialah aplikasi web PHP/MySQL yang sangat terdedah. Matlamat utamanya adalah untuk menjadi bantuan bagi profesional keselamatan untuk menguji kemahiran dan alatan mereka dalam persekitaran undang-undang, untuk membantu pembangun web lebih memahami proses mengamankan aplikasi web, dan untuk membantu guru/pelajar mengajar/belajar dalam persekitaran bilik darjah Aplikasi web keselamatan. Matlamat DVWA adalah untuk mempraktikkan beberapa kelemahan web yang paling biasa melalui antara muka yang mudah dan mudah, dengan pelbagai tahap kesukaran. Sila ambil perhatian bahawa perisian ini

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

VSCode Windows 64-bit Muat Turun

VSCode Windows 64-bit Muat Turun

Editor IDE percuma dan berkuasa yang dilancarkan oleh Microsoft