资讯专栏INFORMATION COLUMN

Laravel学习笔记之函数处理(Function Handling)

Rindia / 2660人阅读

摘要:提供了一些函数处理操作的内置函数,主要有开发环境是调用回调函数,并把一个数组作为参数传进去作为回调函数的参数也是调用回调函数,区别是并没有要求把数组作为参数传进回调函数做参数。

说明:Laravel中经常使用PHP的Function Handling来设计代码,本文主要学习PHP的Function Handling特性,来提高写代码时的设计质量。PHP提供了一些函数处理操作的内置函数,主要有:

call_user_func_array( )

call_user_func( )

func_get_arg( )

func_get_args( )

func_num_args( )

function_exists( )

开发环境:Laravel5.3 + PHP7

Function Handling call_user_func_array()/call_user_func()

call_user_func_array()是调用回调函数,并把一个数组作为参数传进去作为回调函数的参数;call_user_func()也是调用回调函数,区别是并没有要求把数组作为参数传进回调函数做参数。在Laravel中大量使用这两个内置函数来设计代码,比如IlluminateFoundationApplication::fireAppCallbacks()的源码:

    /**
     * Call the booting callbacks for the application.
     *
     * @param  array  $callbacks
     * @return void
     */
    protected function fireAppCallbacks(array $callbacks)
    {
        foreach ($callbacks as $callback) {
            call_user_func($callback, $this); //执行回调函数,并把Application对象作为参数传进去
        }
    }

call_user_func()和call_user_func_array()可以说是PHP设计好代码的神器,不得不熟悉,这里给下它的PHPUnit测试看看如何使用,爆绿灯:

assertSame("This is a service provider.", $actual);
    }

    public function testCallUserFuncArray()
    {
        // Arrange
        $provider = new Provider();
        $app      = new Application($provider);

        // Actual
        $actual = call_user_func_array("MyRightCapitalContainerTestscallUserFunc", [$app]);

        // Assert
        $this->assertSame("This is a service provider.", $actual);
    }
}

function callUserFunc($app)
{
    return $app->register();
}

class Application
{
    private $provider;

    public function __construct($provider)
    {
        $this->provider = $provider;
    }

    public function register()
    {
        return $this->provider->register();
    }
}

class Provider
{
    public function register()
    {
        return "This is a service provider.";
    }
}

call_user_func_array()和call_user_func()真是个非常用的函数,值得在设计自己的代码里使用。

func_get_arg()/func_get_args()/func_num_args()

func_get_arg()是从函数的参数列表读取某个指定的参数,func_get_args()是读取函数的整个参数列表作为数组返回,func_num_args()是读取函数的参数的个数。Laravel中的IlluminateFoundationApplication::environment()使用了这三个函数来设计代码,很巧妙:

    /**
     * Get or check the current application environment.
     *
     * @return string|bool
     */
    public function environment()
    {    
        // 如果传入了参数
        if (func_num_args() > 0) {
            // 如果第一个参数是数组形式就把该数组赋值给$patterns;如果不是就把所有参数作为一个数组赋值给$patterns
            $patterns = is_array(func_get_arg(0)) ? func_get_arg(0) : func_get_args();

            foreach ($patterns as $pattern) {
                if (Str::is($pattern, $this["env"])) {
                    return true;
                }
            }

            return false;
        }

        return $this["env"];
    }

看environment()源码可知道environment()是可以传入参数的,如果不传入参数就返回$this["env"]的值即Laravel中的环境变量APP_ENV值,如App::environment()即为读取Laravel当前运行环境变量值;如果传入参数则判断该值是否与环境变量值相等,如App::environment("production","staging", "development")即判断当前Laravel运行环境是否是"production","staging", "development"中的一种。很巧妙的设计。

这里写个PHPUnit测试下,爆绿灯:

class FunctionHandling extends PHPUnit_Framework_TestCase
{
    public function testFuncArgs()
    {
        // Arrange
        $provider = new Provider();
        $app      = new Application($provider);
        
        // Actual
        $arg_number0 = $app->testFuncArg(); 
        $arg_number1 = $app->testFuncArg("Laravel");
        $arg_number2 = $app->testFuncArg(["Laravel", "PHP"]);
        
        // Assert
        $this->assertSame(0, $arg_number0);
        $this->assertSame(1, $arg_number1);
        $this->assertSame(2, $arg_number2);
    }
}

class Application
{
    private $provider;

    public function __construct($provider)
    {
        $this->provider = $provider;
    }

    public function register()
    {
        return $this->provider->register();
    }

    public function testFuncArg()
    {
        if (func_num_args() > 0) {
            $patterns = is_array(func_get_arg(0)) ? func_get_arg(0) :func_get_args();
            return count($patterns);
        }
        
        return 0;
    }
}
 
function_exists()

function_exists()判断指定函数是否已经定义,这个函数在Laravel中大量使用,尤其是造辅助函数时使用,参考Illuminate/Foundation/helpers.php,
Illuminate/Support/helpers.php。这里做个PHPUnit测试,爆绿灯:

class FunctionHandling extends PHPUnit_Framework_TestCase
{
    public function testFunctionExists()
    {
        // Arrange
        $expected = "Container";

        // Actual
        $actual = functionExists("Container");

        // Assert
        $this->assertSame($expected, $actual);
    }
}
        
if (!function_exists("functionExists")) {
    function functionExists($container)
    {
        return $container;
    }
}
    

总结:本文主要学习了PHP的Function Handling,这个技术可以用来提高自己的代码设计能力,同时Laravel中也大量使用了这个技术来巧妙设计代码。下次遇到好的技术在分享,到时见。

欢迎关注Laravel-China。

RightCapital招聘Laravel DevOps

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/30473.html

相关文章

  • Laravel学习笔记Middleware源码解析

    摘要:学习笔记之已经聊过使用了来设计,看源码发现其巧妙用了和的一些数组函数来设计。开发环境内置函数和看源码之前,先看下这几个内置函数的使用。学习笔记之实例化源码解析已经聊过的实例化,得到中的变量,即的实例化对象。后面再学习下的源码,到时见。 说明:本文主要学习Laravel的Middleware的源码设计思想,并将学习心得分享出来,希望对别人有所帮助。Laravel学习笔记之Decorato...

    _Dreams 评论0 收藏0
  • Laravel学习笔记bootstrap源码解析

    摘要:总结本文主要学习了启动时做的七步准备工作环境检测配置加载日志配置异常处理注册注册启动。 说明:Laravel在把Request通过管道Pipeline送入中间件Middleware和路由Router之前,还做了程序的启动Bootstrap工作,本文主要学习相关源码,看看Laravel启动程序做了哪些具体工作,并将个人的研究心得分享出来,希望对别人有所帮助。Laravel在入口index...

    xiaoxiaozi 评论0 收藏0
  • Laravel 学习笔记 Query Builder 源码解析(中)

    说明:本篇主要学习数据库连接阶段和编译SQL语句部分相关源码。实际上,上篇已经聊到Query Builder通过连接工厂类ConnectionFactory构造出了MySqlConnection实例(假设驱动driver是mysql),在该MySqlConnection中主要有三件利器:IlluminateDatabaseMysqlConnector;IlluminateDatabaseQuery...

    zhou_you 评论0 收藏0
  • Laravel学习笔记Callback Type

    摘要:说明本文主要学习的回调类型通常在使用函数进行回调时,如使用进行回调时,需要传入回调,实际上有几种的,在中也大量使用回调,并根据场景不同传入不同的回调类型。开发环境是把函数名作为类型传进去作为回调类型,形式如。 说明:本文主要学习PHP的回调类型callback type,通常在使用函数进行回调时,如使用call_user_func($callback, $parameters)进行回调...

    ChanceWong 评论0 收藏0
  • Laravel 学习笔记 Query Builder 源码解析(下)

    摘要:,看下源码返回很容易知道返回值是,然后将该值存储在变量中,这时。看下的源码去除掉字符后为返回从源码中可知道返回值为,这时。 说明:本文主要学习下Query Builder编译Fluent Api为SQL的细节和执行SQL的过程。实际上,上一篇聊到了IlluminateDatabaseQueryBuilder这个非常重要的类,这个类含有三个主要的武器:MySqlConnection, M...

    qpal 评论0 收藏0

发表评论

0条评论

Rindia

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<