0

iPhone やその他の iOS デバイスの検出を追加したモバイル サイトがあります。iOS ページには、通常のページ (実際には古いモバイル デバイス用) とは異なるレイアウトとビューが必要です。それで、モバイル検出を行うコードがいくつかありますが、その部分は簡単でした。私がやりたいのは、iOS デバイスが検出されたときに Zend が自動的に正しいレイアウトとビューを見つけて使用するようにすることですが、それは驚くほど難しいことが判明しました...

できるだけ早く起動して実行する必要があったため、機能する簡単で汚いハックを行いました。各アクション関数には、iOS ブール値フラグが設定されているかどうかを検出する単純な If ステートメントがあります (これはコントローラーの init で発生します)。であり、そうであれば、レイアウトとビューを明示的にオーバーライドします。既存のコード (アクション内):

if ($_SESSION['user']['iPhone']) {
    $this->_helper->layout->setLayout('osriphone'); // 'osr' is the name of the app
    $this->_helper->viewRenderer->setRender('iphone/index');
}

これは機能しますが、ちょっと醜くてハックで、各アクションに配置する必要があり、各アクションのレンダラーを設定する必要があります。Zend ContextSwitch について読んだところ、まさに私がすべきことのように思えました。を使用する (私はまだ Zend に慣れていない) ので、いじり始めましたが、よくわかりません。

コントローラーの init で、ContextSwitch を初期化し、'iphone' のコンテキストを追加し、接尾辞を 'iphone' に設定しています。コンテキストを「iphone」に設定すると、正しいレイアウトとビューが自動的に使用されるようになります。新しいコード (コントローラーの init 内):

$this->_helper->contextSwitch()->initContext();
$contextSwitch = $this->_helper->getHelper('contextSwitch');
$contextSwitch->addContext('iphone', array('suffix' => 'iphone'));
$contextSwitch->setAutoDisableLayout(false);
if ($_SESSION['user']['iPhone']) {
    //$this->_currentContext = 'iphone'; // Doesn't work.
    //$contextSwitch->initContext('iphone'); // Doesn't work.
    //$contextSwitch->setContext('iPhone'); // Not the function I'm looking for...
    // What to put here, or am I barking up the wrong tree?
}

contextSwitcher でいくつかの読み取りを行いましたが、たとえば、特定のアクションごとに固有に設定するなど、多くのものがオンになっているようです (これは必要ありません。これは、アプリのすべてのアクションで発生する必要があります)。 /osr/format/iphone のようなものへのすべてのリンクを調べて変更し、コンテキストを切り替えます (これも実際には必要ではなく、望んでもいません。既にモバイル サイトであり、レイアウト/ビューを次のように切り替えたいと考えています)。ユーザーに対して完全に透過的であり、私の迅速で汚いハックのようにバックエンドからのみ処理されます)。これらは基本的に、私の簡単で汚いハックと同じ量のコードのように見えます。だから...誰か提案はありますか?「$contextSwitch->setContext('iphone');」のような 1 行だけを本当に望んでいます。コントローラーの init の If ステートメントで使用できる

4

3 に答える 3

0

ContextSwitchは、リクエストオブジェクトの「format」プロパティで動作します(デフォルト)。アプリのどこかに設定する必要があります

$requestObject->setParam('format', 'iphone').

ブートストラップ、より適切にはコントローラープラグインに設定しますが、どこに配置するかはアプリによって異なります。

于 2012-05-21T20:03:03.397 に答える
0

わかりました、これをプラグインに入れる方法を考え出したと思います:

プラグイン:

//This is my own namespace for ZF 1.x library, use your own
class My_Controller_Plugin_Ios extends Zend_Controller_Plugin_Abstract {

    public function preDispatch(Zend_Controller_Request_Abstract $request) {
        parent::preDispatch($request);

        if ($_SESSION['user']['iPhone']) {
            $this->_helper->layout->setLayout('osriphone');
            $this->_helper->viewRenderer->setRender('iphone/index');
        }
    }
}

プラグインを application.ini に登録します

resources.frontController.plugins.ios = "My_Controller_Plugin_Ios"

それだけだと思います。userAgent プラグインを調べることもできますが、

于 2012-05-22T07:53:28.623 に答える
0

私は Zend ContextSwitch を使用していないので、実際には役に立ちませんが、コントローラーでいくつかの継承を使用して、すべてのレイアウトを数行で設定できます。それはまだ「ハック」として分類されているかもしれませんが、それははるかに優れたハックです

アクションを実行するたびに、Zend は最初にフレームワーク内の他の多くの関数 (ルーティング、preDispatch、アクション ヘルパーなど) を起動します。また、PostDispatch などのアクションの後に多くのものを起動します。これは有利に使用できます。

最初に "mainController" のようなコントローラーを作成し、Zend_Controller_action を拡張させ、このコントローラーで predispatch() という関数を作成します。通常のコントローラーを mainController に拡張します。predispatch() という関数があるので、Zend はすべてのコントローラーでこれを自動的に起動します。そこで iPhone/iOS チェックを行うと、上書きしない限り、すべてのコントローラーのすべてのアクションで自動的に実行されます。コントローラーのメソッド (これを防ぐために、このメソッドを final にすることができます)。もちろん、mainctroller 内で多数のさまざまな非 Zend 関数やヘルパーを使用して、コードをできるだけコンパクトで再利用可能なものにすることができます。以下のサンプル コードを参照してください。

<?php
/**
*Maincontroller
*/
class MainController extends Zend_Controller_Action
{
    /**
    * Predispatch function is called everytime an action is called
    */
    final public function preDispatch(){
        //for security reasons, make sure that no one access mainController directly
        $this->request = $this->getRequest();
        if (strtolower($this->request->controller)=='main')
            $this->_redirect('/index/index/');

        //Check for iPhone
        if ($_SESSION['user']['iPhone']) {
            $this->_helper->layout->setLayout('osriphone'); // 'osr' is the name of the app
            $this->_helper->viewRenderer->setRender('iphone/index');
        }
    }
 }


<?php
/**
*Othercontroller
*/
class OtherController extends MainController
{
    /**
    * The correct layout for IndexAction is already set by the inherited preDispatch
    */
    public function indexAction(){
        /* YOUR CODE HERE */
    }
 }

ディスパッチ プロセスの概要については、次のリンクを確認してください (どちらも同じ画像): http://nethands.de/download/zenddispatch_en.pdf

http://img.docstoccdn.com/thumb/orig/22437345.png

于 2012-05-21T19:47:35.353 に答える