Laravel學習筆記之Callback Type

說明:本文主要學習PHP的回調類型callback type,一般在使用函數進行回調時,如使用call_user_func($callback, $parameters)進行回調時,須要傳入回調callback,實際上有幾種callback type的,在Laravel中也大量使用回調,並根據場景不一樣傳入不一樣的回調類型。php

開發環境:Laravel5.3 + PHP7laravel

(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,爆綠燈: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/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測試看下使用: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 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

把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-Chinathis

RightCapital招聘Laravel DevOpsspa

相關文章
相關標籤/搜索