PHP链式操作基本原理,call_user_func(),call_user_func_array()和Magic Methods__get(),__set(),__call()的用法

前言

在阅读框架源码时发现源码中大量使用到了链式操作,和call_user_func()call_user_func_array()这种调用函数的方法;
虽然两者并无关联,但是目的都是使代码更简洁,逻辑更清晰。
整理一些资料和大家一起学习。


call_user_func()call_user_func_array()

call_user_func():把第一个参数作为回调函数调用,后面的参数作为回调函数的参数;
http://php.net/manual/zh/function.call-user-func.php

call_user_func_array():调用回调函数,并把一个数组参数作为回调函数的参数,第二各数组参数作为回调函数的参数。
http://php.net/manual/zh/function.call-user-func-array.php

两种方法类似,在不同的情况下有不同的参数传递方式,现在以call_user_func()为例讲一下各种情况:

回调函数可以用匿名函数,可以用有名函数,可以传递类的方法,

第一个参数为有名函数时,只需传函数的名称,用类的方法时,要传类的名称和方法名

内部方法作为回调函数:

<?php 
class Func{
    static public function sayHi(){
        $str ="HI ";
        if(func_num_args()){//获得参数的个数
            $arg = func_get_arg(0);//获取函数参数,获取参数也可以通过给方法设置形参来获取,这里只是没给方法设置形参获取参数的情况
            return $str.$arg;
        }else{
            return $str;
        }
    }
    
    public function number($num){
        return $num ? $num+1:$num;
    }
}
var_dump(call_user_func("Func::sayHi",'Boy !'));//静态方法,传递类名::方法名
$o = new Func;
$return = call_user_func([$o,'number'],1);//普通方法必须用数组传递该类的对象和方法名
var_dump($return);
?>

外部类作为回调函数:

<?php

namespace Foobar;

class Foo {
    static public function test() {
        print "Hello world!\n";
    }
   public function number($num){
        return $num ? $num+1:$num;
    }  
}
//静态方法
//命名空间\类名::方法名
call_user_func(__NAMESPACE__ .'\Foo::test'); // As of PHP 5.3.0
//命名空间\类名','方法名'
call_user_func([__NAMESPACE__ .'\Foo', 'test']); // As of PHP 5.3.0
//普通方法
$o = new Foo;
$return = call_user_func([$o,'number'],1);//普通方法必须用数组传递该类的对象和方法名
var_dump($return);
?>

外部类还可以通过相对路径的方法作为回调函数:
例如:回调函数为'\\think\\paginator\\driver\\'下的getCurrentPage方法,参数为$var_page

        $class = '\\think\\paginator\\driver\\' ;
        $page  = call_user_func([
            $class,
            'getCurrentPage',
        ],$var_page);

第一个参数为匿名函数时:
call_user_func函数是php引用匿名函数的一种方式,php不像js那样,可以把匿名函数赋值给变量并引用,但可以通过call_user_func函数来调用匿名函数,这也能做到局部变量不被全局污染。

<?php

call_user_func(function($call){
    echo ++$call,'<br/>';
    echo ++$call,'<br/>';
},1);

链式操作的原理

参考:https://www.jb51.net/article/103836.htm

链式操作的核心是返回$this指针,让后面的函数进行调用,和参数的共享!

结合__get(),__set(),__call()__construct(构造方法)进行实现:

__construct 构造方法,创建类时调用
__get()是访问不存在的成员变量时调用;
__set()是设置不存在的成员变量时调用;
__call()当调用类中不存在的方法时调用。

通常在计算字符串函数的时候,要先对字符串进行过滤空格,然后再求其长度:

strlen(trim($str))

但是怎样才能以链式操作的形式实现?

$str->trim()->strlen();

核心思想:

链式操作,类的生命周期的结束在链式操作的末尾,所有可以通过成员变量的方式进行参数的共享,通过__construct进行成员变量的赋值,通过__get(),__set(),__call()来处理调用关系。

<?php
class StringHelper 
{
  private $value;
   
  function __construct($value)
  {
    $this->value = $value;
  }
 
  function __call($function, $args){
    $this->value = call_user_func($function, $this->value, $args[0]);//调用外部的trim()方法,传入2个参数
    return $this;
  }
 
  function strlen() {
    return strlen($this->value);
  }
}
 
$str = new StringHelper("hi boys and girls ! ");
echo $str->trim('0')->strlen();

查看更多:Magic Methods http://php.net/manual/zh/language.oop5.magic.php

最后

这里介绍的链式操作为其最基本的原理,而在框架中它又是如何被灵活运用呢?

敬请关注,后续文章!(o゜▽゜)o☆

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值