2009-09-19 35 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移动到数据库表中。你建议的代码是非常令人印象深刻的,但对于这样一个简单的应用程序可能有点矫枉过正:)感谢所有这些努力! –