Profruit banner

Умен звънец в openHAB

16 декември 2023

Телефонът е винаги с мен и сега, където и да се намирам получавам известие от openHAB, че някой е позвънил и чака пред вратата. А ако ме няма вкъщи става ясно часа и датата на последното позвъняване.

Tasmota Multipress

30 септември 2023

Идеята е Sonoff Touch T1 US 2 в салона, да управлява освен своето осветление и това в кухнята, а още вентилатора.

DIY 12V 1A WiFi Router UPS

22 април 2023

При поредно прекъсване на захранването вкъщи, батерията на нoтбука и двата UPS автоматично превключват на аварийно захранване и едновременно полита съобщение за конфуза

Zigbee2MQTT клониране

21 януари 2023

... как да клонираме съществуваща настройка на Zigbee2MQTT без да се налага последвало интервю на zigbee-устройствата.

LD2410 - бюджетен датчик присъствие в openHAB

11 февруари 2023

Цената на HLK-LD2410 зададе име на поредната тема в моя блог. С негова помощ се постига "народен" датчик присъствие в домашната автоматизация. . ...

Клониране на обект в PHP

PHP4
$obj1 = $obj2; //copy - клониране на обекта
$obj1 = &$obj2; //link - един и същи обект под различно име

PHP5
$obj1 = clone $obj2; //copy - клониране на обекта
$obj1 = $obj2; //link - един и същи обект под различно име

Въведение

PHP4 не предлага никаква възможност за копиране на обектите, освен стандартния. Той е бит по бит - 1:1 на всички свойства на обекта.
В PHP4 копиране на обекта става много просто. Достатъчно е да се присвои значението на една обектна променлива към нова такава.
Пример:
<?php
 class Originale { //PHP4 }

 $first = new Originale; 
 $second = $first;
Променливите $second и $first указват на два различни обекта.

Практиката показала непрактичност при такъв подход. Например, обект, представляващ съединение с база данни или обекти, чийто свойства са обекти, а още обекти, изграждащи дървовидни структури. Това накарало разработчиците, да въведат в PHP5 ключова дума clone.
Пример:
<?php
 class Originale { //PHP5 }

 $first = new Originale; 
 $second = clone $first;
Променливите $second и $first указват на два различни обекта.

Когато копие на обекта се прави с clone в PHP5, PHP автоматически проверява за наличие на магически метод __clone. Липсата му ще накара PHP, да създаде обикновено копие на обекта. Ако магическия метод е определен, то PHP ще го изпълни едва след като копира всички свойства от оригинала.

PHP версия от командна линия

За прозрачност на темата, нека узнаем версия PHP на разположение чрез терминала. Въвеждаме просто php -v.

profruit@prodesktop:~$ php -v
PHP 5.3.2-1ubuntu4.18 with Suhosin-Patch (cli)
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies

От теория към практика

С поредица от примери нека видим как работят нещата.

clone.class.php
<?php
 class original {
  public $var;
 }

object.php
<?php
include('clone.class.php');
 $first = new original;
 
 $first->var = 1;
 $second = $first;

 echo $first->var, '<br>'; //1
 echo $second->var;        //1
Нека разместим нещата и погледнем отново на резултата.
<?php
include('clone.class.php');
 $first = new original;
 
 $first->var = 1;
 $second = $first;
 
 $second->var = 2;

 echo $first->var, '<br>'; //2
 echo $second->var;        //2
Имаме един и същи обект под различно име. Изменението в коя да е инстанция рефлектира на другата по същия начин. Напомням, че сме под PHP 5.3.2.

Дойде ред на същинско клониране
<?php
include('clone.class.php');
$first = new original;
 
 $first->var = 1;
 $second = clone $first;

 echo $second->var, '<br>'; //1

 $second->var = 2;

 echo $first->var, '<br>'; //1
 echo $second->var;        //2
Клонирането на обект originale води до създаване на ново копие. Всички свойства с техните значения са преминали в клонирания обект. Особеност при клониране на обекта е, че конструктора не се извиква, в което убеждава поредния пример.
<?php
class Originale {

 public $var;

 function __construct() {
  $this->var = __CLASS__;
  echo 'конструктор на клас '. $this->var;
 }
}

$first = new Originale;
$second = clone $first;
Резултатът от изпълнението печати в браузъра само веднъж конструктор на клас Originale.

Това говори, че конструктора е извикан само от създаването на обект new Originale, независимо, че е създаден нов обект $second. Разрешението на подобна нужда, разработчиците предлагат магически метод __clone().

__clone() носи идеята на __construct()

Метод __clone() не приема параметър. Ако такъв е описан PHP автоматически го
привежда в действие и само за клонинга. Пример:
<?php
class Originale {

 public $var;

 function __construct() {
  $this->var = __CLASS__;
  echo "конструктор на клас  {$this->var} <br>";
 }
 
  function __clone() {
  echo 'обектът клониран от '. $this->var;
 }
}

$first = new Originale;
$second = clone $first;
Резултатът от изпълнението печати в браузъра следните два реда:
конструктор на клас Originale
обектът клониран от Originale

Става ясно, че това което прави конструктора при създаване на обект е по силите на магически метод __clone в момента на клониране.

И поредна особеност. Ако ви засърбят ръцете, да извикате конструктора по този начин:

$first = new Originale;
echo $first->__construct();


Може и ще работи, но ще се приеме за моветон.
Това обаче не работи:

echo $second->__clone();

PHP ще възнегодува с следното съобщение:
Fatal error: Cannot call __clone() method on objects





до нови срещи   ^.^
29.09.2012 profruit 

|

0 Response to "Клониране на обект в PHP"

Публикуване на коментар

Този блог е реинкарнация на първите ми опити за споделяне в нета. На времето започнах с къси разкази на преживяното. После се обезсмисли и превърнах блога си в системно радио. Пиша единствено неща, които карат душата ми да живее: openHAB, Ubuntu, Споделено и т.н. Това е моето системно радио, разбирате ли? Моята вълна и вие сте на нея сега.

Архив на блога