MoePress Mini v1.1.3
MoePress Mini is a micro PHP MVC framework which focuses on ONE thing: Multi-level controller.
That is, each URI corresponds to a controller which is under the same path of the URI.
In simple terms:
URL | Controller | Controller Parameter |
---|---|---|
http://site.com/wiki/123 | /controller/wiki/main.php | 123 |
http://site.com/wiki/edit/123 | /controller/wiki/edit/main.php | 123 |
http://site.com/wiki/edit/cover/123 | /controller/wiki/edit/cover/main.php | 123 |
Features
- Automatic routing for multi-level controller.
- Powerful and multiple URL routing, which can match one URL multiple times.
- Only ONE core file, which means lightweight and fast.
- Unrestricted rules for Models, Views and Libraries. Write your codes by your own habits.
Requirements
- PHP 5.2+
- Rewrite module (of Apache, Nginx, or etc.)
License
MoePress Mini is is completely open source and released under the MIT license which means it is perfect for personal or commercial projects.
Tutorial
A brief tutorial will be given in this section about how to built a "Hello World" website from simple to advanced step by step.
Before starting, make sure you have installed PHP environment correctly and enabled rewrite module of Apache or Nginx.
"Hello World"
We assume that your project URL is http://localhost/
, the web directory is htdocs/
. So, for instance, when you visit http://localhost/abc.php
, the PHP file htdocs/abc.php
will be executed.
MoePress Mini has only one core file index.php
, download it, and put it to your project's web directory (in the above case, it is htdocs/
), like this:
htdocs/
└── index.php
To make your website work, you should create a controller/
directory and then write a default controller named main.php
on it:
htdocs/
├── controller/
│ └── main.php
└── index.php
The content of main.php
should be something like this:
<?php if (!defined('MOEPRESS_VERSION')) { die('Access Forbidden'); }
class Controller extends MoePress
{
public function __index()
{
echo 'Hello World';
}
}
Now open http://localhost/
, your browser should output the following line as expected:
Hello World
How it works?
All the controllers should be placed in the controller/
directory, and the file name MUST be main.php
.
By default, the main.php
in the root of controller/
will be called if no extra URI is requested. So when you opened http://localhost/
, controller/main.php
was called.
As for the controller code, see the commented version below.
<?php
// prevent main.php from being executed directly
if (!defined('MOEPRESS_VERSION')) { die('Access Forbidden'); }
// the controller class MUST be "Controller", and extend "MoePress" class
class Controller extends MoePress
{
// default method MUST be "__index()"
// arguments are allowed, like "__index($page = 1)"
public function __index()
{
// do something as you like, such as creating models or loading views
echo 'Hello World';
}
}
// "?>" is not needed in a pure PHP file
Using View
In MVC framework, HTML is written in view layer. To use views, you need to create a view/
directory, and put your view files in it, like this:
htdocs/
├── controller/
│ └── main.php
├── view/
│ └── demo_view.php
└── index.php
Here we create a view named demo_view.php
, the content may be something like this:
<html>
<body>
Hello <?php echo $name; ?>
</body>
</html>
We believe that raw PHP is the best and fastest template engine in PHP environment.
(Anyway, you can still use template engine by extending MoePress Mini.)
Next, modify the method of controller/main.php
to load the view:
function __index()
{
$this->data['name'] = 'MoePress';
$this->view('demo_view.php');
}
Here we pass a variable to the view by using $this->data
. The $this->data
is an Array
, which key is the variable's name and value is the variable's value. Hence, the view can use the variable $name
.
And, method $this->view()
is used to load this view.
Now open http://localhost/
again and you should get the following line:
Hello MoePress
Using Model & Library
Similarity with view layer, you should have model/
and library/
directory to use model and library:
htdocs/
├── controller/
│ └── main.php
├── library/
│ └── demo_library.php
├── model/
│ └── demo_model.php
├── view/
│ └── demo_view.php
└── index.php
Write a simple model demo_model.php
and a simple library demo_library.php
like this:
<?php /* demo_model.php */
class Demo_model
{
public function run()
{
echo '<div>Hello Model</div>';
}
}
<?php /* demo_library.php */
class Demo_library
{
public function run()
{
echo '<div>Hello Library</div>';
}
}
Next, modify controller/main.php
again to use them:
function __index()
{
$this->model('demo_model.php');
$model = new Demo_model();
$model->run();
$this->library('demo_library.php');
$lib = new Demo_library();
$lib->run();
}
Open http://localhost/
and it will output this two lines:
Hello Model
Hello Library
The reason why we put them separated is to make the structure of source file more logical and meet the rule of MVC framework.
Multi-level Controller
Highlights come.
2nd-level Controller
Now you're going to build a homepage for a user, the URL should look like this, where peter
, alice
and bob
are the name of certain users:
http://localhost/home/peter
http://localhost/home/alice
http://localhost/home/bob
...
Obviously the URI /home/
requests a second-level controller.
To build the homepage controller under this URL structure, you should create a new directory named home/
under controller/
directory, and create a new controller controller/home/main.php
, like this:
htdocs/
├── controller/
│ ├── home/
│ │ └── main.php
│ └── main.php
└── index.php
The method of controller controller/home/main.php
should be:
public function __index($name)
{
echo 'This is' . $name . "'s homepage.";
}
Open http://localhost/home/peter
, line This is peter's homepage.
will be showed as expected. You can change peter
in the URL to other people's name, and the output will be changed as well.
Simply create a same-named controller directory, then it works.
3rd-level Controller
Further, your users want to have an album page on their homepages. The album's URL should look like http://localhost/home/album/peter
, to enhance readability.
So it is a third-level controller. Again, create a same-named directory album/
under controller/home/
:
htdocs/
├── controller/
│ ├── home/
│ │ ├── album/
│ │ │ └── main.php
│ │ └── main.php
│ └── main.php
└── index.php
The controller content can be similar:
public function __index($name)
{
echo 'This is' . $name . "'s album.";
}
Now http://localhost/home/album/peter
outputs This is peter's album.
.
Similarly, you can create sub-level controllers by simply adding same-named controller subdirectories, like http://localhost/home/album/photo/peter
or http://localhost/home/album/photo/favor/peter
. No maximum level limitation.
Using Controller Methods
By default, method __index()
will be called when a controller is requested. However, you can write custom methods to response the requests as well.
Take the above case for example, you're going to build several subpages under the homepage, like this:
http://localhost/home/album/peter
http://localhost/home/about/peter
http://localhost/home/work/peter
...
In 3rd-level case, you need to create directories album/
, about/
and work/
under controller/home/
, then write different main.php
controllers for each directory. However, if all these controllers have similar logic, you can do all of it in one 2nd-level controller.
To do so, delete directories controller/home/album
, controller/home/about
and controller/home/work
you have just created. Then edit controller/home/main.php
to add some new methods:
public function __index($name)
{
echo 'This is ' . $name . "'s homepage.";
}
public function album($name)
{
echo 'This is ' . $name . "'s album.";
}
public function about($name)
{
echo 'About ' . $name;
}
public function work($name)
{
echo 'This is ' . $name . "'s work.";
}
Now open http://localhost/home/about/peter
, it will output the corresponding content.
Limit Controller Arguments
When user visit http://localhost/home/mark
, controller controller/home/main.php
will be called and argument 'mark'
will be passed to method __index($name)
. Without limitation, hackers can pass infinite arguments to the controller by requesting http://localhost/home/v1/v2/v3/v4/...
. The method here, however, can only receive 2 arguments, the excess arguments will be ignored, leaving some potential security threats.
To prevent this kind of threats, the controller should limit the number of arguments it may received. Using $argc
property in controller like this:
protected $argc = array(
'__index' => 0, // default method does not accept any argument
'name' => 2, // 'name' method accept 2 arguments only
'book' => array(1, 3) // 'book' method accept 1 to 3 arguments
);
public function __index()
{
// do something...
}
public function name($firstname, $lastname)
{
echo 'Your name is: ['.$firstname.' '.$lastname.']';
}
public function book($tag, $type = 'edu', $page = 1)
{
echo 'Tag: ['.$tag.'], Type: ['.$type.'], Current Page: ['.$page.']';
}
Shown as above, $argc
property is an array in which keys are the methods' name and values are the restrictions, like this: array('method' => $restriction)
. The restriction can be a number or an array. When it is a number, the number of arguments for corresponding method must be equal to it. When it is an array, the array should be array($min_num, $max_num)
, where $min_num, $max_num
are the minimum and maximum number of the arguments that the method will accept.
When the actual arguments do not meet the restriction, an exception will be threw.
Using Configuration
MoePress Mini provides a way for making configurations outside the controller class.
To make configurations, you need to create a new file config.php
:
htdocs/
├── config.php
└── index.php
The config.php
should have an array variable $_CONFIG
which contains configured information:
<?php
// $_CONFIG structure sample
$_CONFIG = array(
'debug' => true, // whether the site is under development
'base_uri' => '', // the root directory of website
'auto_load' => array(
// PHP files which should be loaded automatically before loading controller
),
'routes' => array(
// controller routing rules
)
);
config.php
file is not required by default. For some special cases, however, you have to do configuration to keep MoePress Mini running properly. See Configuration for more details.
Routing Controller
Regular expressions are used for routing controllers. The regular expressions should be written in $_CONFIG['routes']
, where the array key is the URI to be matched while the array value is the matched result used to call the target controller. Here are some examples:
$_CONFIG['routes'] = array(
// route 1
'#^homepage\/(.*)$#' => 'home/$1',
// route 2
'#^home\/([a-z0-9_\-]+)\/album#' => 'home/album/$1'
);
In route 1, when you visit http://localhost/homepage/peter
, the URL is equal to http://localhost/home/peter
.
In route 2, when you visit http://localhost/home/peter/album
, the URL is equal to http://localhost/home/album/peter
.
Note that the URI can be matched more than once. For instance, URI /homepage/peter/album
will be routed to /home/peter/album
by route 1, and then it will be routed to /home/album/peter
by route 2.
Auto Loading
MoePress Mini allows you to load some PHP files (model, library, etc.) before calling the controller, so you don't need to load commonly used models or library manually by using $this->model()
or $this->library()
in controller. The file paths should be written in array $_CONFIG['auto_load']
.
$_CONFIG['auto_load'] = array(
'model/base_model.php',
'library/lib_helper.php'
)
One of the usage of $_CONFIG['auto_load']
is to extend the default Controller
class.
For example, you want to do some actions while calling the controller, and these actions are the same in every controllers. It is not a good idea to write the same code in each controller.
The best way is that we build a auto-loaded custom base controller class by extending MoePress
class, which is the default base class for Controller
class, and then let every controller extend the custom controller class.
Here is the example. Firstly, write a base controller library/base_controller.php
:
<?php
class Base_Controller extends MoePress
{
function __construct()
{
// do something you like...
$this->data['site_title'] = 'My Site';
}
}
Then, create your normal controller which extends the base controller, like controller/main.php
:
<?php
class Controller extends Base_Controller
{
public function __index()
{
// $site_title will be passed to the view ( defined in __construct() )
$this->view('site_index.php');
}
}
To make it work, the base controller's file should be auto-loaded in config.php
:
$_CONFIG['auto_load'] = array(
'library/base_controller.php'
)
Subdirectory Installation
MoePress Mini works well when it is installed in the root directory of the website. But if you put it in a subdirectory, like http://localhost/blog/
, something may go wrong.
To run properly in a subdirectory, you need to configure the $_CONFIG['base_uri']
argument.
For example, if you want to use MoePress Mini in a subdirectory blog/
, the $_CONFIG['base_uri']
should be:
$_CONFIG['base_uri'] = 'blog';
Again, if you want to run your site in another subdirectory project/blog/
, then it should be:
$_CONFIG['base_uri'] = 'project/blog';
Documentation
It is strongly recommended to go through the Tutorial first since more usages, examples and explanations will be given in the tutorial rather then the documentation.
[class] MoePress
Class MoePress
is the base class of every controller. The controller's class name must be Controller
and it must extend MoePress
class.
See How it Works tutorial for more details about the basic usage of controller.
[property] $MP
-
Description
The instance of current controller object.
-
Type
Object, public static property
-
Usage
$controller = MoePress::$MP;
$controller->data['site_title'] = 'My Site';
[property] $config
-
Description
The configuration value in
config.php
, the value is equal to $_CONFIG.
See Advanced Configuration tutorial for more details about the configuration value. -
Type
Array, public static property
-
Usage
$config = MoePress::$config;
$base_uri = $config['base_uri'];
[property] $data
-
Description
The variables to be used in views. The key is the variable's name, and the value is the variable's value. See Using View tutorial for more details about how to pass variables to view layer.
-
Type
Array, public property
-
Usage
$this->data['site_title'] = 'My Site';
[property] $argc
-
Description
The limitation of the number of arguments for each method. The keys are the methods' name, the values are the restrictions. The restrictions can be numbers or arrays
array($min_num, $max_num)
.
See Limit Controller Arguments tutorial for more details about how to limit the arguments. -
Type
Array, protected property
-
Usage
$argc = array( '__index' => 0, 'method1' => 2, 'method2' => array(1, 3) );
[method] __index( [string $arg1 [, string $arg2 [, $...]]] )
-
Description
The default method of a controller. When a controller is loaded, this default method will be called if no request URI matches the custom method of the controller.
See Using Controller Methods tutorial for more details about the controller methods. -
Parameter
None
-
Return
None
-
Usage
No parameter:
public function __index() { echo 'Hello World'; }
Multiple parameters:public function __index($name, $age) { echo "My name is " . $name . ", I'm " . $age; }
[method] view( string $file [, array $data [, boolean $return]])
-
Description
The default method of a controller. When a controller is loaded, this default method will be called if no request URI matches the custom method of the controller.
See Using View tutorial for more details about how to use view. -
Parameters
-
$file
Required. The path of view file. -
$data
Optional. The variables to be passed to the view. Default is an empty array. -
$return
Optional. Return the view output as a string or output to browser directly. Default is false.
-
$file
-
Return
Object | Boolean
If the parameter$return == false
, then this method will return an object$this
pointed to the current controller. Or it will returntrue
for success. -
Usage
Basic:
$this->data['home_user'] = 'Peter'; $this->view('home/body.php');
Pass parameter:$this->view('home/body.php', array('home_user'=>'Peter'));
Multiple calls:$this->view('home/header.php')->view('home/body.php')->view('home/footer.php');
Return as a string:$html = $this->view('home/body.php', array(), true);
[method] model( string|array $files )
-
Description
Load model file(s). This method is is equivalent to
library()
method.
See Using Model & Library tutorial for more usages of the this method. -
Parameter
-
$files
Required. The paths of single or multiple models to be loaded.
-
$files
-
Return
Object
An object$this
pointed to the current controller will be returned. -
Usage
Load single model:
$this->model('user_model.php');
Load multiple models:$this->model(array( 'user_model.php', 'home_model.php' ));
Or in this way:$this->model('user_model.php')->model('home_model.php');
[method] library( string|array $files )
-
Description
Load library file(s). This method is is equivalent to
model()
method.
See Using Model & Library tutorial for more usages of the this method. -
Parameter
-
$files
Required. The paths of single or multiple libraries to be loaded.
-
$files
-
Return
Object
An object$this
pointed to the current controller will be returned. -
Usage
Load single library:
$this->library('image_lib.php');
Load multiple libraries:$this->library(array( 'image_lib.php', 'wiki_lib.php' ));
Or in this way:$this->library('image_lib.php')->library('wiki_lib.php');
[method] site_url( [string $uri] )
-
Description
A helper function. Return the URL of the current website.
-
Parameter
-
$uri
Optional. The URI to be appended to the site's URL. Default is an empty string.
-
$uri
-
Return
String
-
Usage
Basic:
$url = $this->site_url();
// result: http://your-site-url.com/Use URI:$home_url = $this->site_url('home');
// result: http://your-site-url.com/home
[method] current_url()
-
Description
A helper function. Return the current URL, including all the request URIs.
-
Parameter
None
-
Return
String
-
Usage
$url = $this->current_url();
// result: http://your-site-url.com/home/peter?page=2
[method] redirect( [string $url [, int $code]] )
-
Description
A helper function. Redirect the page to a new URL. This function MUST be called before any result output to the browser, otherwise it will fail.
-
Parameters
-
$url
Optional. Both URI or full URL are allowed. For URI input, like 'home', your site's URL will be prepended to the URI to keep the input is a correct URL. Default is an empty string. -
$code
Optional. The HTTP response code. Default is 302.
-
$url
-
Return
None
-
Usage
Basic:
$this->redirect('home');
// 302 redirect to http://your-site-url.com/homeOther HTTP response code:$this->redirect('http://www.google.com/', 307);
// 307 redirect to http://www.google.com/
Configuration
Extra configurations should be made in config.php
. The config.php
file is optional, but it is helpful for some cases, tutorial can be found at Using Configuration
config.php
file need to be created manually, and it contains one array variable $_CONFIG
for configuration. Here is a sample config.php
:
<?php
$_CONFIG = array(
'debug' => false,
'base_uri' => '',
'auto_load' => array(),
'routes' => array()
);
[key] debug
-
Description
'debug' is used to mark whether the site is under development mode. When 'debug' is
true
, MoePress's system exception detail will be printed on the browser. Otherwise, the exception detail will be hidden. -
Type
Boolean
-
Usage
$_CONFIG['debug'] = true;
[key] base_uri
-
Description
'base_uri' is used when MoePress Mini is not installed in the root directory of website.
For instance, if MoePress Mini is in a subdirectoryblog/
, likehttp://your-site-url.com/blog/
, then the 'base_uri' should beblog
. -
Type
String
-
Usage
$_CONFIG['base_uri'] = 'project/blog';
[key] auto_load
-
Description
'auto_load' is an array which contains the file paths of models or libraries which need to be loaded automatically before calling the controller.
-
Type
Array
-
Usage
$_CONFIG['auto_load'] = array( 'model/user_model.php', 'library/image_lib.php' );
[key] routes
-
Description
'routes' is an array used for routing controller. The array keys are regular expressions used to match URIs, and the array values are the matched results. One URI can be matched sequentially more than once.
-
Type
Array
-
Usage
$_CONFIG['routes'] = array( '#^homepage\/(.*)$#' => 'home/$1', '#^home\/([a-z0-9_\-]+)\/album#' => 'home/album/$1' );
About
As a micro framework, MoePress Mini just focuses on few things: multi-level controller, routing and view action. So it's a good choice for lightweight projects.
Changelog
-
v1.1.1 - 2014.10.12
Fix bug, changesite_url
from $_SERVER['SERVER_NAME'] to $_SERVER['HTTP_HOST']. -
v1.1 - 2014.09.06
- Add limitation for the number of controller's arguments. See Limit Controller Arguments.
- Add
$config['debug']
for configuration. See [key] debug.
-
v1.0 - 2013.10.13
First version released.