steevedroz/ci4-base

Provides a very useful set of components to inherit from

1.5.1 2023-02-21 13:14 UTC

This package is auto-updated.

Last update: 2024-04-21 16:04:49 UTC


README

This library offers a very easy way to set up the base of a CodeIgniter project.

Installation

In order to install this package, call composer require steevedroz/ci4-base from your CodeIgniter root folder.

You must then run composer update from your repository.

Set up

Automatic script

By running vendor/bin/ci4-generate, the files template.html and BaseController.php described lower will be generated automatically.

Minimal configuration

The base controller requires a minimal configuration in order to work as intended.

First, you must create a template file at the location app/Views/template.html. The content of this file will be described hereafter.

Then, you should add a new property Config\App::siteName by editing app/Config/App.php like this:

<?php namespace Config;

use CodeIgniter\Config\BaseConfig;

class App extends BaseConfig
{
	public $siteName = '<your site name>';

    // the rest of the class
}

Folders should be created to contain CSS and JavaScript, they are namely: public/css and public/js. All .css and .js files must be placed in thoses files.

No further set up is required.

Content of template.html

The template file must contain a valid HTML, including a doctype and the standard <html> basic canvas, as specified by the W3C.

In this file, a few placeholders can be put:

  • {template_page_title} will display the page title. Config\App::siteName will be used there and must therefore be created if you choose to use that placeholder.
  • {template_css} will display all CSS <link> code that you need. This should be placed in the <head> section of the HTML page.
  • {template_js} will do the same with JavaScript <script> code. This should be placed in the <head> section of the HTML page.
  • {template_content} will include the part of the page that is different on each call.

Exemple template.html file could look like this:

<!DOCTYPE html>
<html lang="en" dir="ltr">

<head>
    <meta charset="utf-8">
    <title>{template_page_title}</title>
    {template_css}
    {template_js}
</head>

<body>
    <header></header>
    <main>{template_content}</main>
    <footer></footer>
</body>

</html>

BaseController

In order to use the base controller, first make a controller that extends SteeveDroz\CiBase\BaseController. Then, this controller has several new options described below.

Display the page

The very basic use of the BaseController is the following:

  1. Create an HTML page with a name corresponding to the controller method. For example, for the method User::show, create the file app/Views/user/show.html. In there, only put the fragment of page that is supposed to be inserted in the template.
  2. From the controller, call $this->render(); to display the template file, with the given fragment page.

Example:

<!-- app/Views/user/show.html -->
<h1>User page</h1>
<p>Welcome on the user page!</p>
<?php namespace App\Controllers;

use SteeveDroz\CiBase\BaseController;

class User extends BaseController
{
    public function show()
    {
        $this->render();
    }
}

Specific template

You can specify a different template page by calling $this->setTemplate('some-template.html') from the current controller or from the init() in BaseController.

Specific page

Instead of creating a page with a matching name, it is possible to create any page in app/Views and specify its name as a parameter: $this->render('some-page.html');. The .html can be ommited.

Inserting data

The BaseController library uses CodeIgniter4 parser to display pages. In order to use it, you can insert data in 2 steps:

  1. Add the desired placeholder in your page fragment (for instance, in app/Views/user/show.html). This placeholder must be placed in braces (for example: {username}).
  2. In the controller, set the value of the placeholder with the data property like this: $this->data['username'] = 'john-doe';.

If the data is an array, the braces placeholder can be replaced by opening and closing braces, as described in the CodeIgniter user guide.

Raw data

In order to insert raw data (i.e. data with HTML that should be interpreted instead of escaped), you can set use $this->rawData instead of $this->data from the controller.

Example: $this->rawData['description'] = 'This is the <em>best</em> description!';

NOTE: this must be used with caution and never with user content! It could be the source of major security holes in your code.

Adding CSS

For this to work, {template_css} must be placed in the <head> tag of app/Views/template.html.

From the controller, you can call the $this->css() method and specify the file you want to include and optionnally the media type.

These options are all compatible:

  1. The .css extension can be ommited: $this->css('style') or $this->css('style.css').
  2. The resource can be local (relative to public/css) or remote (starting with http(s)://).
  3. The second parameter is the media type of the spritesheet (screen, print, speech, etc.). By default, the value is all.

Adding JavaScript

For this to work, {template_js} must be placed in the <head> tag of app/Views/template.html.

From the controller, you can call the $this->js() method and specify the file you want to include and optionnally if the script bust be called before the DOM is ready.

These options are all compatible:

  1. The .js extension can be ommited: $this->js('script') or $this->js('script.js').
  2. The resource can be local (relative to public/js) or remote (starting with http(s)://).
  3. The second parameter (facultative) is if the resource must be loaded after the DOM is ready (true by default).
  4. The third parameter (facultative) is an array containing additional parameters, for example ['integrity' => 'sha256-yadaYadaYadaSha256IntegrityHash=', 'crossorigin' => 'anonymous'].

Example controller

<?php namespace App\Controllers;

use SteeveDroz\CiBase\BaseController;

class Article extends BaseController
{
    public function index()
    {
        // Set page title
        $this->data['page_title'] = 'Articles';

        // Set a normal placeholder
        $this->data['articles'] = $someModel->findAll();

        // Set a raw placeholder
        $this->rawData['hint'] = 'Press the <strong>?</strong> icon for help';

        // Set CSS files
        $this->css('menu'); // without .css
        $this->css('table.css'); // with .css
        $this->css('pages', 'print'); // with media type
        $this->css('https://example.com/layout.min.css'); // remote location

        // Set JS files
        $this->js('script'); //without .js
        $this->js('game.js'); // with .js (both work)
        $this->js('User', false); //without defer
        $this->js('https://code.jquery.com/jquery-3.5.1.min.js', false, ['integrity' => 'sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=', 'crossorigin' => 'anonymous']); // remote location

        // Display a page with the same name as the current controller
        // (app/Views/article/index.html)
        $this->render();

        // ALTERNATIVELY, display a specific page
        // (app/Views/example.html)
        $this->render('example');
    }
}

Note about Auto Routing Improved (since CodeIgniter 4.2.0)

Since the version 4.2.0, it is no longer possible to auto-route methods such as User::login. Instead, one must define User::getLogin and User::postLogin to access it either in GET or POST.

ci4-base 1.5.0 detects the name of such methods and can link to views having the same name without the prefix.

Exemple:

class User extends BaseController
{
    public function getLogin()
    {
        // code
        $this->render();
    }

    public function postLogin()
    {
        // code
        $this->render();
    }
}

Both methods display the content of app/Views/user/login.html.

Warning: only the methods GET and POST work this way, as this library isn't meant to be used to deal with PUT or DELETE requests.

BaseModel

The base model est way more minimal, although the options provided will save you a lot of time.

To use it, simply make your model extends SteeveDroz\CiBase\BaseModel.

Working with events

When working with CodeIgniter Model events, it can rapidly get a bit confusing about what is the content of afterFind parameters. By working with the applyOnFind() method, the base model will detect if you are working with one or many entries and perform the desired operation accordingly.

In order to harness the power of this method, one must first use the afterFind event.

The method takes two arguments: the $data attribute and a callback to apply to each entry.

The callback takes one parameter reprensenting a single element. If the data are retrieved from the database with find() or first(), the callback will be applied to the found entry. If they retrieved with findAll(), it will be applied to each found entries individually.

Example model

<?php namespace App\Models;

use SteeveDroz\CiBase\BaseModel;

class User extends BaseModel {
	protected $table = 'users';
	protected $allowedFileds = ['first_name', 'last_name', 'email'];

	protected $afterFind = ['addFullName'];

	/* Adds a `full_name` field to each user.
	 * [
	 *   'first_name' => 'John',
	 *   'last_name' => 'Doe',
	 *   'email' => 'john.doe@example.com'
	 * ]
	 *
	 * becomes
	 *
	 * [
	 *   'first_name' => 'John',
	 *   'last_name' => 'Doe',
	 *   'email' => 'john.doe@example.com',
	 *   'full_name' => 'John Doe'
	 * ]
	 */
	public function addFullName($data)
	{
		return $this->applyOnFind($data, function($user)
		{
			$user['full_name'] = $user['first_name'].' '.$user['last_name'];
			return $user;
		});
	}
}

// ---

$user = $model->find(1); // $user will have a `full_name`
$user = $model->where('email', 'contact@example.com')->first(); // $user will have a `full_name`
$users = $model->findAll(); // each user in $users will have a `full_name`

Contribute

Contributions in the form of issues or merge request are more than welcome!

If you are new to programming, to CodeIgniter 4, or feel unsure about your aptitude to take part in this project, please consider contributing anyway! As a CS teacher, I am willing to take a look at your code and help you improve it. Seriously, I mean it! After all, it's Git, you can't break anything…