Laravel学习笔记之Callback Type
说明:本文主要学习PHP的回调类型callback type,通常在使用函数进行回调时,如使用call_user_func($callback, $parameters)进行回调时,需要传入回调callback,实际上有几种callback type的,在Laravel中也大量使用回调,并根据场景不同传入不同的回调类型。
开发环境:Laravel5.3 + PHP7
(Function/Static Class Method) Callback Type
Function Callback Type是把函数名作为callable类型传进去作为回调类型,形式如:($function_name, $dependency)
。Static Class Method Callable Type与其类似,是把类名+静态方法名传进去作为回调类型,形式如:("$class_name::$static_method_name", $dependency)
。看下PHPUnit测试,看看如何使用callback type,爆绿灯:
<?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/Relation Class Method) Callback Type
Class Method Callback Type也是类名+静态方法名,只不过形式稍不一样,形式如:([$class_name, $method_name], $dependency)。Relation Class Method Callback Type是可以使用父类的方法传进去作为回调,形式如:([$class_name, "parent::$method_name"], $dependency)。写个PHPUnit测试看下使用:
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 Callback Type是把对象方法作为参数传进去作为回调,形式如:([$object, $method_name], $dependency),写个PHPUnit测试:
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
把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。
Kubernetes学习笔记
Kubernetes学习笔记之CSI External Provisioner源码解析
lx1036赞 3阅读 3.6k
One 一个简洁的博客、微博客系统
Eyeswap赞 45阅读 2.3k评论 1
怎样用 PHP 来实现枚举?
唯一丶赞 25阅读 6.3k评论 4
图片防盗链破解 解决图片防盗链问题 反向代理
TANKING赞 7阅读 11.2k评论 5
Git操作不规范,战友提刀来相见!
王中阳Go赞 5阅读 2k评论 2
微信公众号开发:自动回复文本/图片/图文消息/关键词回复/上传素材/自定义菜单
TANKING赞 2阅读 10k
PHP转Go实践:xjson解析神器「开源工具集」
王中阳Go赞 4阅读 944评论 2
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。