【问题标题】:Why is this Zend Framework _redirect() call failing?为什么这个 Zend Framework _redirect() 调用失败?
【发布时间】:2009-09-19 14:49:55
【问题描述】:

我正在 Zend Framework 中开发一个 Facebook 应用程序。在 startAction() 我收到以下错误:

网址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');
  }

【问题讨论】:

  • 不是 100% - 因此不会将其写为答案 =) - 但是您是否尝试过将 %5F 转换为下划线,因为这就是它们所代表的含义。

标签: php zend-framework redirect


【解决方案1】:

正如@Jani Hartikainen 在他的评论中指出的那样,真的没有必要对下划线进行 URL 编码。尝试使用文字下划线重定向,看看是否可行,因为我相信重定向会自己进行一些 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'
    );
  }
  [...]

models/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);
     }
     [...]

/models/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;
    }
    [...]
}

【讨论】:

  • 我同意:该代码确实需要重构。这是丑陋和难以管理的。数据应从 application.ini 移至 db 表。您建议的代码非常令人印象深刻,但对于这样一个简单的应用程序来说可能有点矫枉过正:) 感谢您付出所有努力!
【解决方案2】:

默认情况下,这将发送 HTTP 302 重定向。由于正在写入标头,因此如果将任何输出写入 HTTP 输出,程序将停止发送标头。尝试查看Firebug 中的请求和响应。

在其他情况下,请尝试对 _redirect() 方法使用非默认选项。例如,您可以尝试:


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

_redirect() 方法还有另一个有趣的选项,code 选项,您可以发送例如 HTTP 301 Moved Permanently代码。


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

【讨论】:

  • 感谢丹尼尔的建议。我试过了,但错误仍然存​​在。不过,我感谢您的帮助。
【解决方案3】:

我想我可能已经找到了答案。看起来 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"/>';

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-09-13
    • 2012-03-14
    • 1970-01-01
    • 2014-11-13
    • 1970-01-01
    • 1970-01-01
    • 2016-08-27
    • 1970-01-01
    相关资源
    最近更新 更多