Skip to content
gwisdomroof edited this page Oct 18, 2012 · 10 revisions

内容

  • 模块介绍
  • 组件
  • 模块结构
  • 模块配置
  • 控制器
  • 模板
  • 区块
  • 数据库
  • 插件
  • 模块-ajax
  • 模块分页
  • 模块服务API

介绍

XoopsEngine系统是由大量的模块所组成的。模块指的是可重复使用的功能块,利用它可构建更复杂的应用程序。在XoopsEngine系统中,模块也采用了MVC结构,它包含有控制器和模板,因此,前端程序员与后端程序员可以分别专注于自己的任务。在XoopsEngine系统中,由于模块有两个重要特性:“模块组合”和“多实例”,因此,您应该在安装后使用它。

模块组合

我们知道,Web应用程序可以被分成若干具体功能部分。以一个新闻网站为例,它可以划分为用户管理、新闻文章管理和用户评论管理等。它们实现了完整的功能,而且可以在其他应用中被重用。因此我们可以把它们作为模块,换句话说,我们可以发现一个新闻网站是由几个模块如用户模块,文章模块和用户评论模块构成。这个特性对于应用程序开发是非常重要的,它将帮助减少开发周期、提高效率。

多实例

一个XoopsEngine模块可以被多次使用来实现特殊功能,这些意味着在XoopsEngine应用程序中用户可以不止一次的安装某个模块。

模块的主要组成部分

XoopsEngine module 使用多个组件来处理页面信息,例如控制器(controller),驱动操作(action)和部分处理器(section)。

controller

Controller是MVC 中的C,他它负责做出合理的需求分析以及产生恰当的输出。XoopsEngine 在路由后会决定哪个控制器将来为请求服务。

Action

Action是随着控制器一起,它是控制器类中实际的方法。

Section

在XoopsEngine的定义中,一个section包含有四种不同功用的部分。这四个部分是前端(front)、管理(admin)、供给(feed)和限制块(block)。

Front

front用于显示前端页面。

Admin

admin是用来显示管理端页面,用户应该登录管理区域来访问它。

Feed

Block

block部分定义了模块的组成块,这些块可以被用于其他应用程序利用以实现其功能。

模块的文件夹结构

模块文件夹是一个独立的包,存放在usr/module文件夹下。以XoopsEngine的demo模块为例,它的文件夹列表如下:

usr
    module
    demo
        asset
            image
                js
                css
        config
        sql
        src
            Controller
                Front                       
                    Admin
            Form
        template
                front
                admin
  • asset - 用于存储静态文件,如JS,CSS和image ,这些文件将被用于显示页面。asset文件夹在安装时将被发布到www文件夹下,它会被命名为module-{模块名称},存放在www/asset文件夹下。
  • config - 用于存储模块的配置文件,每个模块都必须有一个module.php文件来说明模块的基本信息,并决定使用哪个配置文件。
  • sql - 包括用于创建表的SQL文件。
  • src/Controller/Front - 包括前端section的多个Controller文件。
  • src/Controller/Admin -包括管理section的多个Controller文件。
  • src/Form - 如果页面没有表单元素,那么这个文件夹可以忽略。文件夹中的文件将被用于创建、筛选和验证表单。
  • template/fronttemplate/admin - 包含用来显示HTML标签的.phtml文件。 注意:在src文件夹中的文件夹名的首字母必须大写。

配置文件

配置文件允许用户定义模块导航、路由规则和模块的基本信息等。config文件夹中必须有一个module.php文件。这里我们将介绍如何创建module.php文件。首先在配置文件夹创建一个module.php文件中,然后添加以下代码:

module/demo/config/module.php

return array(
    'meta'  => array(
        'title'         => 'DEMO Sandbox',
        'description'   => 'Examples and tests for developers.',
        'version'       => '1.0.0',
        'license'       => 'New BSD',
        'logo'          => 'image/logo.png',
        'readme'        => 'docs/readme.txt',
        'demo'          => 'http://demo.xoopsengine.org/demo'
    ),
    'author'    => array(
        'name'      => 'Taiwen Jiang',
        'email'     => '[email protected]',
        'website'   => 'http://www.xoopsengine.org',
        'credits'   => 'Zend Framework Team; Xoops Engine Team; EEFOCUS Team.'
    ),
    'dependency'    => array(
    ),
    'maintenance'   => array(      
        'resource' => array(
            'database'  => array(
                'sqlfile'   => 'sql/mysql.sql',         
                'schema'    => array(
                    'test'          => 'table',
                    'page'          => 'table',
                )
            ),
            'config'    => 'config.php',
            'block'     => 'block.php',
            'bootstrap' => 1,
            'event'     => 'event.php',
            'search'    => array('callback' => array('search', 'index')),
            'page'      => 'page.php',
            'acl'       => 'acl.php',
            'navigation'    => 'navigation.php',
            'route'     => 'route.php',
            'monitor'   => array('callback' => array('monitor', 'index')),
            'test'      => array(
                'config'    => 'For test'
            )
        )
    )
);

该数组包含三个部分:模块基本信息,作者信息和需要的配置文件。 模块基本信息是由以下部分组成: 必须部分:元数组、标题字段、版本信息和许可信息 可选部分:字段描述、图标、帮助文档和演示。 作者信息是由author数组描述,其中包括姓名、电子邮件、网站和认证信息。在这些字段中,名字字段是必需的,其它的都是可选的。 配置信息主要由maintenance 数组描述,它包含一个resource数组。在这个数组,每个配置文件的名字被分配给一个特殊字段。例如,如果您想添加一个定义模块导航的配置文件,您可以添加一个字段如'navgation'= >'navigation.php'。在resource数组中还有一个database数组,它用来定义如何创建数据库文件。database数组中包含sqlfile和schema两个字段。sqlfile字段描述了SQL schema的名字或数据。schema字段描述了在卸载时如何删除表。 注意:schema字段是可选的;在这个字段,健名是表名而值应该是表。

模块控制器(Module controller )

如前所述,我们对控制器有了总体的概念。在这一节中,我们将介绍如何创建一个控制器文件。一个控制器实际上就是一个类,所以首先你应该定义它的命名空间。

namespace Module\Demo\Controller\Front; 

命名空间将会帮助你避免相同类名的冲突。当然,你应该包括你想使用的类所在的命名空间,比如:

use Xoops\Mvc\Controller\ActionController;

控制器是一个继承自Xoops\Mvc\Controller\ActionController的类,它有一个标准的名字,{控制器名称}Controller,控制器名称的第一个字母必须大写。 在控制器类中,有一些Action,每个Action对应一个用户请求。action方法必须是公开的,以便它被其他类访问。Action名称格式如{Action名称}Action,Action名称的第一个字母必须是小写。 下面是一个控制器文件示例:

module/demo/src/Controller/Front/IndexController.php

namespace Module\Demo\Controller\Front;

use Xoops\Mvc\Controller\ActionController;
use Xoops;

class IndexController extends ActionController
{    
    public function indexAction()
    {   
        // Assign multiple params
        $data = array(
            'data'      => 'Xoops-Zend',
            'module'    => $this->params('module'),
            'title'     => __('Demo page'),
        );
        $this->view()->assign($data);

        // Assign all route params
        $this->view()->assign('params', $this->params()->fromRoute());

        // Assign one single param
        $this->view()->assign('TheParam', 'A specific parameter');

        // Specify page head title
        $this->view()->headTitle()->prepend('Demo page');
        // Specify meta parameter
        $this->view()->headMeta()->prependName('generator', 'DEMO');

        // Specify template, otherwise template will be set up as {controller}-{action}
        $this->view()->setTemplate('demo-index');
    }

    ...
} 

注意: 当创建模块时,我们建议您创建一个·IndexController·和·IndexAction·,因为如果在URL里没有设定Controller和Action时,它将路由到IndexController的IndexAction。 下面是一个控制器文件范例:

模块模板(Module template)

模块模板在XoopsEngine中实际上是一个phtml文件。该文件主要包含HTML页面显示元素。使用一个模板,您应该首先在控制器文件中设置模板。

$this->view()->setTemplate('blank');

如果你把这段代码放在front文件夹的控制器类里,在·template/front·中的·blank.phtml·文件将用于显示这个Action对应的页面。 pthml文件还允许使用PHP脚本。例如:

module/demo/template/front/demo-index.phtml

<h2><?php echo $title; ?></h2>

<div><?php echo 'data: ' . $data; ?></div>
<div><?php echo 'module: ' . $module; ?></div>
<div><?php echo 'The Param: ' . $TheParam; ?></div>

您会发现这段代码中有一个名为·$title·的变量没有定义。实际上它是在控制器的action方法中给它赋值的。

$this->view()->assign('title', 'Xoops-Zend');

模块表单(Module forms)

在XoopsEngine中,有一些操作form的额外的文件,例如初始化form的文件、验证form的文件。因此,我们应该创建一些类来实现它们。

初始化表单

通常,在Zend\Form\Form中的 ·add()·方法是用于为创建表单添加属性,因此我们可以创建一个继承自·Zend\Form\Form·的表单类,然后在·init()·函数中调用·add()·方法。 如果我们想创建一个登录表单:

namespace Module\Login\Form;

use Xoops;
use Xoops\Form\Form as BaseForm;
use Zend\Form\Form;
use Zend\Form\Element;

class LoginForm extends BaseForm
{
    public function init()
    {
        // Adding a text form
        $this->add(array(
            'name'          => 'username',
            'attributes'    => array(
                'type'  => 'text',               
            ),
            'options' => array(
                'label' => __('Username'),
            ),
        ));

        // Adding a password form
        $this->add(array(
            'name'          => 'password',
            'attributes'    => array(
                'type'  => 'password',                
            ),
            'options' => array(
                'label' => __('Password'),
            ),
        ));       

        // Adding a submit form
        $this->add(array(
            'name'          => 'submit',
            'attributes'    => array(
                'type'  => 'submit',
                'value' => 'Login',
            )
        ));
    }
}

type字段的值可以更改,用来创建不同的表单:

// Adding a radio form
$this->add(array(
    'name'          => 'gender',
    'attributes'    => array(
        'type'    => 'radio',
        'value'   => 'male',
        'options' => array(
            'male'   => __('Male'),
            'female' => __('Female'),
        ),
    ),
    'options'       => array(
        'label' => __('Gender'),
    ),
));

// Adding a file form
$this->add(array(
    'name'          => 'upload',
    'attributes'    => array(
        'type'  => 'file',              
    ),
    'options'       => array(
        'label' => __('Upload'),
    ),
));

// Adding a select form
$this->add(array(
    'name'         => 'country',
    'attributes'   => array(
        'type'    => 'select',               
        'options' => array(
            'CHN'   => __('China'),
            'USA'   => __('United States'),
       ),
    ),
    'options'      => array(
        'label' => 'Your country',
    ),
));               

// Adding a textarea form
$this->add(array(
    'name'          => 'message',
    'attributes'    => array(
        'type'  => 'textarea',
        'cols'  => '50',
        'rows'  => '10',               
    ),
    'options'       => array(
        'label' => __('Your details'),
    ),
));

// Adding a caotcha 
$this->add(array(
    'name'          => 'captcha',
    'type'          => 'captcha',
));

注意: 1.如果你想创建一个radio组、checkbox组或者select组,你应该在attributes数组中添加一个option字段。 2.在模板中,如果你使用formElement()或formRow()而不是FormCheckbox()来输出checkbox,您应该从属性数组中移除type字段。

例如:

$this->add(array(
    'name'         => 'feedback',
    'attributes'   => array(
        'value' => '0',
    ),
    'options'       => array(
        'label' => __('Do you want to recieve our email?'),
    ),
    'type'  => 'checkbox', 
));

创建表单实例

我们已经初始化了form属性,如果要显示表单,你应该在控制器中实例化它。可以在控制器中添加以下代码:

use Module\Login\Form\LoginForm;
...

public function indexAction()
{
    $form = new loginForm('login');
    $form->setAttribute('action', $this->url('', array('action' => 'process')));
    ...
}

setAttribute()方法用来设置action的url,您可以使用url()的插件来生成一个url。

显示表单

如果你创建了一个表单实例并将它分配给一个变量,假设变量名为form,您可以使用这个变量来显示表单,主要有三种方法来显示表单:

1.像label一样的显示,例如:echo $this->formRow($form); 2.更加特定的显示,例如: . 显示textecho $this->formInput($form); . 显示selectecho $this->formSelect($form); 3.一般显示,例如:echo $this->formElement($form);

例如:

<?php echo $this->form()->openTag($form); ?>

<!-- Displaying form as well as label -->
<div id='username'>
<?php $element = $form->get('username'); ?>      
    <div><?php
        echo $this->formRow($element); 
        echo $this->formElementErrors($element);
    ?></div>
</div>

<!-- Displaying more particularily -->
<div id='username'>
<?php $element = $form->get('username'); ?>
    <div><?php echo $this->formLabel($element); ?></div>
    <div><?php
        echo $this->formInput($element); 
        echo $this->formElementErrors($element);
    ?></div>
</div>

<!-- Displaying generally -->
<div id='submit'>
<?php $element = $form->get('submit'); ?>
    <div><?php 
        echo $this->formElement($element); 
        echo $this->formElementErrors($element);
    ?></div>
</div>

<?php echo $this->form()->closeTag(); ?>

注意:如果使用formRow()方法,您不需要再调用formLabel()来输出标签。

添加编辑器

XoopsEngine为编辑长文本提供了几种类型的编辑器,编辑器的使用同他表单元素同,你只要修改·type·的值,并添加一些属性:

$this->add(array(
    'name'          => 'editor',
    'attributes'    => array(
        'type'  => 'editor',
    ),
    'options'       => array(
        'label'  => __('Editor'),
        'set'    => '',
        'editor' => 'html',
   ),
));

在数组中,·type·字段的值指定为·editor·,这将有助于增加一个编辑器;·set·字段和·editor·字段是一组属性,它们的值和功能如以下列表:

Type $editor $set Description
html html '' HTML syntax is allowed
compound markitup 'html' Compound block
markdown markitup 'markdown' Markdown syntax is allowed
default textarea '' Only plain text is allowed

初始化表单实例后,您可以在模板中使用·formElement()·来显示编辑器。

创建表单过滤器和验证器

这部分将介绍如何创建一个表单过滤器和验证器,它与创建一个表单有相同的操作,您首先应该初始化过滤器和验证器的属性,然后在控制器中添加验证代码。 例如,初始化一个过滤器和验证器代码如下:

$this->add(array(
    'name'          => 'username',
    'required'      => true,
    'filters'       => array(
        array(
            'name'         => 'StringTrim',
        ),
    ),
    'validators'    => array(
        array(
            'name'         => 'Regex',
            'options'      => array(
                'pattern'       => '/^[a-zA-Z0-9][a-zA-Z0-9-_]{0,24}$/',
            ), 
        ),
        // Adding another validator 
        new StringLength(array(
            'min'          => '4',
            'max'          => '25',
        )),
    ),
));

在这段代码中,·required·字段说明该表单是否需要一个输入数据。·filters·数组中的·StringTrim·表明表单数据将会被trim。·validators·数组中的·Regex·字段允许您根据正则表达式来规范输入。如果你想要添加另一个验证器,您可以实例化一个对象,比如·new StringLength·,这个对象通过字段·min·和·max·来限制输入长度。

注意:你也可以通过这种方式添加自己验证器,但你首先应该实现验证器的代码。

现在你可以实例化过滤器(filter)对象,并在Controller中添加验证代码:

$post = $this->request->getPost();
$form = new LoginForm('login');
    
$form->setData($post);
$form->setInputFilter(new LoginFilter);
if(!$form->isValid()) {
     // do something     
}
$values = $form->getData();

·getPost()·方法通过·POST·方法获取表单数据。这个·setData()·方法为过滤和验证设置post数据。这里我们首先应该实例化过滤器对象,然后使用·isValid()·方法来检查是否输入数据是有效的。·getData()·方法将返回过滤后的数据。

模块区块(Module blocks)

XoopsEngine模块为应用程序提供了区块(block),这些区块是控制器中action的实际接口。

配置区块(Configuring blocks)

为了创建一个区块,我们应该在·config·文件夹添加一个block.php文件,并且在·module.php·文件中添加配置信息。 假如我们想添加两个区块命名为·block-a·和·details·:

module/demo/config/block.php

return array(
    // block-a block
    'block-a'    => array(
        'title'         => __('First Block'),
        'description'   => __('Block with options and tempalte'),
        'render'        => array('block', 'blocka'),
        'template'      => 'block-a',
    ),

    // block-b block
    'block-b'  => array(
        'title'         => __('Second Block'),
        'description'   => __('Block with custom options and tempalte'),
        'render'        => array('block', 'blockb'),
        'template'      => 'block-b',
    ),
);

然后你应该在module.php文件中添加·block·字段到·resource·数组中:

'block'  => 'block.php',

用户也可以添加配置数据来配置区块,当模块安装时,配置信息会存储在数据库,如果需要用户可以改变配置数据。为了允许用户配置区块,唯一要做的就是在·block·数组中添加一个·config·字段:

'block-a'   => array(
    ...
    'config'        => array(
        // text option
        'first' => array(
            'title'         => 'Your input',
            'description'   => 'The first option for first block',
            'edit'          => 'text',
            'filter'        => 'string',
            'value'         => __('Demo option 1'),
        ),
    ),
),

在·config·数组中,·edit·字段通过输入数据定义了表单类型,·filter·字段定义了filter的类型。

创建区块

我们已经配置了区块,这个模块有两个区块,现在创建一个区块文件来实现其功能。 您应该创建一个·block.php·文件,其中包含一个block类,并存放在·src· 文件夹下。

namespace Module\Demo;

class Block
{
    public static function blocka($options, $module = null)
    {
        $block = array(
            'caption'   => __('Block A'),
            'content'   => sprintf('Called by %s through %s', $module, __METHOD__),
            'options'   => $options,
        );
        return $block;
    }

    public static function blockb($options, $module = null)
    {
        $block = array(
            'caption'   => __('Block B'),
            'content'   => sprintf('Called by %s through %s', $module, __METHOD__),
            'options'   => $options,
        );
        return $block;
    }
}

在代码中,·option·参数包含用户存放在数据库中的数据,·module·参数是当前的模块。

创建模板

在配置部分中,我们已经为·block-a·和·block-b·设置模板,现在需要在·template\block·文件夹下创建一个·block-a.phtml·和·block-b. phtml·:

module/login/template/block/block-a.phtml

<h2><?php echo $block['caption']; ?></h2>
<p><?php echo $block['content']; ?></p>
<hr />
<h3><?php _e('The options: '); ?></h3>
<?php foreach($block['options'] as $key => $value) { ?>
<div><span><?php echo $key; ?></span><span><?php echo $value; ?></span></div>
<?php } ?>

module/demo/template/block/block-b.phtml

<h2><?php echo $block['caption']; ?></h2>
<p><?php echo $block['content']; ?></p>
<hr />
<h3><?php _e('The options: '); ?></h3>
<?php foreach($block['options'] as $key => $value) { ?>
<div><span><?php echo $key; ?></span><span><?php echo $value; ?></span></div>
<?php } ?>

变量存储在$block数组中,该数组是由系统提供,你不需要定义它。

显示区块

block的展示代码通常在theme文件夹下的phtml文件里实现,XoopsEngine提供帮助函数·widget()·用来实现区块。

<div style="float: right;">
    <?php echo $this->widget('login-details', array('cache_ttl' => 9999)); ?>
</div>

<div style="float: left;">
    <?php echo $this->widget('login-login', array('cache_ttl' => 9999)); ?>
</div>

模块数据库

在操作数据库之前,我们首先应该创建一个数据库或一个表。在前面的小节中,我们已经介绍了配置中的sql file,XoopsEngine会自动搜索该文件并执行其代码来创建表。所以我们唯一需要做的就是在·sql·文件夹下创建一个·.sql·文件,并且添加代码来创建表及其字段:

module/demo/sql/mysql.sql

CREATE TABLE `{test}` (
    `id`      int(10) unsigned        NOT NULL auto_increment,
    `message` varchar(255)            NOT NULL default '',
    `active`  tinyint(1)              NOT NULL default '1',

    PRIMARY KEY  (`id`)
);

注意:所有的表名必须用‘{’和‘}’括起来,所有的系统表名必须由·core·开头。 这些生成的代码会在模块安装时自动执行,在安装后的数据库中可以看到一个名为·{prefix}{module name}{table name}·的表。现在我们可以通过实际的编码来操作这些表。 XoopsEngine为操作安装后的数据库表封装了一个类,API在Xoops.php中,所以你需要引用它的命名空间:

use Xoops;

获取表实例

Xoops类提供了我们一个命名为model的方法来获取一个表实例,但是这种方法只能操作XoopsEngine的数据库。该方法接受两个参数,第一个是表的名称,第二个是模块的名称(可以忽略)。这种方法最终返回一个·Xoops\Application\ModelAbstract·实例。

$model = Xoops::model('user');
$model = Xoops::model('login/user');
$model = Xoops::model('user', 'login');

假设表的前缀是·xe·,当前的module是·login·,因此,第一行将返回一个实例,这个实例与表·xe_core_user·关联。·xe_core_user·表是一个系统表。第二行和第三行会返回相同的结果,操作的是·xe_login_user· 表。 操作表的其他方法是·getModel()·方法,但是这种方法不能操作系统创建的表。例如,如果您想操作表·xe_login_user·表,使用下面的代码:

$model = $this->getModel('user'); 

注意:我们建议你使用·getModel()·来获取当前模块表,因为安装多次时,模块名称将会改变。

查询(Select)

XoopsEngine提供我们一个·select()·方法来从表获取数据,该方法继承自Zend的·select()·方法。

$select = $model->select();
$rowset = $model->selectWith($select);

$select = $model->select()->where(array('username' => 'root'));
$rowset = $model->selectWith($select);

// Alternative
$rowset = $model->select(array('username' => 'root'));

$rowset = $model->select(array('username' => 'root')); 在代码中,·select()·方法用于从表里选择数据。该函数的参数是由数组描述的查询条件。 第一个block将返回表的所有数据,第二和第三个block有同样的作用,它会返回·username· 等于 ·root·的多行数据,下面是一个·where·的例子:

// 'username' != 'root'
$rowset = $model->select(array('username != ?' => 'root'));
$rowset = $model->select(array('username <> ?' => 'root'));
// 'age' > '23'
$rowset = $model->select(array('age > ?' => '23'));
// 'age' <= '45'
$rowset = $model->select(array('age <= ?' => '23'));

使用SQL中的 IN:

$ids = array('1', '2', '4', '7');
$rowset = $model->select(array('id' => $ids));

这个代码会选择id等于·$ids·数组中任意元素的行。

使用 ·order·, ·limit·:

$select = $model->select()->where(array('username' => 'root'))
                          ->order(array('username ASC'));
$rowset = $model->selectWith($select);

$select = $model->select()->where(array('username' => 'root'))
                          ->offset(1)
                          ->limit(20);
$rowset = $model->selectWith($select);

使用group:

$select = $model->select()->group(array('name', 'id'));
$select = $model->select()->group('name');

查询列:

$select = $model->select()->where(array('username' => 'root'))
                        ->columns(array('username', 'age', 'email'));
$rowset = $model->selectWith($select);

select时去掉重复的数据:

$select = $model->select()->where()->columns(array('username' => new \Zend\Db\Sql\Expression('distinct username')));
$rowset = $model->selectWith($select);

这个方法只能移除单一的字段,如果你添加另一个没有重复值的字段,比如·id·,这个方法会返回所有行的·username·和·id·字段。

例如,如下这个表:

id username gender age
1 root male 23
2 root female 45

如果用如下的代码来查询数据:

 $select = $model->select()
                 ->where()
                 ->columns(array('username' => new \Zend\Db\Sql\Expression('distinct username'), 'id', 'gender'));
 $rowset = $model->selectWith($select);

它会返回:

id username gender
1 root male
2 root female

你会看到重复的用户名·root·,向下面这样使用·group()·可以移除重复的数据:

$select = $model->select()
                ->where()
                ->columns(array('*'))
                ->group('username');
$rowset = $model->selectWith($select);

从多个表中Select

Zend 提供一个 ·join()· 方法来简单的join连接其它表.

$select = $select->join(array('abbreviation table name' => 'table full name'), 'where string');

在XoopsEngine中,我们使用 ·$model->select()· 来调用方法.

$model = $this->getModel('table1');
$table1 = $model->getTable();
$table2 = $this->getModel('table2')->getTable();

$select = $model->select()->join(array('table2' => $table2), 'table2.element = ' . $table1 . '.element');
$rowset = $model->selectWith($select);

$data = array();
$data = $rowset->toArray();

·join()· 方法的第三个参数是将要联合查询的表的列, 如果用 ·$select()· 来select列,就会从原始的表中select数据.

$model = $this->getModel('userid');
$userid = $model->getTable();
$userinfo = $this->getModel('userinfo')->getTable();
    
$select = $model->select()->join(array('info' => $userinfo), 'info.username = ' . $userid . '.username', array('email'));
$select->columns(array('id'));
$rowset = $model->selectWith($select);  

这些代码同下面的SQL语句等效:

'SELECT userid.id AS id, userinfo.email AS email FROM userid INNER JOIN userinfo AS info ON info.username = userid.username'

插入

我们现在有了Model实例, 它可以被用来插入、更新、删除数据,接下来的代码实现插入数据。

$row = $this->getModel('userinfo')->createRow($data);
$row->save();
if (!$row->id) {
    return false;
}

在代码中, createRow() 方法的 $data 参数是包含要插入数据的数组,数组的键名就是表名:

$data = array(
    'name'      => 'John',
    'password'  => $password,
);

然后调用 save() 方法来插入数据,最终用 $row->id 来确认数据插入正确。

更新

save() 方法也允许用户更新表数据,但是在调用 save() 方法前需要做一些事情,比如取到你要更新的数据的id和取到对应行的实例。

假如你要在 userinfo表里创建 id, usernamepassword 字段,要依据username 字段来修改密码。

// fetching id from table by username
$model = $this->getModel('userinfo');
$rowset = $model->select(array('username' => 'root'));
foreach ($rowset as $row) {
    $id = $row['id'];
}
        
// updating password
$row = $model->find($id);
$row->password = $password;
$row->save();

当然,你可以简单的使用 update() 来更新数据。

$model->update(array('password' => $password), array('username' => 'root'));

删除

在XoopsEngine中, delete() 用来删除数据, 这个方法也需要你调用 find() 方法.

$row = $this->getModel('userinfo')->find($id);
$row->delete();

你也可以用Zend提供的 delete() 方法:

$this->getModel('userinfo')->delete(array('id' => $id));

控制器插件(Controller plugin)

ACL

ACL 是 访问控制列表(Access Control List)的缩写, 他定义了一些角色,并给他们不同的权限来访问资源,XoopsEngine也采用了这种方法来管理用户。acl插件用来获取当前模块的ACL。

该插件没有参数,应该在 {Controller name}Controller.php 中,像这样使用:

$this->acl();

返回值是包含列表信息的 Xoops\Acl\Acl 实例.

配置

config 插件用来从应用程序的config表格里读取配置信息,如果你设置了模块信息,那么推荐用这个方法来读取它们 。

该插件仅接收一个参数:配置数据的名字。

$this->config('sitename');

params

params 插件帮追获取当前的module,controller和action等的信息,或者是通过GET方法传递过来的参数。它接受两个参数,第一个是描述要获取信息的字符串,它可以是module, controller, action 或参数名,第二个参数是可选的,如果按照第一个参数无法找到信息,它会被用作返回值。

例如,如果在login模块、控制器index、行为index中添加如下代码

echo $this->params('module');
echo $this->params('default', 'default');

输出为:

'login'
'default'

假如你通过如下的查询字符串来传递参数: domain/url/login/login/param-default, 然后你可以用如下代码来取 default:

$this->params('param');

如果url是: domain/url/login/login/param/default, 你应该使用如下 API:

$this->params()->fromRoute('param'); 如果url是: domain/url/login/login?param=default, 代码则换成:

$this->params()->fromQuery('param');

如果你是用POST传递数据,就可以使用 fromPost() 方法:

$this->params()->fromPost('param');

重定向

redirect 插件用来基于路由产生URL,这个插件不是单独使用的,应该调用 toRoute() 方法来帮助它生成URL, toRoute() 方法接受3个参数:路由名、参数、选项。 路由名描述了如何生成URL,默认值是 default,参数是包含module、controller和action信息的数组,如果 modulecontroller 都设置为null,它会使用当前模块,当前控制器, Options 参数被用在URL生成中,可以被省略。

$this->redirect()->toRoute('', array(
    'module'     => 'login',
    'controller' => 'index', 
    'action'     => 'index',
));

url

XoopsEngine采取Module-Controller-Action的模型,你应该在URL中设置module、controller和action来路由到正确的页面, url 插件提供从现有参数生成URL的方法。

url 插件接受4个参数,第一个是路由名,它允许你选择路由类型,如果参数是‘’,路由名会被设置为 default ;第二个参数是包含module、controller和action名称的数组,如果没有给出模块名,就会使用当前模块名;第三个参数是路由选项参数,第四个参数是一个布尔值,用来决定是否重用匹配的参数。

$this->url('', array(   
    'module'     => 'system',
    'controller' => 'index',
    'action'     => 'index',
));

$this->url('home');

$this->url('default', array(
    'controller'  => 'index',
    'action'      => 'index',
));

用GET方法来传递用户定义的数据:

$this->url('default', array(
    'controller'  => 'index',
    'action'      => 'index',
    'param'       => 'default',
));

视图

一般情况下,view 插件不独立使用,它通常调用assign()setTemplate() 来为phtml赋值或者设置phtml模板。

assign() --接受两个参数,第一个可以使数组或者字符串,第二个是要赋给它的值,如果是数组,那它就为phtml定义了变量和值。

$this->view()->assign('form', $form);
$this->view()->assign(array(  
    'content'    => 'Hello, world!',
    'form'       => $form,
)); 

·setTemplate()· -- 这个方法用来为当前行为设置模板,它接受一个参数:模板名。如果设置为false,就会使用系统的默认模板。

$this->view()->setTemplate(false);
$this->view()->setTemplate('blank');

Ajax

Ajax用来在不重新加载页面的情况下请求一个页面,在XoopsEngine中,允许用如下两种方式使用Ajax:

1.直接从Action中读取. 2.从模板文件取数据.

第一个方法很简单,只需要创建一个Action,然后在Action中返回数据:

public function ajaxAction()
{
    ...

    return $requestData;
}

第二种方法更常见一些, 需要请求整个模板的数据,所以应该为Action创建一个模板,然后在模板中输出数据:

// in action
public function ajaxAction()
{
    ...

   $this->view()->setTemplate('ajax');
   return $this->view(array('requestData' => $requestData));
   // This code can also be used
   $this->view()->assign(array('requestData' => $requestData));
}

// in ajax.phtml template
<?php echo $requestData; ?>

模块API服务

模块虽然是独立的功能包,但也有可能从其它模块取数据来完成自身的功能。例如, ·article·模块可能在 ·tag· 模块中添加tag, ·tag· 模块也可能返回tag给·article· 模块。 XoopsEngine 为模块从其它模块取数据提供了API. XoopsEngine 把所有的方法封装在类 ·Xoops\Application\Service\Api· 中,这个类只提供了调用目标模块中API类的接口。

我们可以这样使用API:

Xoops::service('api')->demo('method', $args);
Xoops::service('api')->demo->method($args);

这两行代码有同样的作用,他们会调用 ·demo· 模块中 ·src/Api/Api· 类的 ·method· 方法。 ·$args·参数是调用·method·方法的参数.

注意: 以上列出的用法只能在·Api· 类中调用模块.

如果用户想要调用·src/Api· 目录下的其他类, 推荐下面的用法:

Xoops::service('api')->demo(array('check', 'method'), $args);

这段代码会调用 ·src/Api· 目录中 ·check· 类的 ·method· 方法。

这个类只提供了调用模块API的接口,所以用户如果让其它模块访问,就需要现准备API类,下面的代码演示了如何创建一个允许外部访问的API类:

module/demo/src/Api/Api.php

namespace Module\Demo\Api;

use Xoops\Application\AbstractApi;

class Api extends AbstractApi
{
    protected $module = 'demo';

    public function test($args)
    {
        $result = sprintf('Method provider %s - %s: %s', $this->module, __METHOD__, json_encode($args));
        return $result;
    }
}