Klon von Objekten
Durchlauf von Objekten
Serialisierung und Deserialisierung von Objekten
Verwendung integrierter Standardklassen
Merkmale Verwendung
Verwandte Funktionen von Klassen und Objekten
PHP-Reflexionsmechanismus
Die Objektorientierung von PHP ist ein wichtiger Wissenspunkt, und seine Ideen ziehen sich durch den gesamten Prozess unserer Entwicklung. Es gibt einige Wissenspunkte in der Objektorientierung, die wir verstehen müssen, wie z. B. die Eigenschaften des Objektklonens und der Objektdurchquerung sowie der Objektserialisierung und -deserialisierung. Wenn Sie ein PHP-Framework schreiben möchten, müssen Sie auch über PHP nachdenken .
Wenn wir ein Objekt erstellen, wird ein Speicherplatz im Speicher zugewiesen, und der Objektname verweist auf diesen Speicherplatz. Wir haben über die Zuweisung gesprochen Wenn ein Objekt die darin enthaltenen Daten ändert, ändern sich auch die Daten des anderen Objekts entsprechend, da die Zuweisung dem Zuweisen einer Kopie der Objektkennung entspricht, das Klonen jedoch nicht.
<?php class Person{ public $name; public $age; public $sex; public function __construct($name,$age,$sex){ $this -> name = $name; $this -> age = $age; $this -> sex = $sex; } public function getName(){ return $this -> name; } public function getAge(){ return $this -> age; } public function getSex(){ return $this -> sex; } } $a = new Person('宋江','45','男'); echo '<pre class="brush:php;toolbar:false">'; $b = clone $a; $b -> name = '武松'; var_dump($a); var_dump($b);
Ergebnis
Die Syntax des Objektklonens:
$新对象 = clone $就对象;
Wie aus den obigen Ergebnissen ersichtlich ist, an Objekt Datenänderungen wirken sich nicht auf die Daten eines anderen Objekts aus. Durch das Klonen von Objekten wird ein völlig neues Objekt erstellt. Es kann wie folgt verstanden werden:
Unter den magischen Methoden von PHP gibt es eine magische Methode im Zusammenhang mit dem PHP-Klonen, __clone() Wenn der Kopiervorgang abgeschlossen ist Es ist in der Klasse definiert. Wenn die magische Methode __clone() verwendet wird, ruft das neu erstellte oder kopierte Objekt diese __clone()-Methode auf. In dieser Methode können Sie bei Bedarf einige Änderungen an den Attributen vornehmen.
Wenn Sie nicht möchten, dass ein Objekt geklont wird, können Sie die magische Methode __clone() intern als privat definieren. Wenn Sie zu diesem Zeitpunkt klonen, werden Sie zur Eingabe von
< aufgefordert 🎜>Call to private Peoson::__clone() from context ''
foreach(对象名 as $key => $val){ //$key是属性名,$val是属性值 }
<?php class Person{ public $name; public $age; private $sex; public function __construct($name,$age,$sex){ $this -> name = $name; $this -> age = $age; $this -> sex = $sex; } } $person = new Person('孙悟空',256,'男'); foreach ($person as $key => $value) { echo $key . ' = ' . $value . '<br>'; } .......结果........ name = 孙悟空 age = 256
<?php class Person{ public $name; public $age; private $sex; public function __construct($name,$age,$sex){ $this -> name = $name; $this -> age = $age; $this -> sex = $sex; } } $person = new Person('孙悟空',256,'男'); //使用file_put_contents()函数把将一个字符串写入文件 file_put_contents('D:person.txt', serialize($person));
Nachdem Sie den obigen Code ausgeführt haben, können Sie sehen, dass sich auf dem Laufwerk D eine Datei „person.txt“ befindet, die ein in eine Zeichenfolge konvertiertes Objekt enthält.
<?php class Person{ public $name; public $age; private $sex; public function __construct($name,$age,$sex){ $this -> name = $name; $this -> age = $age; $this -> sex = $sex; } } //通过file_get_contents这个方法把一个文件读取到字符串。 $str = file_get_contents('D:person.txt'); //进行反序列化。 $person = unserialize($str); echo '<pre class="brush:php;toolbar:false">'; var_dump($person); ......结果...... object(Person)#1 (3) { ["name"]=> string(9) "孙悟空" ["age"]=> int(256) ["sex":"Person":private]=> string(3) "男" }
<?php $person = new StdClass(); $person -> name = '孙悟空'; $person -> age = 524; $person -> sex = '男'; echo '<pre class="brush:php;toolbar:false">'; var_dump($person); ......结果...... object(stdClass)#1 (3) { ["name"]=> string(9) "孙悟空" ["age"]=> int(524) ["sex"]=> string(3) "男" }
traits使用语法:
trait 自定义名称{ //额外定义的代码 } 在类中使用格式 use 自定义的名称;
代码:
<?php //使用trait,自定义名称 trait my_code{ public function minus($num1,$num2){ return $num1 - $num2; } } class A{ public function plus($num1,$num2){ return $num1 + $num2; } } class B extends A{ //使用trait定义的代码块 use my_code; } class C extends A{ use my_code; } class D extends A{ } $b = new B(); $c = new C(); $d = new D(); echo $b -> plus(1,2); echo '<br>'; echo $b -> minus(2,1); echo '<br>'; echo $d -> plus(1,2); echo '<br>'; echo $d -> minus(2,1); ......结果...... 3 1 3 Fatal error: Call to undefined method D::minus() in D:\mywamp\Apache24\htdocs\zendstudio\yunsuanfu\staits.php on line 36
在上面代码中类D没有使用trait代码,所以在使用minus方法时,出现错误。
当我们在trait中写的函数和父类的函数一样时,以trait代码为准,即trait代码的优先级高于继承的类。
在PHP中系统提供了一系列的函数来判断类和对象的。从帮助文档中可以看到好多函数:
在这里我们只对里面的几个函数进行了解。
<?php class Person{ public $name; public $age; private $sex; public function __construct($name,$age,$sex){ $this -> name = $name; $this -> age = $age; $this -> sex = $sex; } public function showInfo(){ echo '名字是:' . $this -> name . ',年龄是:' . $this -> age . ',性别是:' . $this -> sex . '<br>'; } } //判断是否创建了对象,没有创建返回true,创建返回false。 if(class_exists('Person')){ $person = new Person('唐僧',25,'男'); //返回对象的类名 echo '类名是: ' . get_class($person) . '<br>'; //判断方法是否存在。 if(method_exists($person, 'showInfo')){ $person -> showInfo(); }else{ echo '该方法不存在'; } //判断属性是否存在 if(property_exists($person,'name')){ echo $person -> name; }else{ echo '属性不存在'; } }else{ echo '类不存在'; } ......结果...... 类名是: Person 名字是:唐僧,年龄是:25,性别是:男 唐僧
使用类和对象函数,可以保证我们代码的完整性,对出错信息进行及时的捕获输出。
在很多编程语言中都有反射这种概念,反射简单理解就是通过类,获取里面的属性,方法,甚至注释也可以,不管属性和方法的访问修饰符是什么类型都可以获取到。
在PHP 5中具有完整的反射API,添加了对类、接口、函数、方法和扩展进行反向工程的能力。此外,反射 API 提供了方法来取出函数、类和方法中的文档注释。而我们在开发中一般是使用不到反射的,但是在某些情况下使用反射可以更好的处理问题,比如我们需要我们写框架底层,扩展功能,管理大量的未知类。
定义一个类,通过反射创建对象和调用里面的方法:
<?php class Dog{ public $name; protected $age; private $food; public function __construct($name, $age, $food){ $this->name = $name; $this->age = $age; $this->food = $food; } public function cry($sound){ echo '<br> ' . $this->name . ' 叫声是.' . $sound; } } //使用反射完成对象的创建和方法调用 //1. 创建一个反射对象 $reflect_obj = new ReflectionClass('Dog'); //2. 通过反射对象创建Dog对象实例 $dog = $reflect_obj->newInstance('大黄狗', 4, '排骨'); echo '<pre class="brush:php;toolbar:false">'; var_dump($dog); //3. 调用方法-使用代理方式. $reflect_method_cry = $reflect_obj->getMethod('cry'); echo '<pre class="brush:php;toolbar:false">'; var_dump($reflect_method_cry); //4. 代理调用cry $reflect_method_cry->invoke($dog, '汪汪');
结果:
在上面代码中,我们通过new创建了一个反射的对象,在反射对象里面通过newInstance()方法得到类的对象。获取里面的方法可以使用反射对象的getMethod()方法,返回来的是一个方法对象ReflectionMethod类,通过里面的invoke()方法执行该方法。这里只是基本的介绍,可以查找帮助文档了解更多的反射对象和方法。
需求:
有一个类IndexAction,其中的方法和访问控制修饰符是不确定的, 1. 如果index 方法是public,可以执行 _before_index. 2. 如果存在_before_index 方法,并且是public的,执行该方法 3. 执行test方法 4. 再判断有没有_after_index方法,并且是public的,执行该方法
代码:
<?php class IndexAction{ public function index(){ echo 'index<br>'; } public function _before_index(){ echo '_before_index方法执行 <br>'; } public function test($data){ echo 'data : ' . $data . '<br>'; } public function _after_index(){ echo '_after_index方法执行<br>'; } } if(class_exists('IndexAction')){ //创建对象 $reflectionClass = new ReflectionClass('IndexAction'); //判断index是否存在 if($reflectionClass -> hasMethod('index')){ //获取index方法对象 $reflec_index_method = $reflectionClass -> getMethod('index'); //判断修饰符是否是public if($reflec_index_method -> isPublic()){ //判断是否有_before_index方法 if($reflectionClass -> hasMethod('_before_index')){ $reflec_before_method = $reflectionClass -> getMethod('_before_index'); //判断是否是public if($reflec_before_method -> isPublic()){ $reflec_before_method -> invoke($reflectionClass -> newInstance()); //调用test()方法 $reflectionClass -> getMethod('test') -> invoke($reflectionClass -> newInstance(),'这是test的数据'); //判断是否有_after_index方法 if($reflectionClass -> hasMethod('_after_index')){ $reflec_after_method = $reflectionClass -> getMethod('_after_index'); //判断是否是public if($reflec_after_method -> isPublic()){ //执行_after_index方法 $reflec_after_method -> invoke($reflectionClass -> newInstance()); }else{ echo '_after_index不是public修饰的'; } }else{ echo '没有_after_index方法'; } }else{ echo '_before_index修饰符不是public'; } }else{ echo '没有_before_index方法'; } }else{ echo 'index方法不是public修饰'; } }else{ echo 'index方法不存在'; } }else{ echo '类名不存在'; } ......结果....... _before_index方法执行 data : 这是test的数据 _after_index方法执行
在上面的代码中可以看到我们不停地在判断类中有没有某个方法,是不是public修饰,然后执行,我们可以利用封装的思想,把一些共性的特征抽取出来写成一个函数。从而对我们的代码进行优化。
优化的代码:
<?php class IndexAction{ public function index(){ echo 'index<br>'; } public function _before_index(){ echo '_before_index方法执行 <br>'; } public function test($data){ echo 'data : ' . $data . '<br>'; } public function _after_index(){ echo '_after_index方法执行<br>'; } } if(class_exists('IndexAction')){ $reflectionClass = new ReflectionClass('IndexAction'); //创建IndexAction对象。 $indexAction = $reflectionClass -> newInstance(); execute($reflectionClass,$indexAction,'index'); execute($reflectionClass,$indexAction,'_after_index'); execute($reflectionClass,$indexAction,'test','test使用的数据'); execute($reflectionClass,$indexAction,'_after_index'); }else{ echo '没有IndexAction方法'; } //封装的函数 /** * [execute description]对反射的封装。 * @param [type] $reflect_obj [description]反射对象 * @param [type] $worker [description]类对象 * @param [type] $name [description]方法的名字 * @param [type] $canshu [description]方法的参数 * @return boolean [description] */ function execute($reflect_obj,$indexAction,$name,$param = ''){ if($reflect_obj-> hasMethod($name)){ $method = $reflect_obj->getMethod($name); if($method->isPublic()){ $method->invoke($indexAction,$param); }else{ echo $name . '不是public'; } }else{ echo $name . '方法不存在'; } } ......结果..... index _after_index方法执行 data : test使用的数据 _after_index方法执行
可以看到进行功能的封装,可以简化我们的代码,同时代码看起来更加的清晰。
PHP的面向对象的内容到这里算是讲完了,在开发中利用面向对象的思想进行开发是一定要掌握的技能。同时也要对面向对象进行深度的了解。
以上就是PHP,反射、对象序列化的内容,更多相关内容请关注PHP中文网(www.php.cn)!