
Writing a Simple Encyclopedia on Slim Framework
- Tutorial
In this article, 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 a corresponding note in a beautiful template.
Maybe our encyclopedia contains answers to frequently asked questions about cars, or maybe it's a medical guide. Not the point. The main thing is that we do not need CRUD, since another system will be responsible for filling the database table. But stability, speed and ease of support for this simple application are very important to us.
Such an encyclopedia can be very easily created using other frameworks and CMS, but I will try to use the Slim microframework. Why? It's very simple: this note is designed for a novice programmer who wants to start learning 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 the method mentioned in the interface will need:
Next, you need to implement a class containing the "getContentByAlias" method. Since the note is designed for the beginner level of the reader, I will specially remind you of the need to impose an index on the “alias” column. With a large number of materials in the encyclopedia, the index (there will be a search on it) will increase the speed of the database server. We will not touch on such issues as caching (for example, memcached or nginx tools), since this is a separate and very large topic. But about the basic security requirements, it makes sense to mention: shift the responsibility for shielding to the driver, for example, in this way:
Please note that in the query I explicitly indicated to the MySQL subsystems that I only need one record ("LIMIT 1"), and received the data using "fetch", ie only one entry. I use PDO, and I pass the connection through the constructor of the 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 can see, we will need Singleton, which will allow us to get a much-needed connection to the database. In my subjective opinion, a suitable implementation method is as follows:
So the time has come for the implementation of the factory itself. With high probability, such an electronic encyclopedia will not develop (in the sense of a new functional), however, the probability is not at all zero, therefore, it is necessary to provide for the possibility of finalizing and developing the project at the very initial stage of design. The implementation of the factory was as follows:
I have not forgotten anything? Oh yes. Where is Slim itself? First of all, we need to connect the files necessary for our simple application - a very ascetic electronic encyclopedia. At this stage, we will specify the “debug” mode in the settings:
Remember that we must show the content in the template depending on the page alias? Using the second argument of the render method, data is transferred to the view (View in the MVC pattern). And we also had a requirement to redirect the user to the main page if there is no search entry in the database. The redirect method solves this problem. Using “use”, we pass the required arrays and other variables to the scope of the anonymous function (closure or lambda function appeared in PHP since version 5.3). Let's try:
In cases where the view is static content, it is sufficient to use the following implementation:
Let's think about the sad. Mistakes can happen, which means that we must definitely consider the behavior of the electronic encyclopedia in such situations. As the ancient sages said: “the programmer is not the only 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 case of an unsuccessful attempt to find the page, however, in this example, in case of any errors, I 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):
Everything is ready, it remains only to call the "run" method:
Simply? Good documentation will help you understand all the features of 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 the meeting).
Maybe our encyclopedia contains answers to frequently asked questions about cars, or maybe it's a medical guide. Not the point. The main thing is that we do not need CRUD, since another system will be responsible for filling the database table. But stability, speed and ease of support for this simple application are very important to us.
Such an encyclopedia can be very easily created using other frameworks and CMS, but I will try to use the Slim microframework. Why? It's very simple: this note is designed for a novice programmer who wants to start learning 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 the method mentioned in the interface will need:
interface IPortal {
public function getContentByAlias($alias);
}
Next, you need to implement a class containing the "getContentByAlias" method. Since the note is designed for the beginner level of the reader, I will specially remind you of the need to impose an index on the “alias” column. With a large number of materials in the encyclopedia, the index (there will be a search on it) will increase the speed of the database server. We will not touch on such issues as caching (for example, memcached or nginx tools), since this is a separate and very large topic. But about the basic security requirements, it makes sense to mention: shift the responsibility for shielding 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;';
/**
* Constructor
*/
public function __construct($_pdo) {
$this->_pdo = $_pdo;
}
/**
* Get content by alias
*/
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 query I explicitly indicated to the MySQL subsystems that I only need one record ("LIMIT 1"), and received the data using "fetch", ie only one entry. I use PDO, and I pass the connection through the constructor of the 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 can see, we will need Singleton, which will allow us to get a much-needed connection to the database. In my subjective opinion, a suitable implementation method 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];
/**
* Constructor
*/
private function __construct() {
$this->_pdo = new PDO($this->_pdoUrl, $this->_pdoUser,
$this->_pdoPassword, $this->_pdoPrm);
}
/**
* Singleton
*/
private function __clone() {}
private function __wakeup() {}
public static function getInstance() {
if (self::$_instance === null) {
self::$_instance = new self;
}
return self::$_instance;
}
/**
* Get connection
*/
public function getConnection() {
return $this->_pdo;
}
}
So the time has come for the implementation of the factory itself. With high probability, such an electronic encyclopedia will not develop (in the sense of a new functional), however, the probability is not at all zero, therefore, it is necessary to provide for the possibility of finalizing and developing the project at the very initial stage of design. The implementation of the factory was as follows:
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 itself? First of all, we need to connect the files necessary for our simple application - a very ascetic electronic encyclopedia. At this stage, we will specify the “debug” mode in the settings:
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 must show the content in the template depending on the page alias? Using the second argument of the render method, data is transferred to the view (View in the MVC pattern). And we also had a requirement to redirect the user to the main page if there is no search entry in the database. The redirect method solves this problem. Using “use”, we pass the required arrays and other variables to the scope of the anonymous function (closure or lambda function appeared in PHP since version 5.3). 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 view 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. Mistakes can happen, which means that we must definitely consider the behavior of the electronic encyclopedia in such situations. As the ancient sages said: “the programmer is not the only 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 case of an unsuccessful attempt to find the page, however, in this example, in case of any errors, I 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 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 the meeting).