Разделы
Теги | RSS © 2008 – 2017
Контакты
email: igor@veselov.sumy.ua
skype: utz0r2
» » » Страница 5

4. Коротко ООП PHP - Магические методы (magic methods) __


Магиеские методы - "магия" данных методов сводится к тому, что они могут перехватывать (отсюда их второе название - методы-перехватчики) сообщения, посланные неопределенным (по сути - несуществующим) методам и свойствам
Всегда начинаются с двойного подчеркивания.
__construct() - этот метод запускается автоматически при созданнии экземпляра класса
__destruct() - метод запускается автоматически при уничтожении обьекта
__call(), __callStatic() - перехватывают обращение к несуществующему методу в контексте объекта и в статическом контексте
__get(), __set() - выполняется при чтении/записи данных из недоступных свойств
__isset() - будет выполнен при использовании isset() или empty() на недоступных свойствах
__unset() - будет выполнен при вызове unset() на недоступном свойстве
__sleep() - вызывается, когда объект подвергается сериализации при помощи функции serialize()
__wakeup() - вызывается при восстановлении объекта при помощи функции unserialize()
__toString() - метод, с помощью которого можно обращаться к классу как к строке
__invoke() - вызывается при попытке использовать объект в качестве функции
__set_state() - метод, который вызывается для классов, экспортирующих значения свойств функцией var_export()
__clone() - вызывается при клонировании объекта
__debugInfo() - метод вызывается функцией var_dump(), когда необходимо вывести список свойств объекта
<?php
class Car {

	function __construct() {
		echo 'Конструктор, вызывается автоматически во время создания экземпляра класса <br/>';
	}

	function __destruct() {
		echo 'Деструктор, вызывается автоматически во время уничтожения экземпляра класса <br/>';
	}

    function __call($name, $arguments) {
        // значение $name регистрозависимо
        echo "Вызов метода '$name' " . implode(', ', $arguments). "<br/>";
    }

    static function __callStatic($name, $arguments) {
        echo "Вызов статического метода '$name' " . implode(', ', $arguments). "<br/>";
    }

	function __get($param) {
		echo "Выполнить из за чтения данных из недоступных свойств: $param <br/>";
	}
	
	function __set($name, $value) {
		echo "Выполнить метод из за записи данных в недоступные свойства: $name -> $value <br/>";
		return $this->{$name} = $value; 
	}

    function __isset($name) {
        echo "Установлено ли '$name'? <br/>";
        // return isset($this->data[$name]);
    }

    function __unset($name) {
        echo "Уничтожение '$name' <br/>";
        // unset($this->data[$name]);
    }
	
	function __sleep() {
		echo "Объект подвергается сериализации при помощи функции serialize <br/>";
    }	
	
	// function __wakeup() {
		// echo "Объект подвергается восстановлении при помощи функции unserialize <br/>";
    // }	
	
	function __toString() {
		return "Мы вызвали " . __METHOD__ . "<br/>";
	}
	
	function __invoke($vars) {
		return "Нельзя вызывать класс как функцию <br/>";
	}
	
	function __set_state($an_array) {
		return print_r($an_array) . "<br/>";
	}

	function __clone()	{
		echo 'Вызывается при клонировании объекта <br/>';
	}

	function __debugInfo() {
		echo 'Вызывается при var_dump <br/>';
	}
	
}

$car = new Car();	// __construct
$car->runTest('в контексте объекта');	// __call
car::runTest('в статическом контексте объекта'); // __callStatic
$car->asdfasdf;	// __get
$car->asdfasdf = 'test';	// __set
isset($car->a); // __isset
isset($car->b); // __unset
$a = serialize($car); // __sleep
// unserialize($a); // __wakeup
echo $car; // __toString
echo $car('Пиу'); // __invoke
eval('$b = ' . var_export($car, true) . ';'); 
var_dump($b); // __set_state
$car2 = clone $car; // __clone
var_dump($car2); // __debugInfo

3. Коротко ООП PHP - Обьявление как статические (static) и финальные (final).


Объявление свойств и методов класса статическими позволяет обращаться к ним без создания экземпляра класса.
Финальные классы используются для запрета унаследования, а методы для запрета переопределения.
<?php
class Car {
	
	// доступ к статическим свойствам класса не может быть получен через оператор ->
	public static $name = 'БМВ';
	
	public static function run() {
		
		// псевдо-переменная $this не доступна внутри статического метода
		echo self::$name . ' Едь!';
		
	}
	
}

// final - класс CarAlien не может быть унаследован
final class CarAlien extends Car {
	
	// final - метод Hi не может быть переопределен
    final public static function run() {
		
		// псевдо-переменная $this не доступна внутри статического метода
		echo 'Мы приехали с миром '  .parent::$name . '!';
		
    }
	
}

echo Car::$name;

echo "<br/>";

Car::run();

echo "<br/>";

CarAlien::run();
Использовать статические функции класса можно, не создавая самого экземпляра класса - это экономит память.

2. Коротко ООП PHP - Принципы: инкапсуляция, полиморфизм, наследование


Обьект Car в жизни это слишком обобщенно. Поэтому создадим машины унаследовав родитель-класс Car (наследование), имзеним их свойства и методы при необходимости (полиморфизм), и ограничим области видимости свойств и методов с помощью спецификаторов доступа private, protected, public ( инкапсуляция(сокрытие внутренних процессов)).
<?php
class Car {

	const DOORS = 5;
	const TYPE = 'хетчбек';

	// инкапсуляция	(ограничили область видимости свойств odo только классом Car и его наследникми)
	protected $odo;
	
	public $fuel = 100;
	public $speed = 0;

	public function run( $speed = 0, $time = 0 ) {
		$this->speed = $speed;
		$this->odo = $speed*$time;
		return 'Движемся со скоростью: ' . $speed . ' км/ч. В течении '  .$time . ' часов <br/>';
	}

	public function stop() {
		$this->speed = 0;
		return 'Остановились, наша скорость: 0 км/ч <br/>' . $this->getOdo();
	}

	// инкапсуляция (ограничили область видимости метода getOdo только классом Car)
	private function getOdo () {
		return 'Проехали дистанцию: ' . $this->odo . ' км <br/>';
	}
	
}

// наследование (наследуем класс родитель Car)
class Zaz extends Car {
	
	// полиморфизм (переопределили константы DOORS и TYPE для Zaz)
	const DOORS = 4;
	const TYPE = 'седан';
	
	// полиморфизм (переопределили свойство $fuel)
	public $fuel = 40;

	// расширили новым методом zagloh только для класса Zaz 
	public function zagloh () {
		return 'Заглох... <br/>';
	}
	
}

// наследование (наследуем класс родитель Car)
class Amfibia extends Car {

	// полиморфизм (переопределили метод run, все остальное осталось от класса Car)
	public function run ( $speed = 0, $time = 0, $water = 0 ) {
		$this->speed = $water == 1? $speed/3 :	$speed;
		$this->odo = $this->speed*$time;
		return 'Движемся со скоростью: ' . $this->speed . ' км/ч. В течении '  .$time . ' часов <br/>';
	}
	
	// рашсирили родительский метод stop
	public function stop() {
		return 'Пшшшш... ' . parent::stop();
	}
	
}


// Cоздаем экземпляр объекта класса Zaz
$car = new Zaz();
echo 'У машины: ' . $car::DOORS . ' двери<br/>';
echo 'Тип машины: ' . $car::TYPE . '<br/>';
echo 'В баке: ' . $car->fuel . ' л топлива<br/>';
echo 'Текущая скорость машины: ' . $car->speed . ' км/ч<br/>';
echo $car->run();
echo $car->zagloh();
echo $car->run(60, 10);
echo $car->stop();

// Cоздаем экземпляр объекта класса Amfibia
$car2 = new Amfibia();
echo 'По воде: ' . $car2->run(60, 10, 1);
echo $car2->stop();

1. Коротко ООП PHP - Класс (class) и его объект (object)


Класс – это способ описания сущности. И по классу создается объект (экземпляр класса).
Если абстрогироваться еще больше, то класс - это чертеж автомобиля, а обьект - это сам автомобиль собраный по чертежу. Рассмотрим пример.
<?php
class Car {
	
	// константы
	const DOORS = 5;
	const TYPE = 'хетчбек';
	
	// свойства
	public $fuel = 100;
	public $speed = 0;
	public $odo;
	public $status = 'хорошее';
	
	// метод run ( имеет входные параметры скорость и время )
	public function run( $speed = 0, $time = 0 ) {
		// $this это обращение к переменной или методу в контексте класса
		$this->speed = $speed;
		$this->odo = $speed * $time;
		return 'Движемся со скоростью: ' . $speed . ' км/ч. В течении '  .$time . ' часов';
	}
	
	// метод stop
	public function stop() {
		$this->speed = 0;
		return 'Остановились, наша скорость: 0 км/ч';
	}

	// метод getOdo
	public function getOdo () {
		return 'Проехали дистанцию: ' . $this->odo . ' км';
	}
	
}

// Cоздаем экземпляр объекта класса Car
$car = new Car();

// Вызов констант
echo 'У машины: ' . $car::DOORS . ' дверей<br/>';
echo 'Тип машины: ' . $car::TYPE . ' <hr/>';

// Текущие свойства
echo 'В баке: ' . $car->fuel . ' л топлива<br/>';

// Операция над свойством
$car->fuel = $car->fuel/2; // Слили половину =)

echo 'Теперь в баке: ' . $car->fuel . ' л топлива<br/>';
echo 'Текущая скорость машины: ' . $car->speed . ' км/ч<hr/>';

// Выполнение методов
echo $car->run() . '<br/>';
echo $car->run(60,10) . '<br/>';
echo $car->stop() . '<br/>';
echo $car->getOdo();

0. Коротко ООП PHP - Плюсы и минусы


Начинаю серию постов под названием "Коротко ООП PHP". В цикле затрону основные моменты обьектно ориентированного программирования на PHP. А сегодня начнем с плюсов и минусов. Подразумевается, что вы вкурсе что такое PHP на уровне новичка.

Плюсы: помогает создавать более управляемые проекты за счет создания обьектов, сводит дублирование кода к минимуму, код более расширяем и структурирован. Тестируемый. И закрыт от внешнего мира.

Минусы: производительность, она ниже. Необходимо понимать базовые концепции. Проектирование классов не всегда просто, и скорей всего придеться переписывать, пока не научишся на ошибках. Документировать классы сложней, т.к. методы могут переопределяться. Иногда сложно понять какие поля и методы относятся к данному классу из за сложности ирархии классов и приходится просматривать весь код. В библиотечном классе часто содержится больше методов, чем это реально необходимо.

Цитата из книги, которая ставит все на место:
Процедурный код (код, использующий структуры данных) позволяет легко добавлять новые функции без изменения существующих структур данных. Объектно - ориентированный код, напротив, упрощает добавление новых классов без изменения существующих функций.
Обратные утверждения также истинны.
Процедурный код усложняет добавление новых структур данных, потому что оно требует изменения всех функций. Объектно-ориентированный код усложняет добавление новых функций, потому что для этого должны измениться все классы.
Таким образом, то, что сложно в ОО, просто в процедурном программировании, а то, что сложно в процедурном программировании, просто в ОО!

rinvex/country - php библиотека для получения данных о стране


// Get single country
$egypt = country('eg');

// Get country name                                 // Get country native name
echo $egypt->getName();                             echo $egypt->getNativeName();

// Get country official name                        // Get country ISO 3166-1 alpha2 code
echo $egypt->getOfficialName();                     echo $egypt->getIsoAlpha2();

// Get country area                                 // Get country borders
echo $egypt->getArea();                             echo $egypt->getBorders();

// Get country currencies                           // Get country languages
echo $egypt->getCurrencies();                       echo $egypt->getLanguages();

// Get country emoji                                // Get country flag
echo $egypt->getEmoji();                            echo $egypt->getFlag();


// Get all countries                                // Get countries with where condition (continent: Oceania)
$countries = countries();                           $whereCountries = \Rinvex\Country\Loader::where('geo.continent', ['OC' => 'Oceania']);

https://github.com/rinvex/country
«»
Вверх