-
Notifications
You must be signed in to change notification settings - Fork 0
Tutorial
This framework adopts a Front Controller model. This means that all HTTP requests are processed by the Dispatcher class, which routes each request to the appropriate resource (controller and method). This design pattern helps to organize and manage the code, and simplifies the generation of responses to various types of requests (such as GET, POST, etc.) and data formats (like HTML, JSON, etc.).
In this framework, the format of URLs is specified as 'ControllerClassName/MethodName'. The class and method to be executed are determined by this URL. This allows you to intuitively understand which URL corresponds to which controller and method.
For instance, the URL http://yourwebsite.com/product/show would execute the 'showAction' method of the 'ProductController' class.
Also, this framework adopts a naming convention for template, JavaScript, and CSS files as 'ClassName/MethodName.tpl', 'ClassName/MethodName.js', 'ClassName/MethodName.css' respectively. This makes it easier to track which controller and method correspond to which view files, JavaScript files, and CSS files.
In this tutorial, we will explain these basic concepts and how to use the framework in detail.
In this section, we'll explain how to construct controllers and the role they play within the framework.
You define the routing by creating methods in your Controller class with the suffix 'Action'. More specifically, these methods correspond to URLs of the format 'ControllerClassName/MethodName'. Each controller file is located in the format /class/controller/{ControllerName}Controller.php.
Here's an example of a controller class reflecting these concepts:
/**
* SampleController
*/
class SampleController extends ControllerBase
{
/**
* Processed before the controller method is executed
*
* @return void
*/
protected function preAction()
{
// $this->SESSION_CHECK = false;
}
/**
* INDEX
*
* @return void
*/
public function indexAction()
{
$this->setTitle('Hello NeNe-PHP!!');
$this->setString('t_contents', 'This framework is produced by AYANE International.');
}
}The preAction() method is where you write the code to be executed before each Action is called. The ControllerBase class, which is the superclass of Controller, implements the basic features needed for website construction. For example, setTitle() provides the ability to set the page's <title/> tag, and setString() provides the ability to pass a string to a variable written in the template file.
Smarty is adopted as the template engine. This simplifies the generation of HTML and display of data.
In our framework, we have adopted Smarty as our template engine. The template files are arranged in the following structure:
-
/view/compile/: The compiled template files. -
/view/source/{ControllerName}/*.tpl: Template files for each controller. -
/view/source/*.tpl: Common template files shared across the application.
For security reasons, we recommend setting the document root to the htdocs directory within your project folder. If there's a necessity to set the project folder as your document root, please move the /view directory to a location that's either within the document root or inaccessible from outside.
Additionally, you would need to revise the constants defined in /ini/xSystemIni.php according to the new location of the moved directory:
// VIEW
const DIR_SMARTY_TEMPLATE = DIR_ROOT . 'view/source'; // SMARTY TEMPLATE
const DIR_SMARTY_COMPILE = DIR_ROOT . 'view/compile'; // SMARTY TEMPLATE COMPILE
const DIR_SMARTY_CONFIG = DIR_ROOT . 'view/config'; // SMARTY CONFIG
const DIR_SMARTY_PLUGINS = DIR_ROOT . 'view/plugins'; // SMARTY PLUGINThrough this configuration, management and maintenance of template files can be conducted efficiently.
When accessing via the browser with {Controller class name}/{method name}, the template files are searched for in the following order. If a file exists, that file will be loaded.
/view/{Controller class name}/{method name}.tpl/view/{Controller class name}/common.tpl/view/{Controller class name}.tpl/view/common.tpl
Here is a sample template for a site login screen:
{include file='head_01.tpl'}{include file='head_02.tpl'}
<p class="information">
{$t_contents}
</p>
<div class="login__form_block">
<div id="app" class="hidden">
{include file='../components/loginform.tpl'}
</div>
</div>
{include file='footer.tpl'}For more details on how to use the template, please refer to the official Smarty page.
When accessing the framework via a browser using a specific URL in the format {Controller class name}/{method name}, the framework searches for JavaScript and CSS files based on the rules outlined below. If the files exist, they are loaded in the order specified.
-
/htdocs/css/common.css: Common styles shared across all controllers and methods. -
/htdocs/css/{Controller class name}.css: Styles specific to a particular controller but shared across its methods. -
/htdocs/css/{Controller class name}/common.css: Alternative location for styles specific to a controller but shared across its methods. -
/htdocs/css/{Controller class name}/{method name}.css: Styles unique to a specific method within a controller.
-
/htdocs/js/common.js: Common scripts shared across all controllers and methods. -
/htdocs/js/{Controller class name}.js: Scripts specific to a particular controller but shared across its methods. -
/htdocs/js/{Controller class name}/common.js: Alternative location for scripts specific to a controller but shared across its methods. -
/htdocs/js/{Controller class name}/{method name}.js: Scripts unique to a specific method within a controller.
It's important to note that beyond loading these files based on the aforementioned rules, the framework doesn't interfere with the directory. This means users have the flexibility to integrate mechanisms like SCSS auto-compilation or to use any JavaScript framework of their choice. This design choice ensures that developers have the freedom to extend or customize their asset pipeline as needed.
This framework searches for asset files based on the specified rules. If a file is found, it uses the filemtime function to retrieve the file's last modified timestamp. When referencing the file in the HTML header, it appends the timestamp in the format ?unixtimestamp. This method is implemented to prevent outdated caches from being mistakenly used when a file gets updated.
Our framework supports both MySQL and SQLite3 databases. In this section, we'll guide you through the process of setting up a MySQL database and how to use it within the framework.
To set up your database connection, navigate to /ini/xSystemIni.php. In this file, you'll find a section dedicated to database connection details. Please update this section with the appropriate details for your MySQL database:
// データベース接続設定
const DB_TYPE = 'SQLite3'; // TYPE [MySQL|SQLite3]
const DB_DIR = DIR_ROOT . 'data/'; // DIRECTORY FOR SQLite3 DATABASE
const DB_FILE = 'nene.db'; // FILE NAME FOR SQLite3 DATABASE
const DB_USER = 'root'; // USERNAME
const DB_PASS = ''; // PASSWORD
const DB_HOST = 'localhost'; // HOSTNAME
const DB_NAME = 'nene-php'; // DATABASE NAMEMake sure to set DB_TYPE to MySQL. You can leave the DB_DIR and DB_FILE constants as they are, as these are specific to SQLite3 setups.
By crafting a Model class, you empower your application to interact seamlessly with database tables.
For illustrative purposes, let's walk through creating a model for a user table. Assume we have the following table structure:
| Field | Type | Null | Key | Default | Extra |
|---|---|---|---|---|---|
| id | int(11) | NO | PRI | NULL | auto_increment |
| user_id | varchar(50) | NO | NULL | ||
| user_pass | varchar(50) | NO | NULL | ||
| user_name | varchar(50) | NO | NULL | ||
| e_mail | varchar(100) | YES | NULL | ||
| created_at | datetime | YES | NULL | ||
| updated_at | datetime | YES | NULL |
Using the column details above, we'll construct the User Model class. This class, which extends DataModelBase, will encapsulate the aforementioned columns as properties:
<?php
namespace Nene\Database;
use Nene\Xion\DataModelBase as DataModelBase;
class UserModel extends DataModelBase
{
protected static $schema = [
'id' => self::INTEGER,
'user_id' => parent::STRING,
'user_pass' => parent::STRING,
'user_name' => parent::STRING,
'e_mail' => parent::STRING,
'is_deleted' => parent::STRING,
'created_at' => self::DATETIME,
'updated_at' => self::DATETIME
];
protected static $validation = [
'user_id' => ['required' => true],
'created_at' => ['required' => true],
'updated_at' => ['required' => true],
'user_id' => ['required' => true, 'maxlength' => 64],
'user_pass' => ['required' => true, 'maxlength' => 64, 'minlength' => 6],
'user_name' => ['required' => true, 'maxlength' => 255],
'e_mail' => ['required' => true, 'maxlength' => 255],
'is_deleted' => ['required' => true, 'bool' => true]
];
}When designing your application, leverage this model structure to ensure a systematic approach to database interactions.
The $schema variable represents the type information for each column in the table. The supermodel DataModelBase already provides constants tailored for these types.
<?php
abstract class DataModelBase
{
protected const BOOLEAN = 'boolean';
protected const INTEGER = 'integer';
protected const DOUBLE = 'double';
protected const FLOAT = 'double';
protected const STRING = 'string';
protected const DATETIME = 'dateTime';
protected const DATE = 'date';
}Incorporate these constants to consistently define and manage the data types within your models.
The $validation variable defines validation rules for data before it's saved to the database. By using this variable, you can ensure input data conforms to the expected format and range. This helps prevent saving unauthorized or unexpected data, enhancing the application's robustness. Proper validation rules are essential for data consistency and to catch user input errors beforehand.
| Rule | Description |
|---|---|
required |
If set to true, the corresponding property is mandatory. |
maxlength |
The value for the corresponding property must have a character count less than or equal to this number. |
minlength |
The value for the corresponding property must have a character count greater than or equal to this number. |
zeroOrLength |
The value for the corresponding property must have a character count of either this number or zero. |
length |
The value for the corresponding property must have a character count matching this number. |
enum |
The value for the corresponding property must be one of the values in this array. |
bool |
If set to true, the corresponding property's value must be either 1 or 0. |
Using the $validation variable, you can clearly define and manage validation requirements for each model property.
After initializing the model, you can set parameters using the setParam() method. This method supports method chaining, allowing you to set multiple parameters consecutively.
<?php
use Nene\Xion\ControllerBase;
$user = new Database\User();
$user->setParam('user_id', '123')
->setParam('user_pass', 'password')
->setParam('user_name', 'Mary Smith')
->setParam('e_mail', 'user@example.com');If a parameter violates validation, an exception like the following is thrown:
<?php
throw new \Exception('Parameter ' . $prop . ' is a validation error. (value : ' . $val . ')');If you want to avoid exceptions, it's recommended to use the set() method. This method won't update the parameter if a validation error occurs and will return false.
<?php
use Nene\Xion\ControllerBase;
$user = new Database\User();
$user->set('user_id', '123');
$user->set('user_pass', 'password');
$user->set('user_name', 'Mary Smith');
$user->set('e_mail', 'user@example.com');You can check the validation for a specified column name and value using the validate() method. This method returns the validation result as a boolean.
<?php
use Nene\Xion\ControllerBase;
$user = new Database\User();
$result = $user->validate('ColumnName', 'testValue');In this framework's data handling, we utilize two primary components: the model and the mapper.
- Represents each row of a database table as an object.
- The model functions as an entity possessing data attributes and behaviors.
- In this framework, the
setParam()method can be used to set the values for each attribute (or column) of the model.
- Manages interactions between the database and the model.
- The mapper is responsible for operations on the database, such as creating, reading, updating, and deleting model objects.
- For instance, you can add model data to a database table using the
insert()method.
To delve into how to add data to the database using the combination of the model (User) and the mapper, we'll detail each step of the process.
First, create an instance of the user.
<?php
$user = new Database\User();Use the setParam() method to set the data you want to store in the User model.
<?php
$user->setParam('user_id', '123')
->setParam('user_pass', 'password')
->setParam('user_name', 'Mary Smith')
->setParam('e_mail', 'user@example.com');Once the data is set in the model, utilize the mapper to add this data to the database. The mapper acts as a bridge between the model and the database, encapsulating specific database operations (in this case, insert).
<?php
$userMapper = new Database\UserMapper();
$userMapper->insert($user);Through this design, combining the model and mapper effectively allows for simple and efficient database operations. The model defines the "what" of the data, while the mapper dictates "how" that data interacts with the database.