扩展 PHP Class 以允许通过 __callStatic 找到的新方法
Extend PHP Class to allow new methods found via __callStatic
寻找一种灵活的方式来允许其他开发人员为模板系统扩展渲染方法,基本上允许他们生成自己的 render::whatever([ 'params' ]) 方法。
从单个开发人员的角度来看,当前的设置工作得很好,我有许多基于上下文(post、媒体、分类法等)的 classes 设置,其中__callStatic
方法收集调用函数,检查 method_exists
是否在 class 中,如果是,则提取任何传递的参数并呈现输出。
快速示例(伪代码):
-- view/page.php
render::title('<div>{{ title }}</div>');
-- app/render.php
class render {
public static function __callStatic( $function, $args ) {
// check if method exists
if ( method_exists( __CLASS__, $function ){
self::{ $function }( $args );
}
}
public static function title( $args ) {
// do something with the passed args...
}
}
我想允许开发人员从他们自己包含的 class 中扩展可用的方法 - 这样他们就可以创建例如 render::date( $args );
并将其传递给他们的逻辑以收集数据,然后再呈现结果到模板。
问题是,哪种方法最有效且性能最好 - 错误和安全性在这一点上不是一个大问题,可以稍后再解决。
编辑 --
我已经通过执行以下操作(再次伪代码..)来完成这项工作:
-- app/render.php
class render {
public static function __callStatic( $function, $args ) {
// check if method exists
if (
method_exists( __CLASS__, $function
){
self::{ $function }( $args );
}
// check if method exists in extended class
if (
method_exists( __CLASS__.'_extend', $function
){
__CLASS__.'_extend'::{ $function }( $args );
}
}
public static function title( $args ) {
// do something with the passed args...
}
}
-- child_app/render_extend.php
class render_extend {
public static function date( $args = null ) {
// do some dating..
}
}
这里的问题是这仅限于基础 render() 的一个扩展 class。
一种常见的方式(由 Twig 和 Smarty 使用,举几个例子)是要求开发人员手动将他们的扩展注册为可调用对象。 render
class 保留了它们的记录,然后除了检查自己的内部方法外,还检查来自 _callStatic
.
的列表
根据您已有的资料,这可能看起来像这样:
class render
{
/** @var array */
private static $extensions;
public static function __callStatic($function, $args)
{
// check if method exists in class methods...
if ( method_exists( __CLASS__, $function )) {
self::{$function}(self::$args);
}
// and also in registry
elseif (isset(self::$extensions[$function])) {
(self::$extensions[$function])($args);
}
}
public static function title($args)
{
// do something with the passed args...
}
public static function register(string $name, callable $callback)
{
self::$extensions[$name] = $callback;
}
}
开发人员会像这样使用它:
render::register('date', function($args) {
// Do something to do with dates
});
完整演示在这里:https://3v4l.org/oOiN6
寻找一种灵活的方式来允许其他开发人员为模板系统扩展渲染方法,基本上允许他们生成自己的 render::whatever([ 'params' ]) 方法。
从单个开发人员的角度来看,当前的设置工作得很好,我有许多基于上下文(post、媒体、分类法等)的 classes 设置,其中__callStatic
方法收集调用函数,检查 method_exists
是否在 class 中,如果是,则提取任何传递的参数并呈现输出。
快速示例(伪代码):
-- view/page.php
render::title('<div>{{ title }}</div>');
-- app/render.php
class render {
public static function __callStatic( $function, $args ) {
// check if method exists
if ( method_exists( __CLASS__, $function ){
self::{ $function }( $args );
}
}
public static function title( $args ) {
// do something with the passed args...
}
}
我想允许开发人员从他们自己包含的 class 中扩展可用的方法 - 这样他们就可以创建例如 render::date( $args );
并将其传递给他们的逻辑以收集数据,然后再呈现结果到模板。
问题是,哪种方法最有效且性能最好 - 错误和安全性在这一点上不是一个大问题,可以稍后再解决。
编辑 --
我已经通过执行以下操作(再次伪代码..)来完成这项工作:
-- app/render.php
class render {
public static function __callStatic( $function, $args ) {
// check if method exists
if (
method_exists( __CLASS__, $function
){
self::{ $function }( $args );
}
// check if method exists in extended class
if (
method_exists( __CLASS__.'_extend', $function
){
__CLASS__.'_extend'::{ $function }( $args );
}
}
public static function title( $args ) {
// do something with the passed args...
}
}
-- child_app/render_extend.php
class render_extend {
public static function date( $args = null ) {
// do some dating..
}
}
这里的问题是这仅限于基础 render() 的一个扩展 class。
一种常见的方式(由 Twig 和 Smarty 使用,举几个例子)是要求开发人员手动将他们的扩展注册为可调用对象。 render
class 保留了它们的记录,然后除了检查自己的内部方法外,还检查来自 _callStatic
.
根据您已有的资料,这可能看起来像这样:
class render
{
/** @var array */
private static $extensions;
public static function __callStatic($function, $args)
{
// check if method exists in class methods...
if ( method_exists( __CLASS__, $function )) {
self::{$function}(self::$args);
}
// and also in registry
elseif (isset(self::$extensions[$function])) {
(self::$extensions[$function])($args);
}
}
public static function title($args)
{
// do something with the passed args...
}
public static function register(string $name, callable $callback)
{
self::$extensions[$name] = $callback;
}
}
开发人员会像这样使用它:
render::register('date', function($args) {
// Do something to do with dates
});
完整演示在这里:https://3v4l.org/oOiN6