Skip to content
linzongshu edited this page Mar 4, 2013 · 23 revisions

简体中文 | فارسی

Pi module development.

Pi Module Guide

Contents

  • Introduction
  • Main components of module
  • Module folders structure
  • Configuration file
  • Module controller
  • Module template
  • Module forms
  • Module blocks
  • Module database
  • Controller plugin
  • Ajax
  • Module service api

Introduction

A Pi system is made up of plenty of modules. A module is a re-usable piece of functionality that can be used to construct a more complex application. Modules in Pi also adopt MVC structure which contains controllers and templates, therefore, programmers of front end and back end can focus on their own tasks, respectively. In Pi, modules should be installed first if you want to take it into use, because of its two important features: module combination and multiple instances.

Module combination

As we know, a Web application can be divided into several parts with special function. Take a news Web site for example, it could be resolved into user management, news article management and user comments management, etc. These parts has complete function and can be re-used in other application. Hence we can take them as modules, in other word, we can find that a news Web site is consist of several modules such as user module, article module and user comment module. This feature is very important for application development, it will help reducing the develop cycle and improving efficiency.

Multiple instances

A Pi module could be used many times to realize special function, these means users can install a module more than once in the Pi application.

Main components of module

Pi module use several components to deal with a page's information, such as controller, action and section.

Controller

Controller is the C in MVC, it is responsible for making sense of the request and producing the appropriate output. Pi will determine which controller to use for a request after routing.

Action

Action is along with controller, it is a actual method in controller class.

Section

Pi defines a section which have four parts of different usages. The four parts in section is front, admin, feed and block.

  • Front

The front part is used to display pages of front end.

  • Admin

The admin part is used to display pages of admin end, users should login admin area to access it.

  • Feed

The feed part is used to operate RSS.

  • Block

The block part define blocks of module, these blocks can be used by other application to implement its function.

Module folders structure

A module folder is a independent package and is kept in usr/module folder. Take the demo module in Pi for example, its folders are list as follows:

usr
    module
    demo
        asset
            image
                js
                css
        config
        sql
        src
            Controller
                Front                       
                    Admin
            Form
        template
                front
                admin
  • asset - used to store static files such as js, css and image, these files will be used for displaying pages. The asset folder will be publish to the www folder when installs, and it will be named module-{module name} in www/asset folder.
  • config - used to store configuration files of the module, there must have a module.php in it to represent basic information of module, and which configuration file to use.
  • sql - includes sql file that is used to create tables.
  • src/Controller/Front - includes controller files of front section.
  • src/Controller/Admin - includes controller files of admin section.
  • src/Form - can be ignored if you do not have form element in your page. The file included in this folder are used to create, filter and validate form.
  • template/front and template/admin - includes .phtml files that are used to display HTML tags.

Note: the first letter of folder name in src folder must be uppercase.

Configuration file

Configuration files allow user to define module navigation, route rules and basic information of the module, etc. And a module.php file is needed in config folder. Here we will introduce how to create module.php file. Create a module.php file under config folder, and add following codes:

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.Pi.org/demo'
    ),
    'author'    => array(
        'name'      => 'Taiwen Jiang',
        'email'     => '[email protected]',
        'website'   => 'http://www.Pi.org',
        'credits'   => 'Zend Framework Team; Pi 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'
            )
        )
    )
);

This array includes three parts: basic module information, author information and configuration file needed.

Basic module information is described by meta array, fields of title, version and license are required, and fields of description, logo, readme and demo are optional.

Author information is described by author array which includes fields of name, email, website and credits. Among these fields, name field is required, and the others are optional.

The configuration information is mainly described by maintenance array which contains a resource array. In this array, each configure file name is assign to a special field, for example,if you want to add a configuration file to define the navigation of module, you can add a field such as 'navigation' => 'navigation.php'. Files used to create database are defined in database array in resource array. The database array include sqlfile and schema two fields. The sqlfile field describes the file name of SQL schema or data and schema field describes tables to remove during uninstall.

Note: schema field is optional; in this field, name of key is table name, and value should be table.

Module controller

As mentioned previous, we have a summary concept of controller. In this section we will introduce how to create a controller file. A controller is a class actual, so you should define its namespace first.

namespace Module\Demo\Controller\Front;

The namespace will help you to avoid conflict of classes with same name. Certainly, you should include the namespace of the class you want to use such as:

use Pi\Mvc\Controller\ActionController;

A controller is a class inherits from Pi\Mvc\Controller\ActionController, it has a standard name, which is {controller name}Controller, and the first letter of controller name must be uppercase.

In a controller class, there are several actions, each action corresponding to a user request. The action method must be public so it can be access by other classes. Action name a format such as {action name}Action, but the first letter of action name should be lowercase.

Here is an example of controller file:

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

namespace Module\Demo\Controller\Front;

use Pi\Mvc\Controller\ActionController;
use Pi;

class IndexController extends ActionController
{    
    public function indexAction()
    {	
        // Assign multiple params
        $data = array(
            'data'      => 'Pi-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');
    }

    ...
}

Note: we recommend you to create a IndexController and a IndexAction when create module, because there will route to index action of index controller if you do not set controller and action in your URL.

Module template

A module template is actual a phtml file in Pi. This file mainly contains HTML elements for displaying pages. To use a template, you should set the template in controller file first.

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

If you put this code in controller class of front folder, a template named blank.phtml in template/front folder will be used to display page for the action.

The pthml file also allows to use PHP scripts. For example:

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>

You may find that there is a variable named $title in this code without define. Actural we have assign value to it in controller action method.

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

Module forms

In Pi, there are extra files to operate forms, such as file to initialize form, file to validate form. Therefore, we should create some classes to implement them.

Initializing forms

Generally, the add() method in Zend\Form\Form is used to add attributes for creating a form, so we could create a form class inherits from Zend\Form\Form, then call the add() method in init() function.

Supposing we want to create a login form:

namespace Module\Login\Form;

use Pi;
use Pi\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',
            )
        ));
    }
}

The value of type field can be changed to create different forms:

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

// 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',
));

Note:

  1. There should add an options field in attributes array if you want to create a group of radio or checkbox as well as select.

  2. If you use formElement() or formRow() other than methods FormCheckbox to output checkbox and radio form in template, you should move the type field out of attributes array.

For exmple:

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

Creating Form instance

We now have initialized the form attribute, if you want to display a form, you should instantiate it in controller. You can add the following codes in you controller:

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

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

The setAttribute() method helps to set the action url, you can use url() plugin to generate a url.

Displaying Forms

If you have create a form instance and assign it to a variable, suppose it is form, you can use this variable to display forms, there are mainly three methods to display forms:

  1. Displaying forms as well as label, for example: echo $this->formRow($form);
  2. Displaying more particularily, for example:
  • Displaying a text: echo $this->formInput($form);
  • Displaying a select: echo $this->formSelect($form);
  1. Displaying generally, for example: echo $this->formElement($form);

The code are:

<?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(); ?>

Note: if formRow() method is used, you do not need to call formLabel() to output label.

Adding editor

Pi provides several types of editor for you to edit long text, the usage of editor is the same as other form elements, you should only change the type value, and add some attributes:

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

In the array, the type field is assigned with a value editor, this helps add an editor; the set field and the editor is a group of attributes, their value and function are list as:

Type $editor $set Description
html html '' HTML syntax is allowed
compound markitup 'html' Compound block, HTML and following syntx allowed: %block.name.title%, %block.name.content%, %block.name.link%, %block.name.class%
markdown markitup 'markdown' Markdown syntax is allowed
default textarea '' Only plain text is allowed

After initilized the form instance, you can use formElement() to display the editor in template.

Creating form filter and validator

This part we will introduce how to create a form filter and validator, it has the same operation as creating a form, you should intialize the attributes of filter and validator first, and then add the validation code in controller.

For example, initializing a filter and validator:

$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',
        )),
    ),
));

In this code, the required field tells that whether the form needs an input data. The StringTrim in filters array tells that the form data will be trimmed. The Regex field in validators array allows you to standardize the input according to regular expression. If you want add another validator, you can instantiate an object, such as new StringLength, this object will restrict the input length by fields min and max.

Note: you can also add yourselves validators by this way, but you should implement the codes of validator first.

Now you can instantiate the filter object and add the validation code in controller:

$post = $this->request->getPost();
$form = new LoginForm('login');

$form->setData($post);
$form->setInputFilter(new LoginFilter);
if(!$form->isValid()) {
    // do something     
}
$values = $form->getData();

The getPost() method gets the form data by POST method. The setData() method sets the post data for filtering and validating. Here we should instantiate the filter object first and then use the isValid() method to check whether the input data are valid. The getData() method will return the filtered data.

Module blocks

Pi module provides blocks for application to use, these blocks are actual interfaces to actions in controllers.

Configuring blocks

In order to create a block, we should add a block.php file in config folder and add the configure message in the module.php file.

Supposing we want to add two blocks named block-a and 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',
    ),
);

Then you should add block field to resource array in module.php:

'block'  => 'block.php',

It also allows users to add configuration data for configure blocks, this configuration data will be stored in application's database when module installs, users can change the configuration data if need. To allow users to configure blocks, the only thing you need to do is add a config field in block array:

'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'),
        ),
    ),
),

In the config array, the edit defines the form type for inputing data, and filter defines the filter type.

Creating blocks

Since we have configured the blocks, and we have two block for the module, now it time to create a block file to implement their function.

You should create a Block.php that contain a block class in src folder.

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;
    }
}

In the code, the options parameter contains the data users set into the database, and the module parameter is the current module.

Creating template

In the configuration section, we have set the templates of block-a and block-b to block-a and block-b, now it is necessary to create block-a.phtml and block-b.phtml in template\block folder:

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 } ?>

Variables here are stored in $block array, this array is provided by system, you do not need to define it.

Displaying block

The blocks' displaying codes are generally implement in phtml file of theme folder, Pi's helper widget() is used to realize it.

<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>

Module database

Before operates a database, we should create a database or a table first. In the previous section, we have introduced the configuration of sql file, Pi will automatically search this file and executes its code to create tables for us. So the only thing we need to do is create a .sql file in the sql folder and add codes to create table and its fields:

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`)
);

Note: all table names here must be quoted with '{' and '}', and all system tables must be prefixed with core.

These creation codes will be executed automatically when the module installs. You can find a table named {prefix}_{module name}_{table name} in the installed database. Now we can operate the table by coding the action method.

Pi have encapsulated a class for user to operate tables of the installed database. And the API is in Pi.php file, so you should include its namespace:

use Pi;

Getting table instance

The Pi class provides us a method named model to fetch a table instance, but this method can only operate database of Pi. This method takes two parameters, the first one is the name of table, and the second is the name of module which can be ignored. This method finally return a Pi\Application\Model\ModelAbstract instance.

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

Supposing the prefix of table is xe, and current module is login, hence, the first line will return an instance which relates to table xe_core_user. The xe_core_user table is a system table. The second line and third line will return same result, and its table operated is xe_login_user.

The other method to operate table is getModel(), but this method can not operate tables create by system. For example, if you want to operate table xe_login_user, using the follow code:

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

Note: we recommend you to use getModel() to fetch current module tables when codes, because the installed module name will change when the module is installed multi-times.

Select

Pi provides us a select() method to fetch data from table, this method inherits from select() method of Zend.

$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'));

In the code, select() method is used to select data from table. The parameter of it is the condition, which represent by array.

The first block will return all data of table, the second and third block has the same effect, which will return rows that username equal to root. Here is some example of writing where array:

// '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'));

Using SQL IN:

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

This code will select the id equal to anyone in the $ids array.

Using 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);

Using group:

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

Selecting columns:

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

Removing the repeat data when selects:

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

This method only can remove single field, if you add another field such as id and it does not have repeat value, this method will return all rows of field username and id.

For example, there is a table such as:

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

If you use the following code to select data:

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

It will return:

id username gender
1 root male
2 root female

You may find there has repeat username root, if you want to remove the repeat data, using group() method as follows:

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

Select from multi-table

Zend provides us a method call join() to join another table to compact.

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

In Pi, we can use $model->select() object to call the method.

$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();

The third parameter of join() method is the columns of the joined table to select, if you use $select() to select columns, it will select the elements of original table.

$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);  

The SQL statement of this code will be as same as:

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

Insert

Now we have a model instance, it can be used to call methods for inserting, updating and deleting data. The following codes will insert data into table.

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

In the codes, $data parameter of createRow() method is an array which contain data to insert, the key of the array is same as that of table:

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

Then a save() method is called to insert data into table, and finally use $row->id to assure the data is insert correctly.

Update

The save() method also allow user to update data of tables. But something should be done before using save() method. Such as fetching the id of the data you want to update and getting instance of the rowset.

Supposing you create fields id, username and password in your table userinfo, you want to change the password according to username field.

// 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();

Certainly you can also use a simple method update() to update data.

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

Delete

In Pi, delete() method is used to delete data, this method also need you to call find() method.

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

You can also use delete() method provide by Zend:

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

Controller plugin

acl

ACL is the abbreviation of Access Control List, it defines several roles and give them different authority to access resources. Pi also adopts this method to manage users. The acl plugin is used to fetch access controller list of current module.

This plugin takes no parameter, and it should be used in {Controller name}Controller.php file like this:

$this->acl();

The return value is a Pi\Acl\Acl instance contain list information.

config

The config plugin is used to read configuration data from config table of application, if you set the configuration data for your module, this plugin is recommended to fetch the value.

This plugin takes only one parameter, and it indicates the name of the configuration data.

$this->config('sitename');

params

The params plugin helps you to get current module, controller and action information or parameters post by GET method. This plugin takes two parameters, the first parameter is a string describes the information want to fetch, it can be module, controller, action or parameter name, and the second parameter is optional, it will be set as return value if there is no value searched according to first parameter.

For example, if you adding following code in module login, controller index and action index such as:

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

Output:

'login'
'default'

Supposing you post data by query string like this: domain/url/login/login/param-default, then you can use the following code to fetch the value default:

$this->params('param');

If the url is: domain/url/login/login/param/default, you should use the following API:

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

If the url is: domain/url/login/login/?param=default, the code should be replaced as:

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

If you post parameters by POST method, you can use fromPost() method:

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

redirect

The redirect plugin is used to generate a URL base on a route. This plugin do not use independently, you should call a toRoute() method in it to help to generate the URL. The toRoute() method takes three parameters which is route name, params and options.

Route name describes how to generate a URL, its default value is default, params is an array contains module, controller and action information, if the module and controller field are set to null, it will use current module and controller. Options parameter is used in URL generation, it can be ignored.

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

url

Pi adopts a Module-Controller-Action model, you should set module name, controller name and action name in url to route to right page. The url plugin provides the function to generate a URL by given parameters.

The url plugin takes four parameters, the first is route name, it allows you to choose your route style, it will set to default if you set it to ''; the second parameter is an array which contain module name, controller name and action name, if you do not give the module name, current module will be used; the third parameter is an option parameter for route and the fourth parameter is a Boolean which decided whether to reuse matched parameters.

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

$this->url('home');

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

Posting a user-defined parameter by GET method:

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

view

Generally, the view plugin do not use independently, it often call assign() or setTemplate() to assign value to phtml and set a phtml template.

assign() -- this function takes two parameters, the first on can be array or string, if it is string, the second parameter must be the value assign to it, if it is array, it define the variable and its value for phtml file.

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

setTemplate() -- this function is used to set template for current action, it takes only one parameter, which is a string contain template name. If you set the parameter to false, a default template will be provided by system.

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

Ajax

Ajax is used to request a page without reload the page. In Pi, it allow you to use Ajax to request a page by two ways:

  1. Reading from action method directly.
  2. Fetching data from template file.

The first method is a bit simple, it only needs to create an action, and you can return the data in the action method:

public function ajaxAction()
{
    ...

    return $requestData;
}

The second method is more commonly, it request the whole template data, so you should create a template for action, and output the data in the template:

// 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; ?> 

Module Service API

Although a module is a independent function package, it may fetch data from other module to implement its function. For example, an article module may add tags into a tag module, the tag module may also return tags to article module. Pi provides users a service API for module to fetch data from other modules. Pi encapsulates all the methods in the Pi\Application\Service\Api class, this class only provides a interface for users to call the methods in the API class of target module.

We can use this API like this:

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

This two line code has the same effect, they will call the method method in the src/Api/Api class of the demo module. The $args parameter is the parameter of the method method.

Note: the usage list above can only call the method in the Api class.

If users want to call the other classes in the src/Api directory, the following usage is recommended:

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

This code will call the method method of the check class in the src/Api directory.

This class only provides the interface to call a module's APIs, so users should create APIs first for other module to access. The following code is an example on how to create an API class for accessing from outside:

module/demo/src/Api/Api.php

namespace Module\Demo\Api;

use Pi\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;
    }
}
  • [Configuration files of Module](configuration files of module)
  • [Xoops APIs](xoops apis)
  • [Paginator Guide](paginator guide)