The purpose of this article is to share experience in writing a simple OOP MVC PHP framework. I also want to provide the community with source code and ask for criticism, approval, comments and support.
Introduction
In the course of the operation of various modern frameworks, I realized that I didn’t understand enough how everything is arranged inside; I do not realize why the developers chose this or that solution; I pay attention only to the current task and do not look "higher, deeper and farther." And, as an option for professional growth, I chose to create my own project.
As practice has shown further: to read, know, hear about something, and to be able to realize it yourself are completely different things. Theorizing can be infinite, but only a real practical task allows you to understand at what level you are. In this connection, “writing your own bicycle” was started. How it turned out - to judge you.
Development process
Development of the framework was carried out as follows: initially there was some simple web application that was being developed, copied, changed structure, acquired new classes and components, etc. A few months ago I had free time, a lot of enthusiasm and decisiveness to finish the framework -serious. " I spent 3-4 weeks together to write this version (working on average 1-3 hours per day, 3-4 days per week).
')
As the standards and requirements were developed, I deliberately overestimated myself, I searched for optimal solutions and rewrote the code many times. So, for example, I changed the work with the configuration 5-6 times (and several times dramatically), routing - 3-4 times. As examples, I took the code from articles, publications, manuals, frameworks (Yii2, CodeIgniter, Zend, Phalcon, Bun), etc.
Requirements analysis
It all starts with an analysis of the requirements and wishes for the final system.
The framework should:
- allow you to quickly create a website from scratch
- have a number of already implemented basic technical solutions and tools
- contain split frontend and backend
- meet modern requirements for code, technology, applied technical solutions, etc.
- already contain in the basic configuration a demo application on the basis of which you can conduct your development
- be modular and extensible
- have clear documentation, technical support (ideally - community)
Applied technologies
The list of such decisions directly depends on what you know and what you apply in your real practice. Those. We approach the need for continuous monitoring of new products and changes in IT.
Practices and technologies:
- Programming language: PHP > = 5.5. * Or PHP > = 7. *
- Database: MySql > = 5.4. *
- Package Manager: Composer
- Autoload: PSR-4 , Encoding: PSR-2 , Logging: PSR-3
- We use the functionality of the language: namespaces, traits, magic functions , etc.
- Apply patterns when building class structure, implementing tasks
- Typesetting html code using Twitter Bootstrap
- We use the best approaches in programming: SOLID, DRY, KISS, YAGNI
- We cover the code PhpUnit- tests (testing the work of the base classes of the application)
- we cover Codeception functionality with tests (acceptance testing)
Folder structure
I will give the structure of files and folders in the framework (you can also see the code on
GitHub ):
Code
There is one
single entry point in the application. I cite the code of the
index.php file from the root public folder of the web server.
session_start(); $loader = require(__DIR__ . '/../../vendor/autoload.php'); $loader->addPsr4('framework\\', __DIR__ . '/../../system/'); $loader->addPsr4('frontend\\', __DIR__ . '/../'); $loader->addPsr4('common\\', __DIR__ . '/../../common/'); $config = array_merge( require(__DIR__ . '/../config/main.php'), require(__DIR__ . '/../../common/config/main.php') ); $appication = new \framework\core\Application(); $appication->run($config);
The
run method code
($ config) from the
\ framework \ core \ Application () class. The required classes of the application are loaded and the corresponding controller is called (in the
execute () method).
public function run($config = []) { $this->benchmark = new Benchmark(); $this->environment = Environment::get(); $this->config = new Registry($config); $this->response = new Response(); $this->request = Request::getInstance(); $this->assets = new Asset($this->config->assets); $this->setParams(); $this->router = new Router($this->config->routes); $this->execute(); }
The code for the
execute () method from the
\ framework \ core \ Application () class. The required controller has already been selected at this stage, we initialize this controller, handle the headers, and display the content. In case of an error - we throw
404 Not Found .
public function execute() { $controllerName = $this->router->getControllerName(); try { $controllerClass = '\\' . $this->config->name . '\controllers\\' . $controllerName . 'Controller'; if (class_exists($controllerClass)) { $controller = new $controllerClass; if ($controller instanceof Controller) { $controller->setApplication($this)->run(); } } else { throw new CoreException('Controller "' . $controllerName . '" not exists: ' . Request::getInstance()->server["REQUEST_URI"]); } } catch (CoreException $e) { $e->logError(); $this->response->setHeader("HTTP/1.1 404 Not Found"); $this->router->error404(); $this->execute(); exit(); } foreach ($this->response->getHeaders() as $header) { header($header); } echo $this->response->getContent(); }
Improvements and future plans
As an adapter to connect to the database, I used
PDO . In the course of PDO, I didn’t like it very much - it’s hard to debug queries, I want comfort in using ORM. You can install
Eloquent ORM - this is a modern and ready-made solution (used in the Laravel framework), and besides, it is well documented and can be installed from the composer in a few minutes.
I also thought about expanding the basic functionality of the framework: I wanted to add support for modules. Those. so that you can write, for example, a blog as a separate module (with its own controllers, viewers, models, etc.). And then connect this module anywhere in the application.
It is possible to expand the base “gentleman’s” set of classes in the core, complicate the system of logging, error handling, configuration, write a full-fledged demo site with all the functionality, etc.
Conclusion
I will be glad to hear criticism of the code, architecture, initial requirements and other things. Comments will be actively read, I will try to answer questions.
I would also like to implement a project based on this framework. That is to say to test the tool in work. It is clear that the search for customers is not at all to this section, but I would like to hear whether it is possible to start a real project with this decision? Popular out-of-the-box frameworks provide functionality 50-100 times better and bigger, difficult to compete with.
→
GitHub Code