2009-09-19 39 views
0

我正在開發一個Zend Framework中的Facebook應用程序。在startAction()中出現以下錯誤:爲什麼這個Zend Framework _redirect()調用失敗?

URL http://apps.facebook.com/rails_across_europe/turn/move-trains-auto無效。

我已經在下面包含了startAction()的代碼。我還包括了moveTrainsAutoAction的代碼(這些都是TurnController操作)。我在startAction()中找不到任何有關_redirect()的錯誤。我在其他操作中使用相同的重定向,並且它們完美無瑕地執行。如果您發現問題,請您查看我的代碼並讓我知道嗎?我很感激!謝謝。

public function startAction() { 
    require_once 'Train.php'; 
    $trainModel = new Train(); 

    $config = Zend_Registry::get('config'); 

    require_once 'Zend/Session/Namespace.php'; 
    $userNamespace = new Zend_Session_Namespace('User'); 
    $trainData = $trainModel->getTrain($userNamespace->gamePlayerId); 

    switch($trainData['type']) { 
     case 'STANDARD': 
     default: 
     $unitMovement = $config->train->standard->unit_movement; 
     break; 
     case 'FAST FREIGHT': 
     $unitMovement = $config->train->fast_freight->unit_movement; 
     break; 
     case 'SUPER FREIGHT': 
     $unitMovement = $config->train->superfreight->unit_movement; 
     break; 
     case 'HEAVY FREIGHT': 
     $unitMovement = $config->train->heavy_freight->unit_movement; 
     break; 
    } 
    $trainRow = array('track_units_remaining' => $unitMovement); 
    $where = $trainModel->getAdapter()->quoteInto('id = ?', $trainData['id']); 
    $trainModel->update($trainRow, $where); 
    $this->_redirect($config->url->absolute->fb->canvas . '/turn/move-trains-auto'); 
    } 
. 
. 
. 
    public function moveTrainsAutoAction() { 
$log = Zend_Registry::get('log'); 
$log->debug('moveTrainsAutoAction'); 
    require_once 'Train.php'; 
    $trainModel = new Train(); 

    $userNamespace = new Zend_Session_Namespace('User'); 
    $gameNamespace = new Zend_Session_Namespace('Game'); 

    $trainData = $trainModel->getTrain($userNamespace->gamePlayerId); 

    $trainRow = $this->_helper->moveTrain($trainData['dest_city_id']); 
    if(count($trainRow) > 0) { 
     if($trainRow['status'] == 'ARRIVED') { 
     // Pass id for last city user selected so we can return user to previous map scroll postion 
     $this->_redirect($config->url->absolute->fb->canvas . '/turn/unload-cargo?city_id='.$gameNamespace->endTrackCity); 
     } else if($trainRow['track_units_remaining'] > 0) { 
     $this->_redirect($config->url->absolute->fb->canvas . '/turn/move-trains-auto'); 
     } else { /* Turn has ended */ 
     $this->_redirect($config->url->absolute->fb->canvas . '/turn/end'); 
     } 
    } 
    $this->_redirect($config->url->absolute->fb->canvas . '/turn/move-trains-auto-error'); //-set-destination-error'); 
    } 
+1

不是100% - ,因此不打算寫這個作爲一個答案=) - 但你嘗試轉換%5F的成下劃線,因爲這是他們代表什麼。 –

回答

0

我想我可能已經找到答案。看起來Facebook並不擅長重定向,因此使用Facebook的'fb:redirect'FBML是必要的。這似乎工作:

$this->_helper->layout()->disableLayout(); 
$this->_helper->viewRenderer->setNoRender(); 

echo '<fb:redirect url="' . $config->url->absolute->fb->canvas . '/turn/move-trains-auto"/>'; 
0

默認情況下,這將發送一個HTTP 302重定向。由於它正在寫入標題,所以如果有任何輸出寫入HTTP輸出,程序將停止發送標題。嘗試查看Firebug中的請求和響應。

在其他情況下,嘗試使用_redirect()方法的非默認選項。例如,你可以嘗試:


$ropts = { 'exit' => true, 'prependBase' => false }; 
$this->_redirect($config->url->absolute->fb->canvas . '/turn/move-trains-auto', $ropts); 

沒有爲_redirect()方法另一個有趣的選項,代碼選項,例如,您可以發送一個HTTP 感動301永久代碼。


$ropts = { 'exit' => true, 'prependBase' => false, 'code' => 301 }; 
$this->_redirect($config->url->absolute->fb->canvas . '/turn/move-trains-auto', $ropts); 
+0

感謝Daniel的建議。我試過了,但錯誤依然存在。不過,我很感激幫助。 –

2

由於@Jani Hartikainen指出在他的評論中,我們實在沒有必要進行URL編碼下劃線。嘗試用文字下劃線重定向,看看是否有效,因爲我相信重定向使自己的網址編碼。


不是真的與你的問題,但在我看來,你應該重構你的代碼有點擺脫的switch-case語句(或者至少它們定位於單點):

控制器/ TrainController.php

[...] 
public function startAction() { 
    require_once 'Train.php'; 
    $trainTable = new DbTable_Train(); 

    $config = Zend_Registry::get('config'); 

    require_once 'Zend/Session/Namespace.php'; 
    $userNamespace = new Zend_Session_Namespace('User'); 
    $train = $trainTable->getTrain($userNamespace->gamePlayerId); 

    // Add additional operations in your getTrain-method to create subclasses 
    // for the train 
    $trainTable->trackStart($train); 
    $this->_redirect(
     $config->url->absolute->fb->canvas . '/turn/move-trains-auto' 
    ); 
    } 
    [...] 

模型/ DBTABLE/Train.php

class DbTable_Train extends Zend_Db_Table_Abstract 
    { 
    protected $_tableName = 'Train'; 
    [...] 
    /** 
     * 
     * 
     * @return Train|false The train of $playerId, or false if the player 
     * does not yet have a train 
     */ 
    public function getTrain($playerId) 
    { 
     // Fetch train row 
     $row = [..]; 
     return $this->trainFromDbRow($row); 

    } 
    private function trainFromDbRow(Zend_Db_Table_Row $row) 
    { 
     $data = $row->toArray(); 
     $trainType = 'Train_Standard'; 
     switch($row->type) { 
      case 'FAST FREIGHT': 
      $trainType = 'Train_Freight_Fast'; 
      break; 
      case 'SUPER FREIGHT': 
      $trainType = 'Train_Freight_Super'; 
      break; 
      case 'HEAVY FREIGHT': 
      $trainType = 'Train_Freight_Heavy'; 
      break; 
     } 
     return new $trainType($data); 
    } 

    public function trackStart(Train $train) 
    { 
     // Since we have subclasses here, polymorphism will ensure that we 
     // get the correct speed etc without having to worry about the different 
     // types of trains. 
     $trainRow = array('track_units_remaining' => $train->getSpeed()); 
     $where = $trainModel->getAdapter()->quoteInto('id = ?', $train->getId()); 
     $this->update($trainRow, $where); 
    } 
    [...] 

/米odels/Train.php

abstract class Train 
{ 

    public function __construct(array $data) 
    { 
     $this->setValues($data); 
    } 

    /** 
    * Sets multiple values on the model by calling the 
    * corresponding setter instead of setting the fields 
    * directly. This allows validation logic etc 
    * to be contained in the setter-methods. 
    */ 
    public function setValues(array $data) 
    { 
     foreach($data as $field => $value) 
     { 
     $methodName = 'set' . ucfirst($field); 
     if(method_exists($methodName, $this)) 
     { 
      $this->$methodName($value); 
     } 
     } 
    } 
    /** 
    * Get the id of the train. The id uniquely 
    * identifies the train. 
    * @return int 
    */ 
    public final function getId() 
    { 
     return $this->id; 
    } 
    /** 
    * @return int The speed of the train/turn 
    */ 
    public abstract function getSpeed(); 
    [..] //More common methods for trains 
} 

/models/Train/Standard.php

class Train_Standard extends Train 
{ 
    public function getSpeed() 
    { 
     return 3; 
    } 
    [...] 
} 

/models/Train/Freight/Super.php

class Train_Freight_Super extends Train 
{ 
    public function getSpeed() 
    { 
     return 1; 
    } 

    public function getCapacity() 
    { 
     return A_VALUE_MUCH_LARGER_THAN_STANDARD; 
    } 
    [...] 
} 
+0

我同意:該代碼確實需要重構。這是醜陋的和難以管理的。數據應該從application.ini移動到數據庫表中。你建議的代碼是非常令人印象深刻的,但對於這樣一個簡單的應用程序可能有點矯枉過正:)感謝所有這些努力! –