Выбрать страницу

Функции обратного вызова важный, и нужный механизм языка. Первое, что приходит в голову при упоминании функций обратного вызова – это пользовательская сортировка массивов (например, usort()). Но, это лишь незначительная часть возможностей этого механизма.

Функции обратного вызова позволяют добавить к объекту новые функциональные возможности.

Для примера возьмем некоторый класс:

class ProductClass {
	private $price=0;
	private $quantity=0;
	public function setPrice($price) {
		$this->price=$price;
	}
	public function getPrice() {
		return $this->price;
	}
	public function setQuantity($quantity) {
		$this->quantity =$quantity;
	}
	public function getQuantity(){
		return $this->quantity;
	}
}

Класс хороший замечательный, но со временем, что цента товара может зависеть от количества продаваемого товара. В данной реализации нам придется или переписывать метод getPrice,или наследовать от этого класса другой и в нем переопределять этот метод. Но есть и более удобный способ ,если мы в методе предусмотрим использование функции обратного вызова, то все что нам понадобиться – это просто написать эту функцию и использовать ее при вызове нашего метода.

Например, так:

class ProductClass {
	private $price=0;
	private $quantity=0;
	public function setPrice($price) {
		$this->price=$price;
	}
	public function getPrice($callback=null) {
		$price=$this->price;
		if (isset($callback)){
			if (!is_callable($callback)){
				throw new Exception('Функция не может быть вызвана');
			}
			$price=call_user_func($callback,$this->price,$this->quantity);
		}
		return $price;
	}
	public function setQuantity($quantity) {
		$this->quantity =$quantity;
	}
	public function getQuantity(){
		return $this->quantity;
	}
}

function discount_1($price,$quantity){
		return $price-2;
}

$discount_2=create_function('$price,$quantity', 'return $quantity>5?$price*0.9:$price;');

$discount_3=function($price,$quantity){
	return $quantity>5?$price*0.8:$price;
}

$product=new ProductClass();
$product->setPrice(100);
$product->setQuantity(10);
echo "Price: ".$product->getPrice()."\n";
echo "Price 1: ".$product->getPrice('discount_1')."\n";
echo "Price 2: ".$product->getPrice($discount_2)."\n";
echo "Price 3: ".$product->getPrice($discount_3)."\n";

Мы добавили в метод получения цены функцию обратного вызова. И определи три различных функции вычисления цены, тремя различными способами. Последний функция discount_3 способ стал доступен начиная с PHP 5.3, с помощью такого синтаксиса стало удобнее создавать анонимные функции.

Предусмотрев возможность использования функций обратного вызова, мы можем не изменяя основной класс изменить поведение методов так как нам необходимо.

Если рассматривать практические применения, то можно вспомнить о CMS Joomla, реализация плагинов в ней как раз основана на механизме функций обратного вызова. Фактический каждый плагин является функцией обратного вызова.

Было опубликовано 21 декабря 2012 на php-example.ru

Share This