1

ライブサイトでいくつかの新機能をテストしようとしています。

私の目標は、プレフィックス(たとえば、「dev」)を付け、そのプレフィックスに、dev_ {action_name}として定義したものを除いて、デフォルトのアクションを含む完全なサイトを表示させることです。

例:

/dev/orders/create

OrdersController :: dev_create()アクションが見つからない場合は、OrdersController :: create()を使用します。

これまでのところ、ルーターで標準の「dev」プレフィックスを作成し、次のようなbeforeFilterマジックを配置することができました。

<?php
//bootstrap.php code:
Configure::write('Routing.prefixes', array('admin', 'dev'));

// AppController::beforeFilter() code:
if (preg_match('/^dev_(.*)$/', $this->params['action'], $subs)){
   $new_action = $subs[1];
   if (method_exists($this, $new_action)){
          $this->params['action'] = $new_action;
    } 
}
?>

これは期待どおりに機能しますが、完全なルーティングスキーマが「dev」にコピーされないため、すべてのリンクが「devプレフィックス」なしでレンダリングされ、カスタムルートが無視されます。

.htaccessルールで修正し、クエリ文字列にdev=trueを入れることを考えました。

#webroot/.htaccess
RewriteRule ^dev(.*)$ index.php?dev=true&%{QUERY_STRING}
#... rewrite conds ...
RewriteRule ^(.*)$ index.php [QSA,L] #original Cake rewrite

しかし、これでは結果が得られませんでした(Cakeは、書き直されたものではなく、元のURLを解析していました)。

これを行う「正しい」方法はありますか?

4

2 に答える 2

1

このような何かがあなたが望むことをするべきです。アクションを呼び出す前に、アクションが存在するかどうかを確認し、存在しない場合は元のアクションにフォールバックします。後で実行すると、アクションが存在しないため、例外が発生します。

それ以上のものがあるかもしれませんが、これは始まりです。

// need to override invokeAction
public function invokeAction(CakeRequest $request) {
  if ($request->prefix == 'dev') {
    if (!method_exists($request->action)) {
      $request->action = str_replace($request->prefix.'_', '', $request->action);
      $request->prefix = null;
    }
  }
  return parent::invokeAction($request);
}
于 2012-10-02T01:11:56.730 に答える
1

私はCakePHP2.2.1でこれを成功裏に達成しました。それは醜いです、それは長いです、それは規則に反しています、しかしそれはうまくいきます!:D

ファイル:/app/webroot/.htaccess

RewriteEngine On
RewriteRule ^dev/(.*)$ $1 //my hack
    //      /dev/orders/create => /orders/create 
    //      /dev/css/main.css => /css/main.css
    // This only changes the url for the next rule
    // Cake would have still parsed /dev/orders/create
    // but this is needed for the sake of static files in app/webroot
//cake native rewrite
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php [QSA,L]

ファイル:bootstrap.php

$url = (!empty($_SERVER['REQUEST_URI'])) ? $_SERVER['REQUEST_URI'] : ''; 
    //$url is still /dev/orders/create, despite the rewrites

Configure::write('App.dev', false); 
//we use this to check if we're in "dev" mode
//anywhere in the app, just call: 
    //  if ( Configure::read('App.dev') ) ...

//check if URL starts with /dev
if (preg_match('|^/dev|', $url)){ 
    /* the most important thing is to trick CakePHP
    into thinking it's on a /dev/ subfolder on the server
    this preserves all the routing as it 
            should be, not making it prefixed route */
    Configure::write('App.base', '/dev');
    Configure::write('App.dev', true);
    //this changes /dev/orders/create to /orders/create 
            //for Cake's Route parser
    $_SERVER['REQUEST_URI'] = preg_replace('|/dev|', '', $_SERVER['REQUEST_URI']); 
}
?>

この時点で、CakePHPに/dev/の下のサイトの完全なコピーを表示させるために必要なものはすべて揃っています。Cakeはすべてのデフォルトのアクションとビューを実行し、すべてのリンクは期待どおりに機能し(URLにヘルパーを使用している限り)、すべての静的ファイルが提供されます。すべてのアプリパスと定数はそのまま残ります。

さて、いくつかのメソッドマジックについて:

<?php
//file: AppController.php
public function invokeAction(CakeRequest $request) {

    if (Configure::read('App.dev')) {
        $new_action = 'dev'.$request->params['action'];
        if (method_exists($this, $new_action)){
            $request->params['action'] = $new_action;
        }
    }


    return parent::invokeAction($request);
}
?>

これらすべてにより、次のことが可能になります。

  • / dev /にサイトの完全に機能するエイリアスがあります。これには、ルート、プレフィックス、静的ファイル、データベース接続などが含まれます。
  • 名前の前に「dev」を使用してACTIONをオーバーライドします。
  • 「dev」または「notdev」のスイッチを1つ用意します(App.dev config)

例えば:

<?php
//OrdersController.php

//gets called on /admin/orders/view
public function admin_view(){} 

//gets called on /dev/admin/orders/view
public function devadmin_view(){ 
    //views have to be defined manually for DEV actions
    $this->render('devadmin_view'); 
}

//gets called on /admin/orders/add 
//            AND /dev/admin/orders/add
public function admin_add() {} 

?>
于 2012-10-02T07:06:32.647 に答える