symfony 中轻松 Ajax

概述

symfony 的 Ajax 助手令程序界面美化成为小菜一碟。 本教程将向你一步步展示如何在片刻间创建一个 Ajax 支持的 symfony 应用。

介绍

如果懒得不能忍受阅读苦楚的家伙们,建议你们观看完全展示如下内容的 在线视频

电子商务应用程序中向购物车添加物品并不完全符合“添加到购物车”的提法,因为这个过程需要点击 “添加到购物车” 按钮,浏览一个新的页面(购物车),然后返回商店或者结账。

Ajax 启用拖放(drag-and-drop)交互、给与即时的视觉反馈而不需要离开商店,令程序通过更接近购物车的提法。

该教程的目标程序是开发 symfony 版本的Rails上由script.aculo.us发布的购物车演示。prototype javascript 架构(framework)(已捆绑在 symfony 内)和一些 script.aculo.us javascript 是 javascript 助手的核心。

建立应用

首先建立一个 sfdemo 项目,一个 app 应用和一个 cart 模块:

$ cd /home/steve
$ mkdir sfdemo
$ cd sfdemo
$ symfony init-project sfdemo
$ symfony init-app app
$ symfony init-module app cart

配置网站服务另这个新应用得以被访问(如网站服务器安装所述,使用虚拟主机或者别名)这里假设模块可以通过 localhost 来访问:

http://localhost/cart/

在向你道恭喜(Congratulations)。

你的 app 应用必须可以访问 symfony javascript 类库。 如果你的 app 不能工作,从浏览器检查是否可以访问类库(比如测试 http://localhost/sf/js/prototype.js)。如果不能访问,你可以用 3 种不同的方法解决这个问题:

  • 别名(Alias) 配置 Apache:

    Alias /sf /$data_dir/symfony/web/sf
    
  • web 目录建立 sf 链接(symbolic link):

    $ cd /home/steve/sfdemo/web
    $ ln -sf /$data_dir/symfony/web/sf sf
    
  • 将 javascript 文件拷贝到 web/js 目录:

    $ cd /home/steve/sfdemo/web
    $ mkdir -p sf/js
    $ cp /$data_dir/symfony/web/sf/js/*.js sf/js/
    

主页面

首先,你需要建立一个代购物品列表。 为了简化这个之,该列表可以通过 cart 动作类的 getProducts() 方法访问。 购物车是 sfUser 对象的一个具有属性 参数容器(parameter holder) 的参数。 将 sfdemo/app/modules/cart/actions/actions.class.php 改为:

[php]
class cartActions extends sfActions
{
  public function executeIndex()
  {
    $this->getUser()->setAttribute('cart', array());
    $this->products = $this->getProducts();
  }

  private function getProducts()
  {
    return array('iPod black', 'iMac', 'iMac RC', 'iPod');
  }
}

cart 模块的主业面将包含一个物品列表,和一个接受拖放的区域。 这个区域便是购物车。 打开 sfdemo/app/modules/cart/templates/indexSuccess.php 模板并写入:

[php]
<h1>symfony Apple store demo</h1>

<div id="shopping_cart">

  <h2>Products:</h2>

  <div id="product_list">
    <?php foreach($products as $id => $title): ?>
      <?php echo image_tag('product'.$id, array(
        'id'    => 'product_'.$id,
        'class' => 'products'
      )) ?>
    <?php endforeach ?>
  </div>

  <h2>Cart:</h2>

  <div id="cart" class="cart">
  </div>

</div>

你可以看到产品以图片形式显示。 使用 这个压缩文件中的图片,将它们放在 sfdemo/web/images/ 目录中, 另外,部分样式已经帮你设置好, 所以建议你将 这个样式表 放在 sfdemo/web/css/ 目录中并在 sfdemo/app/modules/cart/config/ 目录中添加 view.yml 文件,写入如下内容:

all:
  stylesheets:  [cart]

现在访问下面的地址查看购物车准备设置:

http://localhost/cart/

聚焦购物车

购物车中的内容将随你的物品拖放动作而改变。 这意味着模板中 cart 内容必须在独立文件中。使用 include_partial() 助手来实现之。 购物车中的物品将被储存在样式为 float:left 的一个个div中,因此在该容器之后需要一个空白的 div。这就需要我们对 indexSuccess.php 模板作如下修改:

[php]
  <h2>Cart:</h2>

  <div id="cart" class="cart">
    <div id="items">
      <?php include_partial('cart') ?>
    </div>
    <div style="clear:both"></div>
  </div>

</div>

include_partial() 助手将在 sfdemo/app/modules/cart/templates/ 目录中查找并引用 _cart.php 文件。 以如下内容创建这个文件:

[php]
<?php foreach($sf_user->getAttribute('cart') as $product_id => $quantity): ?>
<div>
  <?php for($i = 1; $i <= $quantity; $i++): ?>
    <?php echo image_tag('product'.$product_id, array(
      'class' => 'cart-items',
      'id'    => 'item_'.$product_id.'_'.$i,
      'style' => 'position:relative'
    )) ?>
  <?php endfor ?>
  (<?php echo $quantity ?> <?php echo $products[$product_id] ?>)
</div>
<?php endforeach ?>

<?php if (!$sf_user->getAttribute('cart')): ?>
  nothing yet in your shopping cart.
<?php endif ?> 

如果购物车中有物品,则将以图片形式出现,有多少个出现多少次,其数量显示在每种产品之后。

现在重新查看购物车:

http://localhost/cart/

好了,没有太多的变化,仍旧空空荡荡...... 是添加 Ajax 的时候了。

添加 javascript 行为

编辑 indexSuccess.php 模板,引入 javascript 助手:

[php]
<?php use_helper('Javascript') ?>

添加对 draggable_element javascript 助手的调用,另图片可以被拖拽:

[php]
<?php foreach($products as $id => $title): ?>
  <?php echo image_tag('product'.$id, array(
    'id'    => 'product_'.$id,
    'class' => 'products'
  )) ?>
  <?php echo draggable_element('product_'.$id, array('revert' => true)) ?>
<?php endforeach ?>

这为产品列表中的每个图片添加了 '可拖拽(draggable)' 行为。其中 revert(返回) 选项使图片在被拖拽释放时回到原来的位置(除非被其它元素接收)。

现在,将 cart 定义为接收元素。 你只需要确定模板中那个部分在事件发生执行需要更新,需要调用那个动作来提供更新内容,以及那个类型的可拖拽元素可以被接收。使用drop_receiving_elements javascript 助手实现之:

[php]
<?php echo drop_receiving_element('cart', array(
  'update'     => 'items',
  'url'        => 'cart/add',
  'accept'     => 'products',
)) ?>

现在再试一下,将物品移动到购物车:可以了。 当一个可拖拽物品被拖动至接收元素,一个 XMLHTTPRequest 被发送至 add 动作,其结果被显示在 items div 中。问题是 cart 模块的 add动作还没有被定义。

定义更新动作

sfdemo/app/modules/cart/actions/actions.class.php 中添加 add 动作:

[php]
public function executeAdd()
{
  $tmp = split('_', $this->getRequestParameter('id', ''));
  $product_id = $tmp[1];

  $cart = $this->getUser()->getAttribute('cart');
  if (!isset($cart[$product_id]))
  {
    $cart[$product_id] = 1;
  }
  else
  {
    ++$cart[$product_id];
  }
  $this->getUser()->setAttribute('cart', $cart);
  $this->products = $this->getProducts();      
}

该动作接收 javascript 传递来的参数(被拖放物品的 id)并将其添加至购物车。

add 的结果将显示在仅仅是引用 _cart.phpaddSuccess.php 模板,但此次需要传递 products 参数:

[php]
<?php include_partial('cart', array('products' => $products)) ?>

该模板不能使用全局布局(global layout),因此编辑 sfdemo/app/modules/cart/config/ 目录中的 view.yml 文件,写入:

addSuccess:
  has_layout:   off

all:
  has_layout:   on
  stylesheets:  [cart]

试一下:你现在可以将物品添加到购物车了。

聚焦可用性

你现在可以止步了,但是这个购物车还有个大问题:在购物车被更新过程中,界面上没有变化,用户可能会感到茫然。 这是请求不同步的一个普遍问题:需要添加一个指示(indicator)区域,用以标示请求正在处理。 另外,也没有告知用户什么时候物品被购物车接收到,因此还需要设置 cart div 的 hover 样式。

做到这一点需要编辑 indexSuccess.php 模板并写入:

[php]
<div style="height:20px">
  <p id="indicator" style="display:none">
    <?php echo image_tag('indicator.gif') ?> updating cart...
  </p>
</div>

将 'indicator.gif' 图片文件 存放在 sfdemo/web/images/ 目录。

现在修改 drop_receiving_element() javascript 助手的调用代码,在请求过程中显示指示器并声明 hover 样式:

[php]
<?php echo drop_receiving_element('cart', array(
  'update'     => 'items',
  'url'        => 'cart/add',
  'accept'     => 'products',
  'script'     => 'true',
  'hoverclass' => 'cart-active',
  'loading'    => "Element.show('indicator')",
  'complete'   => "Element.hide('indicator')"
)) ?>

结语

该演示的全部代码可以从这里下载 并且可以在线访问。 你将注意到些许的不同(增加了一个回收箱) 但和谐内容没有变化。

javascript 助手的文档完善之前,你可以从 script.aculo.us documentation获得更多信息。

  • Bookmark at
  • Bookmark "tutorial:symfony_ajax:start" at del.icio.us
  • Bookmark "tutorial:symfony_ajax:start" at Digg
  • Bookmark "tutorial:symfony_ajax:start" at Furl
  • Bookmark "tutorial:symfony_ajax:start" at Reddit
  • Bookmark "tutorial:symfony_ajax:start" at Ask
  • Bookmark "tutorial:symfony_ajax:start" at BlinkList
  • Bookmark "tutorial:symfony_ajax:start" at blogmarks
  • Bookmark "tutorial:symfony_ajax:start" at Blogg-Buzz
  • Bookmark "tutorial:symfony_ajax:start" at Google
  • Bookmark "tutorial:symfony_ajax:start" at Ma.gnolia
  • Bookmark "tutorial:symfony_ajax:start" at Netscape
  • Bookmark "tutorial:symfony_ajax:start" at ppnow
  • Bookmark "tutorial:symfony_ajax:start" at Rojo
  • Bookmark "tutorial:symfony_ajax:start" at Shadows
  • Bookmark "tutorial:symfony_ajax:start" at Simpy
  • Bookmark "tutorial:symfony_ajax:start" at Socializer
  • Bookmark "tutorial:symfony_ajax:start" at Spurl
  • Bookmark "tutorial:symfony_ajax:start" at StumbleUpon
  • Bookmark "tutorial:symfony_ajax:start" at Tailrank
  • Bookmark "tutorial:symfony_ajax:start" at Technorati
  • Bookmark "tutorial:symfony_ajax:start" at Live Bookmarks
  • Bookmark "tutorial:symfony_ajax:start" at Wists
  • Bookmark "tutorial:symfony_ajax:start" at Yahoo! Myweb
  • Bookmark "tutorial:symfony_ajax:start" at BobrDobr
  • Bookmark "tutorial:symfony_ajax:start" at Memori
  • Bookmark "tutorial:symfony_ajax:start" at Faves
  • Bookmark "tutorial:symfony_ajax:start" at Favorites
  • Bookmark "tutorial:symfony_ajax:start" at Facebook
  • Bookmark "tutorial:symfony_ajax:start" at Newsvine
  • Bookmark "tutorial:symfony_ajax:start" at Yahoo! Bookmarks
  • Bookmark "tutorial:symfony_ajax:start" at Twitter
  • Bookmark "tutorial:symfony_ajax:start" at myAOL
  • Bookmark "tutorial:symfony_ajax:start" at Slashdot
  • Bookmark "tutorial:symfony_ajax:start" at Fark
  • Bookmark "tutorial:symfony_ajax:start" at RawSugar
  • Bookmark "tutorial:symfony_ajax:start" at LinkaGoGo
  • Bookmark "tutorial:symfony_ajax:start" at Mister Wong
  • Bookmark "tutorial:symfony_ajax:start" at Wink
  • Bookmark "tutorial:symfony_ajax:start" at BackFlip
  • Bookmark "tutorial:symfony_ajax:start" at Diigo
  • Bookmark "tutorial:symfony_ajax:start" at Segnalo
  • Bookmark "tutorial:symfony_ajax:start" at Netvouz
  • Bookmark "tutorial:symfony_ajax:start" at DropJack
  • Bookmark "tutorial:symfony_ajax:start" at Feed Me Links
  • Bookmark "tutorial:symfony_ajax:start" at funP
  • Bookmark "tutorial:symfony_ajax:start" at HEMiDEMi
tutorial/symfony_ajax/start.txt · 最后更改: 2007/12/03 11:26 由 yujiexie
www.chimeric.de Creative Commons License Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0