在PHP中伪造方法属性?

前端之家收集整理的这篇文章主要介绍了在PHP中伪造方法属性?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
PHP中可以使用等效的.NET方法属性,还是以某种方式模拟这些?

上下文

我们有一个我们喜欢的内部URL路由类.它今天工作的方式是,我们首先必须使用中央路由管理员注册所有的路由,如下所示:

$oRouteManager->RegisterRoute('admin/test/',array('CAdmin','SomeMethod'));
$oRouteManager->RegisterRoute('admin/foo/','SomeOtherMethod'));
$oRouteManager->RegisterRoute('test/',array('CTest','SomeMethod'));

每当遇到路由时,调用回调方法(在上述情况下都是静态类方法).但是,这样做将路由与方法分开,至少在代码中.

我正在寻找一些方法来使路线更接近方法,你可以在C#中完成:

<Route Path="admin/test/">
public static void SomeMethod() { /* implementation */ }

我现在看到的选项是要创建一些PHPDoc扩展,让我能够这样:

/**
 * @route admin/test/
 */
public static function SomeMethod() { /* implementation */ }

但是,这将需要编写/重用PHPDoc的解析器,并且很可能会相当缓慢.

另一个选择是将每个路由分成自己的类,并具有如下所示的方法

class CAdminTest extends CRoute
{
    public static function Invoke() { /* implementation */ }
    public static function GetRoute() { return "admin/test/"; }
}

然而,这仍然需要注册每个单一的类,并且将有大量的类(不用说额外的代码量).

那么这里有什么选择?什么是最好的方式来保持路由接近于它调用方法

这就是我最终解决这个问题. article provided by Kevin是一个巨大的帮助.通过使用ReflectionClass和ReflectionMethod :: getDocComment,我可以轻松地浏览PHPDoc注释.一个小的正则表达式找到任何@route,并注册到该方法.

反思不是那么快(在我们的情况下,在一个单独的函数中对于RegiserRoute进行硬编码调用的速度是慢2.5倍),而且由于我们有很多路由,所以我们不得不将完成的路由列表缓存Memcached,所以在每一页的加载上都不需要反射.总的来说,我们最终在缓存时平均花了7ms将路由注册为1,7ms(平均每个页面的反射使用了18ms).

如果需要手动注册,可以在子类中覆盖的代码如下所示:

public static function RegisterRoutes()
{
    $sClass = get_called_class(); // unavailable in PHP < 5.3.0
    $rflClass = new ReflectionClass($sClass);
    foreach ($rflClass->getMethods() as $rflMethod)
    {
        $sComment = $rflMethod->getDocComment();
        if (preg_match_all('%^\s*\*\s*@route\s+(?P<route>/?(?:[a-z0-9]+/?)+)\s*$%im',$sComment,$result,PREG_PATTERN_ORDER)) 
        {
            foreach ($result[1] as $sRoute)
            {
                $sMethod = $rflMethod->GetName();
                $oRouteManager->RegisterRoute($sRoute,array($sClass,$sMethod));
            }
        }
    }
}

感谢大家指出我正确的方向,这里有很多好的建议!我们采用这种方法,只是因为它允许我们保持路由接近它调用代码

class CSomeRoutable extends CRoutable
{
    /**
     * @route /foo/bar
     * @route /for/baz
     */
    public static function SomeRoute($SomeUnsafeParameter)
    {
        // this is accessible through two different routes
        echo (int)$SomeUnsafeParameter;
    }
}

猜你在找的PHP相关文章