Home > Article > Backend Development > PHP micro-framework design
1. Overall analysis of the framework
Before implementing a framework, we need to understand what effect the framework should achieve. According to the ideas of traditional frameworks, we can roughly summarize the following points:
1. Implementation The MVC architecture separates the control, logic, and view layers.
2. Encapsulate various functions and functional modules to enable writing in one place and calling in multiple places, reducing code redundancy.
3. It is easy to expand and can easily introduce external extension libraries to enhance its own framework.
4. Select the design pattern and encapsulate or write various engine modules.
The basic framework requirements are roughly like this. With these requirements, the next step is the design of an architecture. There are many problems involved that need to be solved. Let's analyze them step by step.
2. Framework design process
1. Framework directory
This is actually a very important step. Depending on your choice, the final directory structure will be very different. In addition to meeting the basic three layers In addition, extension libraries, front-end files, templates, resource files, etc. also need to be placed in directories, which determines whether it is convenient for you to call later. I used the smaty engine as the view engine in this framework design. The directory structure is roughly as follows:
This picture shows a structure of a two-level directory. The more in-depth directories are not shown one by one due to the limited picture display, and each directory and the main The functions of files will be discussed one by one later.
2. Directory introduction
(1) data directory
You can see the directory structure in the picture above. Since the smarty engine is used, the buffer directory and cache directory need to be configured in the smarty engine. So this is the role of the data directory.
(2)framework directory
This directory is the core of our framework, and the db directory contains our database operation function library. There is a function.php file placed in the function directory. The main function of this file is to facilitate the quick instantiation of method calls at each layer in a mode such as M (‘do’). The libs directory places the core factory class files of the framework, such as database operation classes and view operation classes, to facilitate external files to call the methods in it in such a way as DB::funtion(). view places the smarty view engine. include.list.php is the file that our framework needs to include when calling it. All of them are saved in an array. pc.php is our framework startup engine, responsible for the unified initialization of each of our modules and the parsing of our URLs.
(3) img directory
is used to place our style files, js files and other related resource files
(4) libs directory
Although the name of this directory is the same as the libs directory under the framework, But it can be seen that the corresponding business processing content in the three layers of MVC and an org extension directory are placed in this directory. Controller places controllers, Model places models, and View places view processing classes.
(5) tpl directory
This directory places some template files for front-end display. You can see that I have placed two directories, admin and index, for the storage of template files in the front-end and back-end respectively.
(6) admin.php and index.php
Generally speaking, single-entry mode will be used when using MVC architecture, and these two files are the entry files of the single-entry mode to start the framework.
(7) config.php
Basically all frameworks have this configuration file, which includes database configuration, smarty engine configuration, and the definition of some static variables, etc.
All these structures are just a basic structure of the micro-framework. In fact, complex frameworks will have many extended functions and external plug-ins, and corresponding adjustments can be made to this directory structure.
3. Key points of the framework
(1) Dynamic call of the controller
The usual URL in single entry mode is probably similar to index.php?controller=controller&method=method, which is obtained through the get method After the controller and method names, we can perform dynamic initialization in the following ways
function C($name,$method){ require_once('/libs/Controller/'.$name.'Controller.class.php'); eval('$obj=new '.$name.'Controller();$obj->'.$method.'();'); } function M($name){ require_once('/libs/Model/'.$name.'Model.class.php'); eval('$obj=new '.$name.'Model();'); return $obj; } function V($name){ require_once('/libs/View/'.$name.'View.class.php'); eval('$obj=new '.$name.'View();'); return $obj; }
(2) Native method transformation
Friends who are familiar with smarty should know that smarty has two methods, assign and display, which are used respectively. It is used to register variables and output variables to the template file, but registering multiple variables at the same time will make our code very complicated, so we try to transform these two methods
public static function assign($data){ foreach ($data as $key => $value) { self::$view->assign($key,$value); } } public static function display($template){ self::$view->display($template); }
We make the assign method redundant Write so that it can directly register the array, which reduces the amount of our subsequent code. If we want to introduce other external libraries, we can also use this method to transform the native function to make it more applicable.
(3) File inclusion logic
The startup file of this framework is pc.php. Therefore, including pc.php basically contains the files needed by the entire framework. First, take a look at an entry file index. .php content.
header("Content-type:text/html;charset=utf-8"); date_default_timezone_set('Asia/Shanghai'); require_once('config.php'); require_once('framework/pc.php'); PC::run($config)
It’s very simple. It contains the configuration file and framework startup engine pc.php, and then calls the run method to start the framework. Then look at the content of pc.php
$currentdir=dirname(__FILE__); include_once($currentdir.'/include.list.php'); foreach ($paths as $path) { include_once($currentdir.'/'.$path); } /** * 完成一系列的初始化和调用控制器 */ class PC { public static $controller; public static $method; private static $config; private static function init_db(){ DB::init('mysql',self::$config['dbconfig']); } private static function init_view(){ VIEW::init('Smarty',self::$config['viewconfig']); } private static function init_controller(){ self::$controller=isset($_GET['controller'])?daddslashes($_GET['controller']):'index'; } private static function init_method(){ self::$method=isset($_GET['method'])?daddslashes($_GET['method']):'index'; } public static function run($config){ self::$config = $config; self::init_db(); self::init_view(); self::init_controller(); self::init_method(); C(self::$controller,self::$method); } }
foreach traversal contains include all files in include.list.php, and pass the controller and corresponding method to the C class for automatic inclusion. Take another look at what is included in include.list.php
$paths=$arrayName = array( 'function/function.php', 'libs/core/DB.class.php', 'libs/core/VIEW.class.php', 'db/mysql.class.php', 'view/Smarty/Smarty.class.php' );
这里面存储了一个数组,包含了咱们的两个工厂类、数据库操作类、外部引擎类、核心function类。
至此,可以梳理一下整个框架对一个url请求的处理流程:
(4)业务分离
mvc的核心就在于各层之间的严格分离,但Controller层和Model经常容易被混淆在一起,这样会导致mvc架构失去原有的意义,我们需要清楚,控制层只实现简单的控制和逻辑处理,不涉及到具体的业务和数据交互,所有的具体操作都应放到Model层。另外,这两层中的类名和文件名也应保持一致。
(5)方法控制
我们在通过url的形式调用控制器及方法时,某些方法是不想被外部调用到的,比如登录检查函数,这个时候我们可以通过将函数定义为私有函数的方式避免其直接被通过url的形式调用到,来防止风险的发生。
(6)扩展性设计
一个框架应该具备好的扩展性,尤其对于新外部库引入,应该能很容易通过简单修改就可以使用,因此应该将配置项单独分离存储。
三、总结
该框架基本设计就是这个样子,很简单,但基本实现了mvc架构,虽然和市面上的成熟框架相差很多,但重写一遍对于mvc的架构理解会更加深入,加之如今越来越多的网站都采用的这种单入口mvc架构,对于这类网站的渗透更需要很好的理解。
1. Overall analysis of the framework
Before implementing a framework, we need to understand what effect the framework should achieve. According to the ideas of traditional frameworks, we can roughly summarize the following points:
1. Implementation The MVC architecture separates the control, logic, and view layers.
2. Encapsulate various functions and functional modules to enable writing in one place and calling in multiple places, reducing code redundancy.
3. It is easy to expand and can easily introduce external extension libraries to enhance its own framework.
4. Select the design pattern and encapsulate or write various engine modules.
The basic framework requirements are roughly like this. With these requirements, the next step is the design of an architecture. There are many problems involved that need to be solved. Let's analyze them step by step.
2. Framework design process
1. Framework directory
This is actually a very important step. Depending on your choice, the final directory structure will be very different. In addition to meeting the basic three layers In addition, extension libraries, front-end files, templates, resource files, etc. also need to be placed in directories, which determines whether it is convenient for you to call later. I used the smaty engine as the view engine in this framework design. The directory structure is roughly as follows:
This picture shows a structure of a two-level directory. The more in-depth directories are not shown one by one due to the limited picture display, and each directory and the main The functions of files will be discussed one by one later.
2. Directory introduction
(1) data directory
You can see the directory structure in the picture above. Since the smarty engine is used, the buffer directory and cache directory need to be configured in the smarty engine. So this is the role of the data directory.
(2)framework directory
This directory is the core of our framework, and the db directory contains our database operation function library. There is a function.php file placed in the function directory. The main function of this file is to facilitate the quick instantiation of method calls at each layer in a mode such as M (‘do’). The libs directory places the core factory class files of the framework, such as database operation classes and view operation classes, to facilitate external files to call the methods in it in such a way as DB::funtion(). view places the smarty view engine. include.list.php is the file that our framework needs to include when calling it. All of them are saved in an array. pc.php is our framework startup engine, responsible for the unified initialization of each of our modules and the parsing of our URLs.
(3) img directory
is used to place our style files, js files and other related resource files
(4) libs directory
Although the name of this directory is the same as the libs directory under the framework, But it can be seen that the corresponding business processing content in the three layers of MVC and an org extension directory are placed in this directory. Controller places controllers, Model places models, and View places view processing classes.
(5) tpl directory
This directory places some template files for front-end display. You can see that I have placed two directories, admin and index, for the storage of template files in the front-end and back-end respectively.
(6) admin.php and index.php
Generally speaking, single-entry mode will be used when using MVC architecture, and these two files are the entry files of the single-entry mode to start the framework.
(7) config.php
Basically all frameworks have this configuration file, which includes database configuration, smarty engine configuration, and the definition of some static variables, etc.
All these structures are just a basic structure of the micro-framework. In fact, complex frameworks will have many extended functions and external plug-ins, and corresponding adjustments can be made to this directory structure.
3. Key points of the framework
(1) Dynamic call of the controller
The usual URL in single entry mode is probably similar to index.php?controller=controller&method=method, which is obtained through the get method After the controller and method names, we can perform dynamic initialization in the following ways
function C($name,$method){ require_once('/libs/Controller/'.$name.'Controller.class.php'); eval('$obj=new '.$name.'Controller();$obj->'.$method.'();'); } function M($name){ require_once('/libs/Model/'.$name.'Model.class.php'); eval('$obj=new '.$name.'Model();'); return $obj; } function V($name){ require_once('/libs/View/'.$name.'View.class.php'); eval('$obj=new '.$name.'View();'); return $obj; }
(2) Native method transformation
Friends who are familiar with smarty should know that smarty has two methods, assign and display, which are used respectively. It is used to register variables and output variables to the template file, but registering multiple variables at the same time will make our code very complicated, so we try to transform these two methods
public static function assign($data){ foreach ($data as $key => $value) { self::$view->assign($key,$value); } } public static function display($template){ self::$view->display($template); }
We make the assign method redundant Write so that it can directly register the array, which reduces the amount of our subsequent code. If we want to introduce other external libraries, we can also use this method to transform the native function to make it more applicable.
(3) File inclusion logic
The startup file of this framework is pc.php. Therefore, including pc.php basically contains the files needed by the entire framework. First, take a look at an entry file index. .php content.
header("Content-type:text/html;charset=utf-8"); date_default_timezone_set('Asia/Shanghai'); require_once('config.php'); require_once('framework/pc.php'); PC::run($config)
It’s very simple. It contains the configuration file and framework startup engine pc.php, and then calls the run method to start the framework. Then look at the content of pc.php
$currentdir=dirname(__FILE__); include_once($currentdir.'/include.list.php'); foreach ($paths as $path) { include_once($currentdir.'/'.$path); } /** * 完成一系列的初始化和调用控制器 */ class PC { public static $controller; public static $method; private static $config; private static function init_db(){ DB::init('mysql',self::$config['dbconfig']); } private static function init_view(){ VIEW::init('Smarty',self::$config['viewconfig']); } private static function init_controller(){ self::$controller=isset($_GET['controller'])?daddslashes($_GET['controller']):'index'; } private static function init_method(){ self::$method=isset($_GET['method'])?daddslashes($_GET['method']):'index'; } public static function run($config){ self::$config = $config; self::init_db(); self::init_view(); self::init_controller(); self::init_method(); C(self::$controller,self::$method); } }
foreach traversal contains include all files in include.list.php, and pass the controller and corresponding method to the C class for automatic inclusion. Take another look at what is included in include.list.php
$paths=$arrayName = array( 'function/function.php', 'libs/core/DB.class.php', 'libs/core/VIEW.class.php', 'db/mysql.class.php', 'view/Smarty/Smarty.class.php' );
这里面存储了一个数组,包含了咱们的两个工厂类、数据库操作类、外部引擎类、核心function类。
至此,可以梳理一下整个框架对一个url请求的处理流程:
(4)业务分离
mvc的核心就在于各层之间的严格分离,但Controller层和Model经常容易被混淆在一起,这样会导致mvc架构失去原有的意义,我们需要清楚,控制层只实现简单的控制和逻辑处理,不涉及到具体的业务和数据交互,所有的具体操作都应放到Model层。另外,这两层中的类名和文件名也应保持一致。
(5)方法控制
我们在通过url的形式调用控制器及方法时,某些方法是不想被外部调用到的,比如登录检查函数,这个时候我们可以通过将函数定义为私有函数的方式避免其直接被通过url的形式调用到,来防止风险的发生。
(6)扩展性设计
一个框架应该具备好的扩展性,尤其对于新外部库引入,应该能很容易通过简单修改就可以使用,因此应该将配置项单独分离存储。
3. Summary
The basic design of this framework is like this. It is very simple, but it basically implements the mvc architecture. Although it is very different from the mature frameworks on the market, rewriting it will give you a deeper understanding of the mvc architecture. In addition, more and more websites today adopt this single-entry MVC architecture, and the penetration of such websites requires a good understanding.
For more PHP micro-framework design related articles, please pay attention to the PHP Chinese website!