说明:本文主要学习PHP的回调类型callback type,一般在使用函数进行回调时,如使用call_user_func($callback, $parameters)进行回调时,须要传入回调callback,实际上有几种callback type的,在Laravel中也大量使用回调,并根据场景不一样传入不一样的回调类型。php
开发环境:Laravel5.3 + PHP7
laravel
Function Callback Type是把函数名做为callable类型传进去做为回调类型,形式如:($function_name, $dependency)
。Static Class Method Callable Type与其相似,是把类名+静态方法名传进去做为回调类型,形式如:("$class_name::$static_method_name", $dependency)
。看下PHPUnit测试,看看如何使用callback type,爆绿灯:segmentfault
<?php namespace MyRightCapital\Container\Tests; class Callback extends \PHPUnit_Framework_TestCase { public function testFunctionCallback() { // Arrange $expected = 'container'; // Actual $actual = call_user_func('MyRightCapital\Container\Tests\functionCallback', 'container'); // ($function_name, $dependency) // Assert $this->assertSame($expected, $actual); } public function testStaticClassMethodCallback() { // Arrange $expected = 'container'; // Actual $actual = call_user_func('MyRightCapital\Container\Tests\StaticClassMethodCallback::staticClassMethod', 'container'); // ("$class_name::$static_method_name", $dependency) // Assert $this->assertSame($expected, $actual); } } function functionCallback($app) { return $app; } class StaticClassMethodCallback { public static function staticClassMethod($app) { return $app; } }
Class Method Callback Type也是类名+静态方法名,只不过形式稍不同,形式如:([$class_name, $method_name], $dependency)。Relation Class Method Callback Type是能够使用父类的方法传进去做为回调,形式如:([$class_name, "parent::$method_name"], $dependency)。写个PHPUnit测试看下使用:api
public function testClassMethodCallback() { // Arrange $expected = 'container'; // Actual $actual = call_user_func([ClassMethodCallback::class, 'classMethod'], 'container'); // ([$class_name, $method_name], $dependency) // Assert $this->assertSame($expected, $actual); } public function testRelationClassMethodCallback() { // Arrange $expected = 'container/container'; // Actual $actual = call_user_func([ClassMethodCallback::class, 'parent::classMethod'], 'container'); // ([$class_name, "parent::$method_name"], $dependency) // Assert $this->assertSame($expected, $actual); } class ClassMethodCallback extends ParentClassMethodCallback { public static function classMethod($app) { return $app; } } class ParentClassMethodCallback { public static function classMethod($app) { return $app . '/' . $app; } }
Object Method Callback Type是把对象方法做为参数传进去做为回调,形式如:([$object, $method_name], $dependency),写个PHPUnit测试:app
public function testObjectMethodCallback() { // Arrange $class_method_callback = new ClassMethodCallback(); $expected = 'container'; // Actual $actual = call_user_func([$class_method_callback, 'objectMethod'], 'container'); // ([$object, $method_name], $dependency) // Assert $this->assertSame($expected, $actual); } class ClassMethodCallback extends ParentClassMethodCallback { public static function classMethod($app) { return $app; } public function objectMethod($app) { return $app; } }
把Closure做为参数传进去做为回调参数这种方式在Laravel中大量使用,好比Laravel的Pipeline源码就大量使用这种方式,Pipeline的源码可看:Laravel学习笔记之Middleware源码解析。写下PHPUnit测试看下:函数
public function testClosureCallback() { // Arrange // Actual $actual = call_user_func(getClosure(), 'stack', 'pipe'); $actual_value = call_user_func($actual, 'request'); // Assert $this->assertInstanceOf(\Closure::class, $actual); $this->assertSame('request/stack/pipe', $actual_value); } function getClosure() { return function ($stack, $pipe) { return function ($passable) use ($stack, $pipe) { return $passable . '/' . $stack . '/' . $pipe; }; }; }
最后,给出整个源码和测试结果:学习
<?php namespace MyRightCapital\Container\Tests; class Callback extends \PHPUnit_Framework_TestCase { public function testFunctionCallback() { // Arrange $expected = 'container'; // Actual $actual = call_user_func('MyRightCapital\Container\Tests\functionCallback', 'container'); // ($function_name, $dependency) // Assert $this->assertSame($expected, $actual); } public function testStaticClassMethodCallback() { // Arrange $expected = 'container'; // Actual $actual = call_user_func('MyRightCapital\Container\Tests\StaticClassMethodCallback::staticClassMethod', 'container'); // ("$class_name::$static_method_name", $dependency) // Assert $this->assertSame($expected, $actual); } public function testClassMethodCallback() { // Arrange $expected = 'container'; // Actual $actual = call_user_func([ClassMethodCallback::class, 'classMethod'], 'container'); // ([$class_name, $method_name], $dependency) // Assert $this->assertSame($expected, $actual); } public function testRelationClassMethodCallback() { // Arrange $expected = 'container/container'; // Actual $actual = call_user_func([ClassMethodCallback::class, 'parent::classMethod'], 'container'); // ([$class_name, "parent::$method_name"], $dependency) // Assert $this->assertSame($expected, $actual); } public function testObjectMethodCallback() { // Arrange $class_method_callback = new ClassMethodCallback(); $expected = 'container'; // Actual $actual = call_user_func([$class_method_callback, 'objectMethod'], 'container'); // ([$object, $method_name], $dependency) // Assert $this->assertSame($expected, $actual); } public function testClosureCallback() { // Arrange // Actual $actual = call_user_func(getClosure(), 'stack', 'pipe'); $actual_value = call_user_func($actual, 'request'); // Assert $this->assertInstanceOf(\Closure::class, $actual); $this->assertSame('request/stack/pipe', $actual_value); } } function getClosure() { return function ($stack, $pipe) { return function ($passable) use ($stack, $pipe) { return $passable . '/' . $stack . '/' . $pipe; }; }; } function functionCallback($app) { return $app; } class StaticClassMethodCallback { public static function staticClassMethod($app) { return $app; } } class ClassMethodCallback extends ParentClassMethodCallback { public static function classMethod($app) { return $app; } public function objectMethod($app) { return $app; } } class ParentClassMethodCallback { public static function classMethod($app) { return $app . '/' . $app; } }
总结:本文主要总结下PHP的Callback Type,便于提升本身的代码设计能力。遇到好的技术再聊,到时见。
测试
欢迎关注Laravel-China。this