PHP实用小技巧之调用录像的方法


Posted in PHP onDecember 05, 2019

主要功能

把你实际的调用操作录下来,然后在你想要的地方重新调用

和匿名函数的作用基本一样,暂存你的调用操作 一般用于链式调用, 然后实际作用于你想要操作的对象上面

好像和没说一样

使用场景

假如 laravel 项目用到了 仓库模式, 然后对于比较复杂的查询条件,一般情况下有三种操作

  • 针对特殊查询增加方法
  • 定一个规则,按照这个规则组装数组,然后需要在 仓库类 里面实现解析
  • 传匿名函数,匿名函数里面写查询条件

现在可以对第三种方法进行优化,传入一个下面代码里的 CallEcho 对象

//控制器里
$callEcho = (new CallEcho())->where("username", "马云")->where("is_boss", 1)->first();
$fubao = (new UserRepository)->first($callEcho);

//仓库类
class UserRepository{
  public function first(CallEcho $callEcho){
    return $callEcho->invoke(new User());
  }
}

看着和匿名函数差不多,但是 CallEcho 可以被继承来实现些接口,继承后还可以对查询条件进行一些操作,比如过滤什么的。用匿名函数的话,完全就看调用方的良心了。

最重要的是不传对象传函数叫什么面对对象

上代码

class CallEcho
{

  protected $callable = null;

  public function __construct()
  {  
    //callable 初始化
    $this->seed();
  }

  protected function seed(){
    $this->callable = $this;
  }

  public function __invoke($obj)
  {
    return $obj;
  }

  public function __call($name, $arguments)
  {
    $current = $this->callable;
    /**
     * 每产生__call,就往callable上面裹一层
     */
    $this->callable = function($obj) use($name, $arguments, $current){
      return call_user_func_array($current, [$obj])->{$name}(...$arguments);
    };
    return $this;
  }
  
  //作用于真正的对象上面
  public function invoke($obj){
    return call_user_func_array($this->callable, [$obj]);
  }
}

简单的测试 以及 使用

class TestCallEcho{
  protected $called = [];

  public function __call($name, $arguments)
  {
    $this->called[] = [$name, $arguments];
    return $this;
  }

  public function end(){
    $this->called[] = "end";
    return $this;
  }

  public function getCalled(){
    return $this->called;
  }
}

function testArrayEq($array1, $array2){
  if(count($array1) !== count($array2)){
    return false;
  }

  foreach ($array1 as $index => $value1){
    if(!isset($array2[$index])){
      return false;
    }
    $value2 = $array2[$index];

    if(is_array($value1) && is_array($value2)){
      if(!testArrayEq($value1, $value2)){
        return false;
      }else{
        //继续判断
      }
    }else{
      if($value1 !== $value2){
        return false;
      }
    }
  }
  return true;
}

function testTestArrayEq(){
  $array1 = [1, 2];
  $array2 = [1, 3];
  $array3 = [1, 2, 3];

  assert(testArrayEq($array1, $array2) == false);
  assert(testArrayEq($array1, $array3) == false);
  assert(testArrayEq($array1, $array1) == true);
}
testTestArrayEq();

$obj = new \stdClass();
$callEcho = new CallEcho();

/*************重点开始****************/
/** @var CallEcho $callEcho */
$callEcho = $callEcho->testNumber(1)->testString("myname")->testObj($obj)->testMulti(1, "myname")->testMulti2("1", $obj)->end();

/** @var TestCallEcho $testCallEcho */
$testCallEcho = $callEcho->invoke(new TestCallEcho());
/************重点结束****************/

//基本上和这个作用一样
$a = function($obj){
  $obj->testNumber(1)->testString("myname")->testObj($obj)->testMulti(1, "myname")->testMulti2("1", $obj)->end();
};


$called = $testCallEcho->getCalled();

$eq = testArrayEq($called, [
  ["testNumber", [1]],
  ["testString", ["myname"]],
  ["testObj", [$obj]],
  ["testMulti", [1, "myname"]],
  ["testMulti2", ["1", $obj]],
  "end"
]);
assert($eq);

PS

灵感来源于slim3 中间件 的实现

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

PHP 相关文章推荐
15种PHP Encoder的比较
Mar 06 PHP
PHP开发中常用的8个小技巧
Aug 27 PHP
php 上传文件类型判断函数(避免上传漏洞 )
Jun 08 PHP
php中获取指定IP的物理地址的代码(正则表达式)
Jun 23 PHP
php设计模式之单例、多例设计模式的应用分析
Jun 30 PHP
php定界符
Jun 19 PHP
thinkphp配置连接数据库技巧
Dec 02 PHP
详解ThinkPHP3.2.3验证码显示、刷新、校验
Dec 29 PHP
PHP进程通信基础之信号量与共享内存通信
Feb 19 PHP
PHP常用函数之格式化时间操作示例
Oct 21 PHP
PHP数据源架构模式之表入口模式实例分析
Jan 23 PHP
Laravel相关的一些故障解决
Aug 19 PHP
Laravel框架控制器,视图及模型操作图文详解
Dec 04 #PHP
Laravel框架下载,安装及路由操作图文详解
Dec 04 #PHP
Laravel框架Eloquent ORM简介、模型建立及查询数据操作详解
Dec 04 #PHP
PHP实现二维数组(或多维数组)转换成一维数组的常见方法总结
Dec 04 #PHP
PHP实现提取多维数组指定一列的方法总结
Dec 04 #PHP
php实现快速对二维数组某一列进行组装的方法小结
Dec 04 #PHP
PHP实现发送微博消息功能完整示例
Dec 04 #PHP
You might like
一篇有意思的技术文章php介绍篇
2010/10/26 PHP
ThinkPHP自动转义存储富文本编辑器内容导致读取出错的解决方法
2014/08/08 PHP
php中动态修改ini配置
2014/10/14 PHP
thinkphp模板继承实例简述
2014/11/26 PHP
PHP使用mysqldump命令导出数据库
2015/04/14 PHP
学习php设计模式 php实现抽象工厂模式
2015/12/07 PHP
js 判断浏览器类型 去全角、半角空格 自动关闭当前窗口
2009/04/10 Javascript
关于JavaScript定义类和对象的几种方式
2010/11/09 Javascript
阻止子元素继承父元素事件具体思路及实现
2013/05/02 Javascript
JS控制日期显示的小例子
2013/11/23 Javascript
编程语言JavaScript简介
2014/10/16 Javascript
JS/Jquery判断对象为空的方法
2015/06/11 Javascript
JavaScript实现自动消除按钮功能的方法
2015/08/05 Javascript
Javascript中arguments对象的详解与使用方法
2016/10/04 Javascript
浅述Javascript的外部对象
2016/12/07 Javascript
Express之get,pos请求参数的获取
2017/05/02 Javascript
React-intl 实现多语言的示例代码
2017/11/03 Javascript
详解angular应用容器化部署
2018/08/14 Javascript
vue2.0 下拉框默认标题设置方法
2018/08/22 Javascript
微信小程序webview实现长按点击识别二维码功能示例
2019/01/24 Javascript
VUE中使用HTTP库Axios方法详解
2020/02/05 Javascript
区分vue-router的hash和history模式
2020/10/03 Javascript
vuex中遇到的坑,vuex数据改变,组件中页面不渲染操作
2020/11/16 Javascript
[03:23:49]2016.12.17日完美“圣”典全回顾
2016/12/19 DOTA
Python基于二分查找实现求整数平方根的方法
2016/05/12 Python
Python算法输出1-9数组形成的结果为100的所有运算式
2017/11/03 Python
基于循环神经网络(RNN)的古诗生成器
2018/03/26 Python
Django设置Postgresql的操作
2020/05/14 Python
python3 使用ssh隧道连接mysql的操作
2020/12/05 Python
css3 自定义字体font-face使用介绍
2014/05/14 HTML / CSS
基于DOM+CSS3实现OrgChart组织结构图插件
2016/03/02 HTML / CSS
司机检讨书
2014/02/13 职场文书
出纳试用期自我鉴定
2014/04/07 职场文书
公司应聘自荐书
2014/06/14 职场文书
公证处委托书
2015/01/28 职场文书
python接口测试返回数据为字典取值方式
2022/02/12 Python