我在网上看到一篇文章
终于找到了答案
<?php
/**
 * @copyright   &#169; 2006, Schmalls / Joshua Thompson, All Rights Reserved
 * @license  http://www.opensource.org/licenses/bsd-license.php New BSD
 * @author   Joshua Thompson <[email protected]>
 * @version  1.0.0
 * @link http://www.countercubed.com
 */
/**
 * This class holds the prototype capabilities
 *
 * Extending this class makes it prototype capable
 */
class Prototype
{
/**
 * Holds prototype functions
 *
 * @var  array
 */
private $_functions = array();
/**
 * Default constructor
 *
 * This is here so that php doesn't complain about the prototype function
 */
public function __construct()
{
}
/**
 * Sets the prototype functions or variables
 *
 * @param   string $name
 * @param   mixed $value
 */
public function __set( $name, $value )
{
if ( function_exists( $value ) ) :
$this->_functions[$name] = $value;
else :
$this->$name = $value;
endif;
}
/**
 * Gets static prototype variables if they exist
 *
 * @param   string $name
 * @return  mixed
 */
public function __get( $name )
{
if ( isset( $this->prototype()->$name ) ) :
return $this->prototype()->$name;
else :
trigger_error( 'Undefined property: ' . __CLASS__ . '::' . $name, E_USER_NOTICE );
endif;
}
/**
 * Calls a static prototype function
 *
 * @param   string $name
 * @param   array $arguments
 * @return  mixed
 */
public function __call( $name, $arguments )
{
if ( isset( $this->_functions[$name] ) ) :
return call_user_func_array( $this->_functions[$name], $arguments );
elseif ( $this->prototype()->isCallable( $name ) ) :
return call_user_func_array( array( $this->prototype(), $name ), $arguments );
else :
trigger_error( 'Call to undefined method ' . __CLASS__ . '::' . $name . '()', E_USER_ERROR );
endif;
}
/**
 * Returns the static prototype holder
 *
 * @return  Prototype
 */
public static function prototype()
{
static $prototype = null;
if ( $prototype === null ) :
$prototype = new Prototype();
endif;
return $prototype;
}
/**
 * Needed for the static calling functionality
 *
 * @return  boolean
 */
public function isCallable( $name )
{
return ( isset( $this->_functions[$name] ) );
}
}
// make some prototype classes
class Test1 extends Prototype
{
}
class Test2 extends Prototype
{
}
class Test3 extends Test1
{
}
// lets create some test static functions
Test1::prototype()->fun1 = create_function( '$arg1', '
echo \'Static Test1::fun1 \' . $arg1 . "\n";
');
Test2::prototype()->fun2 = create_function( '$arg1', '
echo \'Static Test2::fun2 \' . $arg1 . "\n";
');
// now instantiate the objects
$test1 = new Test1();
$test2 = new Test2();
// and make some more functions
$test1->fun3 = create_function( '$arg2', '
echo \'Test1::fun3 \' . $arg2 . "\n";
');
$test2->fun4 = create_function( '$arg2', '
echo \'Test2::fun4 \' . $arg2 . "\n";
');
// output: Static Test1::fun1 bob
$test1->fun1( 'bob' );
// create another function
Test1::prototype()->fun2 = create_function( '$arg1', '
echo \'Static Test1::fun2 \' . $arg1 . "\n";
');
// output: Static Test1::fun2 bobby
$test1->fun2( 'bobby' );
// output: Static Test2::fun2 robert
$test2->fun2( 'robert' );
// output: Test1::fun3 robby
$test1->fun3( 'robby' );
// output: Test2::fun4 rob
$test2->fun4( 'rob' );
// another instance still has the static functions
$test1_2 = new Test1();
// output: Static Test1::fun1 bob
$test1_2->fun1( 'bob' );
$test3 = new Test3();
// this will give an error because prototype functions do not extend down to a child class
$test3->fun1( 'roberto' );
?>

解决方案 »

  1.   

    原文地址
    http://personal.schmalls.com/2006/11/06/prototype-based-programming-in-php/
    如果这样我们可以像javascript那样动态语言了
    写直php来淋漓畅快
      

  2.   

    以前没用过这个create_function,看了下它的原型,这个$argv是参数列表吧?$code是函数内生成的代码.的确是动态语言的特性.可以在自己的类里面用这个函数.不过这样的话会另效率降低.一些必要的方法,还是直接写上好,如果需要自己添加方法,似乎就不用再继承这个类了.
      

  3.   

    1、create_function函数是经常要用到的,尤其是喜欢使用回调函数的朋友
    2、而模拟javascript里的prototype就没有必要了。js不提供继承,所以只能用prototype给对象附加方法。php已经提供了继承因此也就没有必要模拟prototype了
      

  4.   

    xuzuning(唠叨) 可以不明白我说的动态指的是那里
    比如我已经有一个数据库对像
    $db;这个数据库对像已经query了我们一般这样while($db->arraylist[$i]) //这是数据库取出了全部行数据
    {
      $db->arraylist['list'][$i]['title']=substr($db->arraylist[$i]['title'],20);
      $i++;
    }
    模板这样子$tpl->assign("newslist",$db->arraylist);
    大概这样子/////////////////////
    Test2::prototype()->fun2 = create_function( '$arg1', '
    echo \'Static Test2::fun2 \' . $arg1 . "\n";
    ');我们把它换成我们数据库的
    $db::prototype()->fetchAll=ereate_funciton('$arg1','
      $this->arraylist['list'][]=$this->fetchRow;//要处理程序在这里加入
     /*注意这里程序会随着不同数据做出不同的处理,外加入url 截取,计算等*/
    ');这样我们直接可以用$db->fetchAll了
    在另一个页面我们再重写下
    $db::prototype()->fetchAll=ereate_funciton('$arg1','
      $this->arraylist['list'][]=$this->fetchRow;//要处理程序在这里加入
     /*注意这里程序会随着不同数据做出不同的处理,外加入url 截取,计算等*/
    ');
    这些程序是不是只用$db->fetchAll就取出了我想要的数据
      

  5.   

    你依然没有说明这种做法与在派生类中重载fetchAll的区别
    相反,ereate_funciton 定义的函数并不参与php代码加载时的预编译。因此执行ereate_funciton定义的函数时,php还需启动语法分析器做预编译,这样一来效率就要有所下降了
      

  6.   

    Test2::prototype()->fun2 = create_function( '$arg1','$str');
    这个$str是不是可以是字符串。
    我可以可动态加入要处理的php程序了。
    比如
    if(DEBUG){
    $str=" print_r(\$_POST);";
    }
    我可以调试输出提交怎么样
    在一个项目中我们专们有一个放调试文件当我设置项目为调试模式时候我们是不是可以
    动态包含进来。正式发布时候我们把DEBUG设置为false那么自动不会包括进调试程序。这个$str字符串可以任意添加程序代码。 让我想到了设计模式中的
    Decorator模式
    $str中的程序可以动态设置执行先后顺序,添加功能
    Observer模式
    $str 可以动态添加观察者
    就是javascript那个动态加入onload函数一样
    附送上
    javascript addloadEvent函数
    ----------------------------------
    function addloadEvent(func)
    {
      var oldonload=window.onload;
      if(typeof window.onload!='function')
      {
         window.onload=func;
      }else
      {
         window.onload=function(){
       oldonload();
       func();
     }
      }
    }
      

  7.   

    经过你们的分析,我觉得,如果偶尔需要给原类附加1,2个方法,可以使用create_function来生成会很方便.
    但如果需要附加的方法比较多,就不如直接继承了.继承与create_function的差异唠叨老大也说了,一个会预编译,一个不会,那么效率肯定是不会相同的.
      

  8.   

    在用callback function的时候常常这样用