In this post we will look at the process of creating a very simple electronic encyclopedia using the Slim Framework. Suppose you have a database table that contains a huge number of encyclopedic notes and articles. We need to show the user the corresponding note in a beautiful template.
Maybe our encyclopedia contains answers to frequently asked questions about cars, and maybe this is a medical reference book. Not the bottom line. The main thing is that we do not need CRUD, since another system will be responsible for filling the database table. But we are very important stability, speed and ease of support for this simple application.
Such an encyclopedia can be very easily created using other frameworks and CMS, but I will try to use the Slim microform. Why? It's very simple: this note is designed for a novice programmer who wants to start learning the Slim Framework.
Let's start writing the code. The only task of the encyclopedia is to display the contents in a beautiful template. This ascetic functionality is similar to the help system API. Let's start with the implementation of the model and everything connected with it. The unique name of the page will be the only argument that will be needed by the method mentioned in the interface:
interface IPortal { public function getContentByAlias($alias); }
Next, you need to implement a class that contains the “getContentByAlias” method. Since the note is intended for a novice reader level, I will specifically remind you to impose an index on the “alias” column. With a large number of materials in the encyclopedia, the index (it will be searched) will increase the speed of the database server. We will not touch upon such issues as caching (for example, memcached or using nginx tools), since this is a separate and very large topic. But about the basic security requirements, it makes sense to mention: transfer the responsibility for screening to the driver, for example, in this way:
class Portal implements IPortal { private $_pdo; private $_sqlGetContentByAlias = 'SELECT `title`, `content` FROM `pages` WHERE `alias` = ? LIMIT 1;'; public function __construct($_pdo) { $this->_pdo = $_pdo; } public function getContentByAlias($alias) { $stm = $this->_pdo->prepare($this->_sqlGetContentByAlias); $stm->bindParam(1, $alias, PDO::PARAM_STR); $stm->execute(); return $stm->fetch(); } }
Please note that in the request I explicitly indicated to MySQL subsystems that I need only one record (“LIMIT 1”), and received data using “fetch”, i.e. only one entry. I use PDO, and I transfer connection through the designer of a class. Since the Slim Framework does not contain built-in capabilities for working with databases (unlike my favorite Laravel and Yii 2.0), we will have to write another small class. As you have noticed, we will need Singleton, which will allow us to get the much needed connection to the database. In my subjective opinion, the appropriate method of implementation is as follows:
class Connect { private static $_instance; private $_pdo; private $_pdoUrl = 'mysql:host=localhost;dbname=kalinin;charset=utf8'; private $_pdoUser = 'root'; private $_pdoPassword = ''; private $_pdoPrm = [PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC]; private function __construct() { $this->_pdo = new PDO($this->_pdoUrl, $this->_pdoUser, $this->_pdoPassword, $this->_pdoPrm); } private function __clone() {} private function __wakeup() {} public static function getInstance() { if (self::$_instance === null) { self::$_instance = new self; } return self::$_instance; } public function getConnection() { return $this->_pdo; } }
So it is time to implement the factory itself. It is highly likely that such an electronic encyclopedia will not develop (in the sense of a new functional), however, the probability is not zero at all, therefore, it is necessary to foresee the possibility to refine and develop the project at the very initial design stage. The implementation of the factory turned out to be this:
require './app/models/iportal.php'; require './app/models/portal.php'; require './db/connect.php'; class Factory { public static function create($type) { $connection = Connect::getInstance()->getConnection(); switch ($type) { case "simple": return new Portal($connection); break; } } }
I have not forgotten anything? Oh yes. Where is Slim? First of all, we need to connect the files necessary for our simple application - a very ascetic electronic encyclopedia. At this stage we will indicate in the settings the “debug” mode:
require 'Slim/Slim.php'; require './app/models/factory.php'; \Slim\Slim::registerAutoloader(); $app = new \Slim\Slim(); $app->config('debug', true); $app->config(['templates.path' => './app/views/']); $conf['url'] = 'http://127.0.0.1:8098/';
Remember that we have to show the content in the template depending on the page alias? By means of the second argument of the "render" method, data is transferred to the view (View in the MVC pattern). We also had the requirement to redirect the user to the main page in case there is no record in the database. The “redirect” method solves this problem. With the use of "use" we pass into the scope of an anonymous function (closure or lambda function appeared in PHP since version 5.3) the required arrays and other variables. Let's try:
$app->get('/kalinin/:alias', function ($alias) use ($app, $conf) { $model = Factory::create("simple"); $content = $model->getContentByAlias($alias); if(empty($content)) { $app->redirect($conf['url'], 301); } $app->render('page.php', $content); });
In cases where the presentation is static content, it is sufficient to use the following implementation:
$app->get('/', function () use ($app) { $app->render('main.php'); });
Let's think about the sad. Errors can happen, which means we must definitely consider the behavior of the electronic encyclopedia in such situations. As the ancient sages said: “the programmer is not alive with a single XDEBUG,” which means: “in real projects it makes sense to log some errors in detail”. According to the recommendations of the search engines, it is necessary to issue the 404th error code in an unsuccessful attempt to find the page, however, in this example, in case of any errors, I will simply redirect the user to the main page. To work with errors, use the following two closures (for example, I just have a redirect with the 301st response code):
$app->notFound(function () use ($app, $conf) { $app->redirect($conf['url'], 301); }); $app->error(function (\Exception $e) use ($app, $conf) { $app->redirect($conf['url'], 301); });
Everything is ready, it remains only to call the "run" method:
$app->run();
Simply? Good documentation will help you understand all the features of the Slim Framework. Of course, I described only one of the possible approaches. The need to use one or another framework is determined by the programmer on his own (or by a group of developers at a meeting).