当前位置: 首页 > news >正文

php高级之框架源码、宏扩展原理与开发

在使用框架的时候我们经常会看到如下代码
在这里插入图片描述
类的方法不会显示地声明在代码里面,而是通过扩展的形式后续加进去,这么做的好处是可以降低代码的耦合度、保证源码的完整性、团队开发的时候可以分别写自己的服务去扩展类,减少代码冲突等等。我自己看着框架源码实现了这个功能。
以下是结果:
在这里插入图片描述
base代码
在这里插入图片描述
index.php

<?php
require_once "macroable.php";
require_once "base.php";
$a = new phpmacro\Base();
$a::macro("first",function (){$this->query .="I had be macro";return $this->query;
});
$a->first();
var_dump($a->query);

base.php

<?php
namespace phpmacro;/*** @method first()*/
class Base 
{use Macroable;public $query = "init-query";function __construct(){// code...echo "base-contruct";}
}

Macroable.php

<?phpnamespace phpmacro;use BadMethodCallException;
use Closure;
use ReflectionClass;
use ReflectionMethod;trait Macroable
{/*** The registered string macros.** @var array*/protected static $macros = [];/*** Register a custom macro.** @param  string  $name* @param  object|callable  $macro* @return void*/public static function macro($name, $macro){static::$macros[$name] = $macro;}/*** Mix another object into the class.** @param  object  $mixin* @param  bool  $replace* @return void** @throws \ReflectionException*/public static function mixin($mixin, $replace = true){$methods = (new ReflectionClass($mixin))->getMethods(ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED);foreach ($methods as $method) {if ($replace || ! static::hasMacro($method->name)) {static::macro($method->name, $method->invoke($mixin));}}}/*** Checks if macro is registered.** @param  string  $name* @return bool*/public static function hasMacro($name){return isset(static::$macros[$name]);}/*** Flush the existing macros.** @return void*/public static function flushMacros(){static::$macros = [];}/*** Dynamically handle calls to the class.** @param  string  $method* @param  array  $parameters* @return mixed** @throws \BadMethodCallException*/public static function __callStatic($method, $parameters){if (! static::hasMacro($method)) {throw new BadMethodCallException(sprintf('Method %s::%s does not exist.', static::class, $method));}$macro = static::$macros[$method];if ($macro instanceof Closure) {$macro = $macro->bindTo(null, static::class);}return $macro(...$parameters);}/*** Dynamically handle calls to the class.** @param  string  $method* @param  array  $parameters* @return mixed** @throws \BadMethodCallException*/public function __call($method, $parameters){if (! static::hasMacro($method)) {throw new BadMethodCallException(sprintf('Method %s::%s does not exist.', static::class, $method));}$macro = static::$macros[$method];if ($macro instanceof Closure) {$macro = $macro->bindTo($this, static::class);}return $macro(...$parameters);}
}

其实原理就是利用了静态调用的魔术方法与匿名函数的bindTo方法实现了类与方法解藕的效果
以下是test.php,可以清晰的看明白匿名函数bindTo跟bind是怎么用的

<?php
/** * 复制一个闭包,绑定指定的$this对象和类作用域。 * * @author 疯狂老司机 */
class Animal {private static $cat = "cat";private $dog = "dog";public $pig = "pig";
}/* * 获取Animal类静态私有成员属性*/
$cat = static function() {return Animal::$cat;
};/* * 获取Animal实例私有成员属性*/
$dog = function() {return $this->dog;
};/* * 获取Animal实例公有成员属性*/
$pig = function() {return $this->pig;
};$bindCat = Closure::bind($cat, null, new Animal());// 给闭包绑定了Animal实例的作用域,但未给闭包绑定$this对象
$bindDog = Closure::bind($dog, new Animal(), 'Animal');// 给闭包绑定了Animal类的作用域,同时将Animal实例对象作为$this对象绑定给闭包
$bindPig = Closure::bind($pig, new Animal());// 将Animal实例对象作为$this对象绑定给闭包,保留闭包原有作用域
$animal = new Animal();
$pigBindto = $pig->bindTo($animal);
echo $pigBindto()."\r\n";
echo $bindCat()."\r\n";// 根据绑定规则,允许闭包通过作用域限定操作符获取Animal类静态私有成员属性
echo $bindDog()."\r\n";// 根据绑定规则,允许闭包通过绑定的$this对象(Animal实例对象)获取Animal实例私有成员属性
echo $bindPig()."\r\n";// 根据绑定规则,允许闭包通过绑定的$this对象获取Animal实例公有成员属性

输出结果
在这里插入图片描述

相关文章:

php高级之框架源码、宏扩展原理与开发

在使用框架的时候我们经常会看到如下代码 类的方法不会显示地声明在代码里面&#xff0c;而是通过扩展的形式后续加进去&#xff0c;这么做的好处是可以降低代码的耦合度、保证源码的完整性、团队开发的时候可以分别写自己的服务去扩展类&#xff0c;减少代码冲突等等。我自己…...

(2024,示例记忆,模型记忆,遗忘,差分评估,概率评估)深度学习中的记忆:综述

Memorization in deep learning: A survey 公和众和号&#xff1a;EDPJ&#xff08;进 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 进 V 交流群&#xff09; 目录 0 摘要 1 引言 0 摘要 深度神经网络&#xff08;DNNs&#xff09;驱动的深度学习&#xff…...

硬件产品经理

边端协调管理平台 主页一&#xff1a;模型管理1.1 边侧模型管理 二&#xff1a;配置管理2.1 终端软件配置管理 三&#xff1a;设备管理3.1 区域位置管理3.2 工控机管理&#xff08;其实就是围绕授权&#xff09;3.3 生产设备管理3.4 设备运行管理 四&#xff1a;数据服务4.1 实…...

AES加密、解密工具类

1、AES加密、解密工具类 这篇文章,主要记录一下AES加密、解密的工具类代码,在需要使用的时候,直接复制黏贴即可。 package com.gitcode.pms.common.util;import org.slf4j.Logger; import org.slf4j.LoggerFactory;import javax.crypto.Cipher; import javax.crypto.spec.…...

普通人想要自学ai,该如何入手,看完这篇你就懂了,零基础教程!

学会了AIGC之后&#xff0c;我只想说&#xff1a;无敌是多么寂寞&#xff1f; 之前我整理一篇会议记录起码要2小时。现在交给AI &#xff0c;5分钟搞定&#xff1b; 之前整理账目总是出错&#xff0c;现在利用AI财务整合器&#xff0c;轻松解决统计难题&#xff1b; 之前写个…...

Less的简单总结

Less 是一个开源的 CSS 预处理器&#xff0c;它扩展了 CSS 语言&#xff0c;增加了变量、嵌套规则、运算符、函数等特性&#xff0c;使编写 CSS 更加高效、灵活且易于维护。下面是对 "Less" 的一个总结文档&#xff1a; 简介 名称&#xff1a;Less&#xff08;通常表…...

Android:UI:Drawable:View/ImageView与Drawable

文章目录 在View/ImageVIew中显示DrawableDrawable对View的更新操作在View/ImageVIew中显示Drawable API View.setBackground(Drawable) ImageView.setImagDrawable(Drawable) 源码分析 View.mBackground在View.draw(Canvas)中绘制,调用Drawable.draw(Canvas) ImageView.m…...

网络安全实验BUAA-全套实验报告打包

下面是部分BUAA网络安全实验✅的实验内容 &#xff1a; 认识路由器、交换机。掌握路由器配置的基本指令。掌握正确配置路由器的方法&#xff0c;使网络正常工作。 本博客包括网络安全课程所有的实验报告&#xff1a;内容详细&#xff0c;一次下载打包 实验1-路由器配置实验2-AP…...

监控易监测对象及指标之:全面监控SQL Server 2008

随着企业信息化建设的不断深入&#xff0c;数据库作为存储和管理关键业务数据的核心&#xff0c;其稳定性和性能至关重要。SQL Server 2008作为一款广泛使用的关系型数据库管理系统&#xff0c;承载着众多企业的核心业务数据。 为了确保SQL Server 2008数据库的稳定运行和高效性…...

【学习记录】6.11 阅读记录

SpringBoot多环境配置详解(application-dev.yml、application-test.yml、application-prod.yml) springboot集成mybatis【使用generatorConfig.xml配置自动生成代码】 怎么快速查看自己mysql的安装位置 解决 http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd 报错...

100TOPS算力!16GB内存顶配NVIDIA Jetson Orin NX 16GB 开箱

观前提醒&#xff1a;你以为我斥资6600买了一个NX玩&#xff1f;我其实买了三个NX NVIDIA Jetson Orin NX 简介&#xff1a; NVIDIA Jetson Orin NX是NVIDIA推出的一款高性能边缘计算平台&#xff0c;其设计目标是提供卓越的计算能力以支持各种复杂的人工智能&#xff08;AI&am…...

OCP学习笔记-007 SQL语言之一:DQL

1. DQL - Data Query Language 命令行提示符修改 SQL> set time on 10:33:58 SQL> define DEFINE _DATE = "11-DEC-22" (CHAR) DEFINE _CONNECT_IDENTIFIER = "orcl" (CHAR) DEFINE _USER = "SYS" (CHAR) DEFINE _P…...

Git之解决重复输入用户名和密码(三十九)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…...

Python 机器学习 基础 之 【实战案例】轮船人员获救预测实战

Python 机器学习 基础 之 【实战案例】轮船人员获救预测实战 目录 Python 机器学习 基础 之 【实战案例】轮船人员获救预测实战 一、简单介绍 二、轮船人员获救预测实战 三、数据处理 1、导入数据 2、对缺失数据的列进行填充 3、属性转换,把某些列的字符串值转换为数字…...

安全相关的一些基础知识(持续更新)

目录 1. TRNG真随机数生成 2. 对称加密和非对称加密及其区别 3. Hash算法&#xff08;摘要算法&#xff09; 4. HTTPS、TLS、SSL、HTTP区别和关系 HTTPS的基本原理 5. PSS 1. TRNG真随机数生成 True Random Number Generator 在真随机数的生成里&#xff0c;把随机数的生…...

使用TensorFlow和Keras对以ResNet50模型进行微调

以下是使用ResNet50进行微调以识别特定的新东西的代码演示。将使用TensorFlow和Keras进行这个任务。 数据集下载地址&#xff0c;解压到工程里面去&#xff1a; https://www.kaggle.com/datasets/marquis03/cats-and-dogs原始代码&#xff1a; ​ from keras.applications…...

Shell脚本要点和难点以及具体应用和优缺点介绍

Shell 脚本是一种用于自动化任务和简化常见系统命令的脚本语言,通常运行在 Unix 或 Unix-like 的系统上,如 Linux 和 macOS。Shell 脚本可以直接在命令行中执行,也可以保存为文件并通过 bash、sh、zsh 等 shell 解释器来执行。 以下是一个简单的 Shell 脚本示例,它演示了如…...

移动端浏览器的扫描二维码实现(vue-qrcode-reader与jsQR方式)

1. 实现功能 类似扫一扫的功能&#xff0c;自动识别到画面中的二维码并进行识别&#xff0c;也可以选择从相册中上传。 2. 涉及到的一些插件介绍 vue-qrcode-reader 一组用于检测和解码二维码的Vue.js组件 jsQR 一个纯粹的javascript二维码阅读库&#xff0c;该库接收原始…...

android中调用onnxruntime框架

创建空白项目 安装Android Studio及创建空白项目参考&#xff1a;【安卓Java原生开发学习记录】一、安卓开发环境的搭建与HelloWorld&#xff08;详细图文解释&#xff09;_安卓原生开发-CSDN博客 切记&#xff1a;build configuration language 一定选择Groovy&#xff01;官…...

【机器学习】与【数据挖掘】技术下【C++】驱动的【嵌入式】智能系统优化

目录 一、嵌入式系统简介 二、C在嵌入式系统中的优势 三、机器学习在嵌入式系统中的挑战 四、C实现机器学习模型的基本步骤 五、实例分析&#xff1a;使用C在嵌入式系统中实现手写数字识别 1. 数据准备 2. 模型训练与压缩 3. 模型部署 六、优化与分析 1. 模型优化 模…...

别再傻傻用二维数组存大矩阵了!手把手教你用C++实现稀疏矩阵的三元组压缩(附完整代码)

稀疏矩阵高效存储实战&#xff1a;从三元组压缩到十字链表的C实现 当你在处理一个1000010000的矩阵&#xff0c;却发现其中99%的元素都是零时&#xff0c;传统的二维数组存储方式就像用集装箱运输几颗散落的珍珠——浪费了巨大的空间和运输成本。这种"稀疏"场景在科学…...

告别Joplin!用MarkDownload+Obsidian打造你的网页剪藏工作流(附完整配置JSON)

从Joplin到Obsidian&#xff1a;用MarkDownload构建高效网页剪藏系统 每次在网上冲浪时遇到值得保存的内容&#xff0c;你是否也经历过这样的困境&#xff1f;收藏夹里堆满了再也找不到的链接&#xff0c;或是剪藏工具中杂乱无章的片段。作为一个长期依赖Joplin进行知识管理的用…...

【故障】解决ssh连接linux卡着不动的问题

1、原因使用xshell连接一台linux机器&#xff0c;发现连接不上&#xff0c;一直都开在连接这个界面&#xff0c;最后超时才停止。2、排查&#xff08;1&#xff09;首先&#xff0c;检查下防火墙或者selinuxsystem status firewalld #检查服务是否处于非Running的状态getenforc…...

如何突破英雄联盟操作效率瓶颈?League-Toolkit的5大革新功能解析

如何突破英雄联盟操作效率瓶颈&#xff1f;League-Toolkit的5大革新功能解析 【免费下载链接】League-Toolkit 兴趣使然的、简单易用的英雄联盟工具集。支持战绩查询、自动秒选等功能。基于 LCU API。 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit 在快…...

避坑指南:SpringBoot调用DeepSeek API时你可能会遇到的5个问题及解决方案

SpringBoot集成DeepSeek API的5个典型避坑指南 在将DeepSeek的对话补全能力整合到SpringBoot应用时&#xff0c;不少开发者会遇到一些看似简单却容易踩坑的问题。这些问题往往不会在官方文档中被特别强调&#xff0c;但却能让你在调试过程中耗费数小时。本文将聚焦五个最具代表…...

树莓派4b(armv8) 64位系统源码编译onnx实战指南

1. 环境准备&#xff1a;从零搭建树莓派4B开发环境 在树莓派4B上编译ONNX源码之前&#xff0c;我们需要先确保系统环境配置正确。我用的是一台4GB内存版本的树莓派4B&#xff0c;系统是最新的Raspberry Pi OS 64位版本。这里有个小细节要注意&#xff1a;很多教程还在用32位系统…...

利用Charles实现请求与响应的动态修改:从基础到实战

1. Charles工具简介与基础配置 Charles是一款功能强大的网络抓包工具&#xff0c;它就像是你手机和电脑之间的"透明玻璃"&#xff0c;能让你清清楚楚地看到所有进出的网络请求。我第一次接触Charles是在调试一个电商APP的支付接口时&#xff0c;当时遇到一个诡异的bu…...

LabVIEW标准表法开发气体流量标准装置

标准表法是气体流量计检定校准的主流方法&#xff0c;针对气体流量检测过程中自动化程度低、数据采集精度不足、设备控制协同性差的问题&#xff0c;依托 LabVIEW 图形化编程平台搭建气体流量标准装置应用系统&#xff0c;实现温度、压力、流量等参数的自动化采集、设备精准调控…...

AI 辅助 CAPL 脚本编写实战

专栏&#xff1a;《AI 汽车电子测试实战》第 6 篇 作者&#xff1a;一线汽车电子测试工程师 适合人群&#xff1a;CANoe 测试工程师、想学习 CAPL 的新手、想提升脚本效率的测试人员开篇&#xff1a;CAPL 脚本的痛点 CAPL&#xff08;Communication Access Programming Languag…...

AudioLDM-S移动开发:Android音频API集成指南

AudioLDM-S移动开发&#xff1a;Android音频API集成指南 1. 引言 想在Android应用中实现"一句话生成专属音效"的酷炫功能吗&#xff1f;AudioLDM-S让这变得可能。这个强大的AI模型可以将文本描述直接转换为高质量的音效&#xff0c;从雨滴声到科幻音效都能轻松生成…...