当前位置: 首页 > 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. 模型优化 模…...

HTML 语义化

目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案&#xff1a; 语义化标签&#xff1a; <header>&#xff1a;页头<nav>&#xff1a;导航<main>&#xff1a;主要内容<article>&#x…...

OpenLayers 可视化之热力图

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 热力图&#xff08;Heatmap&#xff09;又叫热点图&#xff0c;是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法

树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作&#xff0c;无需更改相机配置。但是&#xff0c;一…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!

5月28日&#xff0c;中天合创屋面分布式光伏发电项目顺利并网发电&#xff0c;该项目位于内蒙古自治区鄂尔多斯市乌审旗&#xff0c;项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站&#xff0c;总装机容量为9.96MWp。 项目投运后&#xff0c;每年可节约标煤3670…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI

前一阵子在百度 AI 开发者大会上&#xff0c;看到基于小智 AI DIY 玩具的演示&#xff0c;感觉有点意思&#xff0c;想着自己也来试试。 如果只是想烧录现成的固件&#xff0c;乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外&#xff0c;还提供了基于网页版的 ESP LA…...

【JavaWeb】Docker项目部署

引言 之前学习了Linux操作系统的常见命令&#xff0c;在Linux上安装软件&#xff0c;以及如何在Linux上部署一个单体项目&#xff0c;大多数同学都会有相同的感受&#xff0c;那就是麻烦。 核心体现在三点&#xff1a; 命令太多了&#xff0c;记不住 软件安装包名字复杂&…...

AI,如何重构理解、匹配与决策?

AI 时代&#xff0c;我们如何理解消费&#xff1f; 作者&#xff5c;王彬 封面&#xff5c;Unplash 人们通过信息理解世界。 曾几何时&#xff0c;PC 与移动互联网重塑了人们的购物路径&#xff1a;信息变得唾手可得&#xff0c;商品决策变得高度依赖内容。 但 AI 时代的来…...

C++:多态机制详解

目录 一. 多态的概念 1.静态多态&#xff08;编译时多态&#xff09; 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1&#xff09;.协变 2&#xff09;.析构函数的重写 5.override 和 final关键字 1&#…...

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)

本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...