ООП PHP
Магические методы
Магические методы: php.net
Магические методы - это методы, которые вызываются не явно, то есть они вызываются автоматически,
например: методы __construct() и __destruct().
Метод __toString()
__toString() - этот метод позволяет классу решать как он будет реагировать при преобразовании в строку.
Есть объект класса BookProduct, внутри этого класса есть метод getProduct(), который выводит информацию о продукте, выведем его с помощью echo, так как там - return $out:
echo $book -> getProduct();
Если-же мы попытаемся вывести: echo $book;, то браузер выведет ошибку: "объект $book не может быть преобразован в строку". Операторы echo, print выводят строку, а $book - объект!.
Однако, мы можем использовать метод __toString(), который будет решать, что делать с объектом, который мы пытаемся преобразовать в строку. Объявим такой метод в классе BookProduct:
...
public function __toString()
{
// echo 'Hello <br>'; // проверяем, что метод работает
return 'Hello <br>';
// - можно сразу вернуть
// - теперь в браузере выводится "Hello", и ошибки нет,
// то есть отрабатывает метод __toString()
return $this -> getProduct();
// - возвращаем результат работы метода getProduct()
}
...
- когда мы пытаемся работать с объектом, как со строкой (вывести его, как строку), тогда PHP ищет магический метод __toString() и выполняет его. Мы можем вернуть пустое значение: return 'Hello <br>'; и ничего не произойдет, а можно сделать и что-нибудь полезное, например, вернуть результат работы метода getProduct() И у нас получается, что запись echo $book; является полным аналогом записи echo $book -> getProduct();
Файл BookProduct.php:
-- файл BookProduct.php --
<?php
namespace ;
use \ \ ;
use \ ;
class extends implements
{
public $numPages;
public $action1;
public $action2;
public function ($name, $price, $numPages)
{
parent :: ($name, $price);
$this -> numPages = $numPages;
$this -> (5);
}
// объявляем магический метод __toString()
public function
{
//echo 'Hello <br>';
//return 'Hello <br>';
// - можно сразу вернуть
// теперь в браузере выводится "Hello", и ошибки нет,
// то есть отрабатывает метод __toString()
return $this -> ();
// - возвращаем результат работы метода getProduct()
}
public function ()
{
}
public function ()
{
$out = parent :: ();
$out .= "Цена без скидки: {$this -> price}<br>";
$out .= "Кол-во страниц:: {$this -> cpu}<br>";
$out .= "Скидка: {$this -> ()}%<br>";
return $out;
}
public function ()
{
return $this -> numPages;
}
public function ($name, $price, $numePage=0)
{
// --------------------------
($name);
($price);
($numePage);
}
}
?>
Файл index.php:
-- файл index.php --
<?php
use \{ , };
use \ \{ , };
(-1);
require_once . '/vendor/autoload.php';
function ($data)
{
echo '<pre>' . ($data, 1 ) . '</pre>';
}
function ($product)
{
echo "<p>Предлагаем чехол для гаджета {$product -> ()} </p>";
}
$book = new ('Три мушкетера', 20, 1000);
$notebook = new ('Dell', 1000, 'Intel' );
// Метод __toString() ---------------
// Есть объект класса BookProduct, внутри этого класа есть метод getProduct(),
// который выводит информацию о продукте;
// выведем его (с помощью echo, так как там - return $out;)
echo $book -> ();
// Если мы попытаемся работать с объектом как со строкой, то будет вызван
// магический метод __toString(), который в свою очередь вызывает
// метод getProduct.
// И получаем, что запись echo $book - является полным аналогом
// записи echo $book->getProduct
echo $book;
?>
Получим:
Результат работы echo $book->getProduct():
О товаре:
Наименование: Три мушкетера
Цена со скидкой: 19
Цена без скидки: 20
Кол-во страниц: 1000
Скидка: 5%
Результат работы echo $book:
О товаре:
Наименование: Три мушкетера
Цена со скидкой: 19
Цена без скидки: 20
Кол-во страниц: 1000
Скидка: 5%
Методы __get() и __set()
__get() и __set() - это аналоги гетеров и сетеров, только вызываются они "магически".
Эти методы предназначены для работы со свойствами, которые не были объявленны в классе или родителе класса.
Метод __get() вызывается, когда мы обращаемся к неопределенному свойству.
Метод __set() вызывается, когда мы пытаемся присвоить что-то неопределенному свойству.
Вызовем в индексном файле тестовое свойство: $book->test = 'Hello' - в браузере оно появляется, хотя в классе это свойство нами не было предусмотрено, что не всегда хорошо, поскольку мы можем случайно обратиться к этому свойству.
Что-бы этого не происходило, можно использовать "магические методы" __get() и __set().
В классе BookProduct объявим эти методы:
__get() - этот метод принимает в себя один параметр - это имя свойства ($name), которое мы хотим получить (такого свойства нет):
public function __get($name)
{
var_dump($name);
}
__set() - этод метод имеет два параметра: имя неопределенного свойства ($name), к которому мы обращаемся, и его значение ($value):
public function __set($name, $value)
{
var_dump($name, $value);
return ;
}
После обновления странички в браузере, мы видим, что свойство "Hello" - пропало, оно уже не было динамически создано для объекта, но отработал метод __set() и метод __get().
выведет:
string 'test' (length=4)
- имя неопределенного свойства (работа метода __set($name, $value))
string 'HELLO' (length=5)
- его значение (работа метода __set($name, $value))
string 'test' (length=4)
- имя неопределенного свойства, к которому мы пытаемся обратиться (работа метода __get($name))
Эти методы можно использовать по желанию: можно ничего не делать (return), можно логировать какую-нибудь ошибку, можно использовать патерн программирования, например - реестр, и записать какое-то свойство в массив и затем с ним работать и т. д.
Например, для метода __get():
В классе Product есть метод getName(), при этом свойство $name является приватным (private $name).
Файл Product.php:
-- файл Product.php --
<?php
namespace ;
abstract class
{
private $name; // приватное свойство $name
protected $price ;
private $discount = 0;
...
...
...
// метод getName()
public function ()
{
return $this -> name;
}
...
...
...
}
?>
- попробуем к нему обратиться (в индексном файле):
echo $book->name;
При этом отрабатывает метод __get()(в классе BookProduct) и в браузере получаем: string(4) "name".
Если закоментировать метод __get(), то в браузере отобразится ошибка.
В методе __get() (в классе BookProduct) создадим переменную:
$method = "get{$name}"
- все наши гетеры начинаются на get, а в переменную $name параметром - приходит имя того свойства, к которому мы хотим обратиться, в данном случае - приходит name.
Выведем ее в браузере, получим - getname.
Первую букву приводим к верхнему регистру:
$name = ucfirst($name);
Проверяем, есть ли у нас такой метод программно:
if(method_exists($this, $method)),
- первым параметром эта функция принимает объект того класса, которого мы хотим проверить,
- на этот объект ссылается псевдопеременная $this;
- вторым параметром - наименование метода, который хранится у нас в переменной $method.
То есть, функция method_exists($this, $method) проверяет: есть-ли метод $method у объекта $this.
- Если есть - возвращаем результат работы этого метода: return $this -> $method();
- А если нет - тогда мы ничего не делаем.
В результате в браузере получим - "Три мушкетера".
При обращении к неопределенному свойству (это свойство (name) хоть и есть у класса, но оно приватное ), мы вызываем магический метод __get() и описываем какую-нибудь логику.
Файл BookProduct.php:
-- файл BookProduct.php --
<?php
namespace ;
use \ \ ;
use \ ;
class extends implements
{
public $numPages;
public $action1;
public $action2;
public function ($name, $price, $numPages)
{
parent :: ($name, $price);
$this -> numPages = $numPages;
$this -> (5);
}
// объявляем магический метод __toString()
public function ()
{
return $this -> ();
// возвращаем результат работы метода getProduct()
}
// объявляем магический метод __get()
// - этот метод принимает в себя один параметр - это имя свойства ($name),
// которое мы хотим получить.
public function ($name)
{
($name);
//echo $method = "get{$name}"; // выведет getname
// проверка наличия метода $method и его вызов при обращении к
// неопределенному свойству
$name = ($name);
// - приводим первую букву к верхнему регистру (n -> N)
$method = "get{$name}"; // создадим переменную
// проверяем, есть ли у нас такой метод программно
if( ($this, $method))
// Первым параметром эта функция принимает объект того класса, которого
// мы хотим проверить. На этот объект ссылается псевдопеременная $this.
// Вторым параметром - наименование метода, который хранится у нас
// в переменной $method.
// То есть, функция method_exists($this, $method) проверяет:
// есть-ли метод $method у объекта $this.
{
// если есть - возвращаем результат работы этого метода
return $this -> $method();
}
}
// объявляем магический метод __set()
// - этод метод имеет два параметра: имя неопределенного свойства ($name),
// к которому мы обращаемся, и его значение ($value)
public function ($name, $value)
{
($name, $value);
return;
}
public function ()
{
}
public function ()
{
$out = parent :: ();
$out .= "Цена без скидки: {$this -> price}<br>";
$out .= "Кол-во страниц:: {$this -> cpu}<br>";
$out .= "Скидка: {$this -> ()}%<br>";
return $out;
}
public function ()
{
return $this -> numPages;
}
public function ($name, $price, $numePage=0)
{
// --------------------------
($name);
($price);
($numePage);
}
}
?>
Файл index.php:
-- файл index.php --
<?php
use \{ , };
use \ \{ , };
(-1);
require_once . '/vendor/autoload.php';
function ($data)
{
echo '<pre>' . ($data, 1 ) . '</pre>';
}
function ($product)
{
echo "<p>Предлагаем чехол для гаджета {$product -> ()} </p>";
}
$book = new ('Три мушкетера', 20, 1000);
$notebook = new ('Dell', 1000, 'Intel');
//offerCase($notebook);
// __get() и __set() --------------------------------------
// добавляем тестовое свойство (работа метода __set())
//$book->test='HELLO';
//debug($book);
// обращаемся к несуществующему свойству (работа метода __get())
//echo $book->test;
// обращение к приватному свойству name (работа метода __get())
echo $book -> name;
?>
Получим:
Три мушкетера
Содержание папки 16 ("Магические методы"):
Наверх Наверх