Seagull PHP框架学习教程之模块生成器

如果你是一个熟练的PHP程序员,你完全可以跳过前面两节你已经非常熟悉的基本概念,直接try一下Seagull的module generator(模块生成器),当你安装完Seagull之后,你可以使用你在安装时设定的管理员账户登陆。当你成功登陆后会直接进入admin
GUI,选择单击左侧导航栏的“Module generator”即可进入Seagull的模块生成器,截屏如下:



事实上,Seagull框架下开发项目,你也就是程序员所需要做的工作仅仅是为Seagull开发一个个模块。而使用模块生成器,你可以很容易的生成一个Seagull模块所需要的文件目录结构,也就是上一节所提到的Seagull下一个模块所包含的那些文件。

我们看一下上面截屏中的各个选项:
“Module Name”  为所要创建的模块指定一个名称
“Manager Name” 指定一个名称来创建一个manager类
“Add following methods” 为这上面创建的manager类创建哪些method,选择你想要在这个manager 类中使用的方法
“Create CRUD Action” 如果上面所创建的manger类的各个action(也就是manager类的method)是对数据库的某个表进行操作时可以选择,这样Seagull会执行SGL_Task_CreateDataObjectEntities类,重新生成数据库所有表的DataObject类。
“Create Templates”  选中以创建默认的模板
“Create languages files” 是否要创建语言文件
“Create ini file” 是否要创建模块配置文件

注意事项:
当选中“Create CRUD Action”复选框时,如果数据库中没有和manager类名一样的表格时,Seagull会抛出如下错误:
Please generate a table (with the same name as your manager entity, eg, "pizza") in the database first.

如果Seagull是运行在linux类服务器上,还有可能出现权限不够的错误。由于module generator会在seagull的modules目录下生成模块所需要的一系列相关文件,所以web服务器(也就是运行web服务器的用户)需要对该目录拥有写的权限。否则seagull会抛出下列错误:
Please give the webserver write permissions to the modules directory

如果你所创建的模块已经存在,那么module generator将只会在指定的模块内创建一个指定的manager类,但是如果该模块内已经存在同名的managaer类,则Seagull会抛出如下错误:
Manager already exists - please choose another manager name

我用module generator创建了一个book模块,下面是module generator生成的book模块的文件目录截屏:
Seagull PHP框架学习教程之模块生成器_第1张图片

其中BookMgr.php就是我们所创建的这个book模块目前唯一的manager类:
  1. <?php
  2. /* Reminder: always indent with 4 spaces (no tabs). */
  3. // +---------------------------------------------------------------------------+
  4. // | Copyright (c) 2008, Demian Turner                                         |
  5. // | All rights reserved.                                                      |
  6. // |                                                                           |
  7. // | Redistribution and use in source and binary forms, with or without        |
  8. // | modification, are permitted provided that the following conditions        |
  9. // | are met:                                                                  |
  10. // |                                                                           |
  11. // | o Redistributions of source code must retain the above copyright          |
  12. // |   notice, this list of conditions and the following disclaimer.           |
  13. // | o Redistributions in binary form must reproduce the above copyright       |
  14. // |   notice, this list of conditions and the following disclaimer in the     |
  15. // |   documentation and/or other materials provided with the distribution.    |
  16. // | o The names of the authors may not be used to endorse or promote          |
  17. // |   products derived from this software without specific prior written      |
  18. // |   permission.                                                             |
  19. // |                                                                           |
  20. // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS       |
  21. // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT         |
  22. // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR     |
  23. // | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT      |
  24. // | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,     |
  25. // | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT          |
  26. // | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,     |
  27. // | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY     |
  28. // | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT       |
  29. // | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE     |
  30. // | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.      |
  31. // |                                                                           |
  32. // +---------------------------------------------------------------------------+
  33. // | Seagull 0.6                                                               |
  34. // +---------------------------------------------------------------------------+
  35. // | bookMgr.php                                                    |
  36. // +---------------------------------------------------------------------------+
  37. // | Author: George Zheng <[email protected]>                                  |
  38. // +---------------------------------------------------------------------------+
  39. // $Id: ManagerTemplate.html,v 1.2 2005/04/17 02:15:02 demian Exp $

  40. require_once 'DB/DataObject.php';
  41. /**
  42.  * Type your class description here ...
  43.  *
  44.  * @package book
  45.  * @author  George Zheng <[email protected]>
  46.  */
  47. class BookMgr extends SGL_Manager
  48. {
  49.     function BookMgr()
  50.     {
  51.         SGL::logMessage(null, PEAR_LOG_DEBUG);
  52.         parent::SGL_Manager();

  53.         $this->pageTitle    = 'Book Manager';
  54.         $this->template     = 'bookList.html';

  55.         $this->_aActionsMapping =  array(
  56.             'add'       => array('add'),
  57.             'insert'    => array('insert''redirectToDefault'),
  58.             'edit'      => array('edit'), 
  59.             'update'    => array('update''redirectToDefault'),
  60.             'list'      => array('list'),
  61.             'delete'    => array('delete''redirectToDefault'),
  62.         );
  63.     }

  64.     function validate($req, &$input)
  65.     {
  66.         SGL::logMessage(null, PEAR_LOG_DEBUG);
  67.         $this->validated    = true;
  68.         $input->error       = array();
  69.         $input->pageTitle   = $this->pageTitle;
  70.         $input->masterTemplate = $this->masterTemplate;
  71.         $input->template    = $this->template;
  72.         $input->action      = ($req->get('action')) ? $req->get('action') : 'list';
  73.         $input->aDelete     = $req->get('frmDelete');
  74.         $input->submitted   = $req->get('submitted');
  75.         $input->book = (object)$req->get('book');
  76.         $input->bookId = $req->get('frmBookID');

  77.         //  if errors have occured
  78.         if (isset($aErrors) && count($aErrors)) {
  79.             SGL::raiseMsg('Please fill in the indicated fields');
  80.             $input->error = $aErrors;
  81.             $this->validated = false;
  82.         }
  83.     }

  84.     function display(&$output)
  85.     {
  86.         if ($this->conf['BookMgr']['showUntranslated'] == false) {
  87.             $c = &SGL_Config::singleton();
  88.             $c->set('debug'array('showUntranslated' => false));
  89.         }
  90.     }


  91.     function _cmd_add(&$input, &$output)
  92.     {
  93.         SGL::logMessage(null, PEAR_LOG_DEBUG);
  94.         $output->template  = 'bookEdit.html';
  95.         $output->pageTitle = 'BookMgr :: Add';
  96.         $output->action    = 'insert';
  97.         $output->wysiwyg   = true;   
  98.     }

  99.     function _cmd_insert(&$input, &$output)
  100.     {
  101.         SGL::logMessage(null, PEAR_LOG_DEBUG);
  102.         $book = DB_DataObject::factory($this->conf['table']['book']);
  103.         $book->setFrom($input->book);
  104.         $book->book_id = $this->dbh->nextId($this->conf['table']['book']);
  105.         $success = $book->insert();

  106.         if ($success !== false) {
  107.             SGL::raiseMsg('book insert successfull', false, SGL_MESSAGE_INFO);
  108.         } else {
  109.             SGL::raiseError('book insert NOT successfull',
  110.                 SGL_ERROR_NOAFFECTEDROWS);
  111.         }
  112.     }

  113.     function _cmd_edit(&$input, &$output)
  114.     {
  115.         SGL::logMessage(null, PEAR_LOG_DEBUG);
  116.         $output->template  = 'bookEdit.html';
  117.         $output->pageTitle = 'BookMgr :: Edit';
  118.         $output->action    = 'update';
  119.         $output->wysiwyg   = true;

  120.         $book = DB_DataObject::factory($this->conf['table']['book']);
  121.         $book->get($input->bookId);
  122.         $output->book = $book;   
  123.     }

  124.     function _cmd_update(&$input, &$output)
  125.     {
  126.         SGL::logMessage(null, PEAR_LOG_DEBUG);
  127.         $book = DB_DataObject::factory($this->conf['table']['book']);
  128.         $book->book_id = $input->bookId;
  129.         $book->find(true);
  130.         $book->setFrom($input->book);
  131.         $success = $book->update();

  132.         if ($success !== false) {
  133.             SGL::raiseMsg('book update successfull', false, SGL_MESSAGE_INFO);
  134.         } else {
  135.             SGL::raiseError('book update NOT successfull',
  136.                 SGL_ERROR_NOAFFECTEDROWS);
  137.         }   
  138.     }

  139.     function _cmd_list(&$input, &$output)
  140.     {
  141.         SGL::logMessage(null, PEAR_LOG_DEBUG);
  142.         $output->template  = 'bookList.html';
  143.         $output->pageTitle = 'BookMgr :: List';

  144.         //  only execute if CRUD option selected
  145.         if (false) {
  146.             $query = "  SELECT
  147.                              0, 1
  148.                         FROM {$this->conf['table']['book']}
  149.                         ";

  150.             $limit = $_SESSION['aPrefs']['resPerPage'];
  151.             $pagerOptions = array(
  152.                 'mode'      => 'Sliding',
  153.                 'delta'     => 3,
  154.                 'perPage'   => $limit,
  155.             );
  156.             $aPagedData = SGL_DB::getPagedData($this->dbh, $query$pagerOptions);
  157.             if (PEAR::isError($aPagedData)) {
  158.                 return false;
  159.             }
  160.             $output->aPagedData = $aPagedData;
  161.             $output->totalItems = $aPagedData['totalItems'];

  162.             if (is_array($aPagedData['data']) && count($aPagedData['data'])) {
  163.                 $output->pager = ($aPagedData['totalItems'] <= $limit) ? false : true;
  164.             }
  165.         }
  166.     }

  167.     function _cmd_delete(&$input, &$output)
  168.     {
  169.         SGL::logMessage(null, PEAR_LOG_DEBUG);
  170.         if (is_array($input->aDelete)) {
  171.             foreach ($input->aDelete as $index => $bookId) {
  172.                 $book = DB_DataObject::factory($this->conf['table']['book']);
  173.                 $book->get($bookId);
  174.                 $book->delete();
  175.                 unset($book);
  176.             }
  177.             SGL::raiseMsg('book delete successfull', false, SGL_MESSAGE_INFO);
  178.         } else {
  179.             SGL::raiseError('book delete NOT successfull ' .
  180.                 __CLASS__ . '::' . __FUNCTION__, SGL_ERROR_INVALIDARGS);
  181.         }   
  182.     }
  183. }
  184. ?>
需要注意的是,manager类从文件名到class名的规范,即有点类似于java中一个文件中至少有一个类,而且文件名就是以类名为文件名。同时从上面的代码你也可以看到action,也就是manager的action method。使用了Seagull框架后,程序员不需要做太多的工作,所有的工作只需要在各个相应的action内实现特定的业务逻辑。

细心的程序员可能会发现,在几乎所有的manager类中都包含有validate(),display()方法。事实上,默认的情况下,Seagull框架中的manager类采用validate,process,display流程。也就是说进入Seagull框架的所有数据都要经过下列这些方法的处理:

validate:未经处理的$_REQUEST数据以一个SGL_Request实例被传递给这个方法,进行数据验证(主要是服务端的数据验证,当然也可以做一些客户端可以执行的数据验证,不过建议不要将客户端能做的数据验证放在这里),最后通过验证的数据会被映射到$input对象(其实是一个SGL_Registry实例)。你可以查看一下上面代码中的validate方法进一步加深认识。

process:如果所有来自客户端的数据被验证有效, $input对象会被做为参数传递经该manager类的某个action method,也就是来自客户端所请求的action进行处理。$input对象的数据被操作加工完后会被映射到$output对象(SGL_Output类的实例)。如果验证结果是无效,那么将跳过action而直接将数据传递给display,并反馈错误信息给用户。

display:该方法主要目的是提供一个进行后期数据加工处理的途径,而且一般是做大部分action都会涉及到的数据加工,也就是说如果你有几个action有共同的任务需要做,你可以考虑放在这里而避免代码重复。

    从上面的这个bookMgr可以看出,使用了Seagull框架以后,程序员的主要工作是创建manager类,并实现其中相应的validate,display和相关的action method。下一篇我会整体介绍一下Seagull框架已经为我们提供的工具类,也就是我们可以直接使用的API,包括发送邮件,图像上传及处理,缓存等一系列经常使用的功能。当你掌握了这些API之后,你的开发时间将大大的减少,这是我们选择Seagull的原因之一。

你可能感兴趣的:(Seagull PHP框架学习教程之模块生成器)