2016-01-20 62 views
2

我正在研究使用Lumen或可能Slim的項目,並想知道是否有可能基於目錄結構自動加載控制器而不是必須註冊所有路由。如何使用Lumen或Slim框架實現默認路由行爲

這就是我希望自動加載的工作原理。

例指南/類結構:

/app/Http/Controllers/ 
    Foo/ 
     BarController.php  # App\Http\Controllers\Foo\BarController 

如果路由是

example.com/foo/bar == App\Http\Controllers\Foo\BarController::index()

example.com/foo/bar/add == App\Http\Controllers\Foo\BarController::add()

註冊路線應優先於自動加載類秒。

我發現了一種基於Opencart路由方法的方法。 他們有超過396個控制器的1145種不同的公共方法,這些控制器都是在沒有明確說明控制器方法的情況下調用的。 這是我的嘗試。

htaccess的

RewriteRule ^([^?]*) index.php?route=$1 [L,QSA]

應用程序/ HTTP/routes.php文件

$route = array_shift($_GET); 
$method_name = ''; 

$parts = explode('/', preg_replace('/[^a-zA-Z0-9_\/]/', '', (string)$route)); 

while ($parts) { 

    $class = '\App\Http\Controllers\\' . implode('\\', $parts); 

    if (class_exists($class)){ 
     $app->match($route, $class . '@' . method_exists($class, $method_name) ? $method_name : 'index'); 
     break; 
    } else { 
     $method_name = array_pop($parts); 
    } 
} 

如果需要路線,其與默認值不同的Opencart的然後使用.htaccess RewriteRuleresponse->redirect路由到一個替代控制器。

我會用他們的方法,但陳述我的路線覆蓋 app/Http/routes.php。像這樣

// route overrides 
$app->get('/', 'common/hom[email protected]'); 
$app->get('/home', 'common/[email protected]'); 

我是否正確的思維,這將讓應用程序運行得更快,因爲它不會有所有註冊的路線匹配搜索?

有沒有更好的方法來執行這個自動路由過程?

+1

您試圖做的事情不會讓您的應用程序工作得更快或更慢,出於某種原因,人們爲了優化而專注於錯誤的事情。然而,你的想法完全破壞了路由的目的。您**希望**定義一條路線,而您**希望**明確說明將要處理的路線。如果你試圖「自動化」路由處理程序,那麼你正在實現隱藏的魔法。最終,路線將與處理程序(控制器/功能)匹配。明確說明它是如何處理它是非常好的。除了麻煩之外,這種類型的自動化沒有任何好處。 – Mjh

回答

1

我認爲你可以使用reflection和Slim 3對defining routes with controller methods instead of closures的支持組合來完成這項工作。

的基本策略是如下:

  1. 搜索通過每個控制器類(使用glob或自動裝載機)的;
  2. 對於每個班級,撥打ReflectionClass::getMethods,使用ReflectionMethod::IS_PUBLIC過濾器,以便您只能獲得該班級的公共方法;
  3. 使用ReflectionClass::getName和命名空間(如有必要)使用ReflectionClass::getNamespaceName獲取類名稱;
  4. 從命名空間,類名稱和方法名稱構建您的路由簽名,可能使用類似https://github.com/cocur/slugify的slugification庫;
  5. 生成相應的路線$app->get($route_signature, "$class_name:$method_name")

這是一個有趣的想法,雖然您需要非常小心,這不會意外暴露您不希望客戶端直接訪問的任何方法。其他一些注意事項:

  • 反思是非常緩慢的,所以你可能會想實現這個更構建步驟,緩存生成的路由,而不是對每個請求飛再生他們。
  • 您可能需要一些額外的命名約定來區分HTTP動詞。例如,以get開始與GET路線對應的所有方法名稱。因此,您可能有\Foo\BarController::getAdd,\Foo\BarController::postAdd
  • 構建參數化路線(/bar/add/{id})將會多一點工作,因爲您可能需要使用ReflectionFunctionAbstract::getParameters來提取相應的方法參數。同樣,您需要根據這些參數來決定如何構建路線。