-
Notifications
You must be signed in to change notification settings - Fork 0
Module Guide
Pi module development.
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
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.
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.
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 thewww
folder when installs, and it will be namedmodule-{module name}
inwww/asset
folder. -
config
- used to store configuration files of the module, there must have amodule.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
andtemplate/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 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
.
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.
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');
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:
-
There should add an
options
field inattributes
array if you want to create a group ofradio
orcheckbox
as well asselect
. -
If you use
formElement()
orformRow()
other than methodsFormCheckbox
to outputcheckbox
andradio
form in template, you should move thetype
field out ofattributes
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:
- Displaying forms as well as
label
, for example:echo $this->formRow($form);
- Displaying more particularily, for example:
- Displaying a
text
:echo $this->formInput($form);
- Displaying a
select
:echo $this->formSelect($form);
- 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.
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>
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));
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 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:
- Reading from action method directly.
- 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; ?>
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)