`
bardo
  • 浏览: 371658 次
  • 性别: Icon_minigender_1
  • 来自: 上海
博客专栏
D1407912-ab64-3e76-ae37-b31aa4afa398
浅述PHP设计模式
浏览量:11594
9d6df9f7-91da-3787-a37c-0e826525dd5d
Zend Framewor...
浏览量:9970
85b628bd-a2ed-3de2-a4b1-0d34985ae8b6
PHP的IDE(集成开发环...
浏览量:9326
社区版块
存档分类
最新评论

PHP:在对象上动态添加一个新的方法

    博客分类:
  • PHP
阅读更多

有关在一个对象上动态添加方法,如果你来自Ruby语言或您熟悉这门语言,你已经知道它是什么...... Ruby提供给你一种方式来获得一个instancied对象,并给这个对象添加一个额外的方法。

 

好!不说Ruby了,让我们来谈谈PHP

 

PHP未提供一个“标准的方式”做这样的事情,这也是没有核心的一部分...

 

但无论如何,它并没有说我们不能做这样的事情。

 

因此,让我们看一下代码,我将展示两个实现:一是使用PHP 5.3,另一个使用PHP5.4,这些例子充分利用在PHP 5.3版本中增加的匿名函数(闭包),并且也利用闭包类的优势以及在5.4版本添加的方法绑定。

 

在PHP 5.3中添加方法的对象

 

 

/**
 * Example in PHP 5.3 
 */
class Meta
{
    
    private $methods = array();

    public function addMethod($methodName, $methodCallable)
    {
        if (!is_callable($methodCallable)) {
            throw new InvalidArgumentException('Second param must be callable');
        }
        $this->methods[$methodName] = $methodCallable;
    }

    public function __call($methodName, array $args)
    {
        if (isset($this->methods[$methodName])) {
            array_unshift($args, $this);
            return call_user_func_array($this->methods[$methodName], $args);
        }

        throw RunTimeException('There is no method with the given name to call');
    }

}

 

 

 

/**
 * Example in PHP 5.3 
 */
require 'Meta.php';

$meta = new Meta();

$meta->addMethod('color', function ($self) {
    $self->name = 'My Name';
    return '#00000';
});

echo $meta->color(), PHP_EOL;
echo $meta->name, PHP_EOL;

 GitHub 的链接 https://gist.github.com/krolow/4189729#file-meta-php

 

它是如何工作的?

它使匿名函数和魔术方法__call,该类元有方法addMethod的使用,这种方法是等待两个参数,第一个是方法名,第二个可调用匿名函数。

 

每次调用原始对象没有(未在类中声明)的方法,该方法调用一下,函数调用将寻找你是否有给定名称注册一个新的方法,如果是,它调用匿名函数,传参数给当前对象的匿名函数,所以你可以访问类的方法和属性。

 

它有一定的局限性,你将不能访问私有的方法和属性,但它有可能使用象反射这样的方法来处理。

 

在PHP5.4中添加方法的对象

trait MetaTrait
{
    
    private $methods = array();
 
    public function addMethod($methodName, $methodCallable)
    {
        if (!is_callable($methodCallable)) {
            throw new InvalidArgumentException('Second param must be callable');
        }
        $this->methods[$methodName] = Closure::bind($methodCallable, $this, get_class());
    }
 
    public function __call($methodName, array $args)
    {
        if (isset($this->methods[$methodName])) {
            return call_user_func_array($this->methods[$methodName], $args);
        }
 
        throw new RunTimeException('There is no method with the given name to call');
    }
 
}

  

 

require 'MetaTrait.php';

class HackThursday {
    use MetaTrait;

    private $dayOfWeek = 'Thursday';

}

$test = new HackThursday();
$test->addMethod('when', function () {
    return $this->dayOfWeek;
});

echo $test->when();

 

 

GitHub中的链接:https://gist.github.com/krolow/4264062#file-test-php

 

正如你所看到的第二个例子让使用trait,PHP5.4的另一项新功能,这样一来我们使模向合成,这是一个好主意,更解耦你的代码。

 

trait作为与PHP 5.3的类Meta.php颇为相似,也是对象的用法,这里的区别是,当添加方法时你匿名函数不再需要接收的对象实例作为参数,正如你在测试的例子可以看到的,并且你能够直接访问$this引用的对象的方法和属性,这就是可能的,因为有Closure::bind,,因为有这一招,我们能够注入对象,将通过传参添加方法的匿名函数放到内部范围。所以一旦你调用该方法,它是动态创建的,我们调用的闭包是在你添加方法时存储在内存中的,并且闭包是与实例在同一范围的。所以我们现在能够访private属性, protected等...并它看起来也更好一点,因为我们并不需要强制的第一个参数是对象的实例。

 

我到底为什么要用它呢?

 

这只是动态添加方法的一种实践,当你想创造更通用的东西,或为你代码的API创建一个漂亮的接口,它给出了一些灵活性。但是必须注意很重要的一点,也许坏的程序员用这样类似的方法可以做出让人发疯的东西。

 

 

原文网址:

http://cobaia.net/php/2012/12/12/php-adding-a-new-method-to-an-object-on-the-fly/

 

 

 

分享到:
评论

相关推荐

    PHP 面向对象技术(全面讲解).txt

    这个配置单上加一个或少一个配件,那么装出来的9 个机子都改变了,这是类和对象的关系(类的 实例化结果就是对象)。 3.什么是面向对象编程呢? 就不说他的概念,如果你想建立一个电脑教室,首先要有一个房间, 房间...

    PHP基础教程 是一个比较有价值的PHP新手教程!

    以下是可以使用的方法: <?php . . . ?> <script language="php"> . . . </script> 语句 与Perl和C一样,在PHP中用(;)来分隔语句。那些从HTML中分离出来的标志也表示语句的结束。 注释 PHP支持C,C++和Unix...

    PHP设计模式精彩剖析

    PHP设计模式是一种面向对象编程的技术,它们提供了一套解决常见软件设计问题的经验总结和通用解决方案。设计模式可以帮助开发人员编写可重用...7. 装饰者模式(Decorator Pattern):动态地给一个对象添加额外的功能。

    core:敏捷工具包的核心对象特征

    动态方法:将方法动态添加到现有对象中 工厂:将类名称指定为字符串 应用范围:注入全局“应用”对象并将其传递给新对象 另外,对于通用异常,您还有一个更好的“异常”类。 社区与支持 从Composer安装 composer ...

    通过php添加xml文档内容的方法

    这里讲述的添加xml文档内容,从上一篇《DOM基础及php读取xml内容操作的方法》继续,代码如下: 复制代码 代码如下:<?php //1、创建一个DOMDocument对象。该对象就表示 xml文件 $xmldoc = new DOMDocument(); //2...

    php+html5使用FormData对象提交表单及上传图片的方法

    本文实例讲述了php+html5使用FormData对象提交表单及...1.创建一个FormData空对象,然后使用append方法添加key/value 复制代码 代码如下:var formdata = new FormData();  formdata.append(‘name’,’fdipzone’); 

    jquery插件使用方法大全

    延迟对象 延迟对象(Deferred Object,jQuery.Deferred对象)是一个可链接的(chainable)实用工具对象,实现了Promise接口,可以在回调队列中注册多个回调、调用回调队列并转发任何同步/异步函数的成败状态。...

    php通过array_unshift函数添加多个变量到数组前端的方法

    本文实例讲述了php通过array_unshift函数添加多个变量到数组前端的方法。分享给大家供大家参考。具体分析如下: php通过array_unshift函数添加多个变量到数组前端,函数返回添加后的数组元素个数 <?php $alpha =...

    php面向对象与面向过程两种方法给图片添加文字水印

    目前绝大多数PHP程序员使用面向过程的方式,因为解析WEB页面本身就非常“过程化”(从一个标签到另一个标签)。在HTML中嵌入过程处理代码是很直接自然的作法,所以PHP程序员通常使用这种方式。 如果你是刚接触PHP,用...

    PHP和MySQL Web开发第4版pdf以及源码

    1.4 添加动态内容 1.4.1 调用函数 1.4.2 使用date()函数 1.5 访问表单变量 1.5.1 简短、中等以及长风格的表单变量 1.5.2 字符串的连接 1.5.3 变量和文本 1.6 理解标识符 1.7 检查变量类型 1.7.1 PHP的数据...

    头像制作抖音微信壁纸小程序搭建一个基于uniCloud阿里OSS对象存储的免费图床源码

    目前市面上很多图床基本上都长久不了,这样就迫使自己需要有一个可以掌控的图床储存,社长给大家分享一个基于对象存储 OSS 的的免费图片,uniCloud 提供免费 100G 云存储空间,目前新注册的好像只有 10G 了,不过也...

    php图片添加水印类库

    一个php图片添加水印类,获得数据库模型的对象,水印处理配置项,添加水印方法,获得图片资源,获得水印位置。

    PHP和MySQL WEB开发(第4版)

    1.4 添加动态内容 1.4.1 调用函数 1.4.2 使用date()函数 1.5 访问表单变量 1.5.1 简短、中等以及长风格的表单变量 1.5.2 字符串的连接 1.5.3 变量和文本 1.6 理解标识符 1.7 检查变量类型 1.7.1 PHP的数据类型 1.7.2...

    强大的php生成word ,html,rtf,pdf框架(包含中文文档)

    添加对象 15 添加标题 15 添加目录 16 表格 17 添加表格 17 添加行 17 添加单元格 17 单元格样式 19 表格样式 20 页脚 22 页眉 23 模版 23 其他问题修改 25 解决文本缩进问题 25 表格对齐和表格缩进 27 图片缩进和...

    oow:面向对象的WordPress插件开发方法

    什么是O? Oow是一个包含可简化插件开发的...在您的composer.json文件eabay/oow添加为依赖项。 用法 首先创建一个插件类: <?php namespace Plugins ; /** @Plugin */ class HelloWorld { /** @Hook(tag="wp_f

    精通正则表达式基于.NET ASP PHP JSP JavaScript

    StringBuilderApplication/DealWithStringBuilder.aspx 动态字符串处理 第9章(/09/) RegexApplication/Default.aspx 正则表达式类的应用 RegexApplication/GetPageHtmlData.aspx 获取网页的内容 ...

    xheditor-1.1.14

    xhEditor也提供了即时的卸载编辑器方法: $('#elm1').xheditor(false); 2.2. 初始化参数列表 初始化参数示例代码: $('#elm1').xheditor({tools:'full',skin:'default',showBlocktag:true,internalScript:false,...

    深入php面向对象、模式与实践

    //在原对象中添加 function __clone(){ $this->对象 = clone $this->对象 } __clone在clone前自动触发,可以执行一些在备份前的属性操作. 2、&传递引用 方法引用传递,改变源对象 复制代码 代码如下: function set_K...

Global site tag (gtag.js) - Google Analytics