Introduction Dernière mise à jour : 2024-06-11

.kernelite est un framework PHP 7.4+ français (ainsi qu'une lib JS & CSS) qui a pour but de faciliter la vie des développeurs.
Il a été créé par (Société SNEW) en Mars 2022 dans sa première version et est en perpetuel développement dans l'objectif de se parfaire.
Il convient à tous types de projets web et est très simple à prendre en main.

Lien vers le site de la société SNEW : SNEW - L'esprit de service

Les bases

.kernelite a une approche MVC mais tout en restant très flexible et permissif pour le développeur. De nombreuses fonctionnalités avancées très utiles ont été intégrées et retravaillées afin que leur utilisation se fasse sans effort.

.kernelite aide le développeurs graces à :
  • API-ready : rend le projet "api" ready sans rien avoir à faire
  • Rooting: un système de rooting automatisé réduit à sa plus grande simplicité
  • Reflexion: grace à la reflexion PHP, demandez et vous êtes livrés
  • No-SQL : quaisment aucune manipulation SQL requise (dans la majorité des cas)
  • Built-in JS: kernelite offre une librairie JS pour toutes les fonctions usuelles
  • Auto-update: mise à jour du framework automatique en ligne de commande

Les pré-requis

Afin de se lancer dans un projet sous .kernelite, certains pré-requis sont necessaires afin de ne pas être totallement perdu. Ils ne sont pas obligatoires mais vous permettront d'utiliser les outils mis à disposition par .kernelite en ayant pleine connaissance de la pertinence de leur utilisation.

Afin d'utiliser .kernelite il vous faudra des compétences en :
PHP Version 7.4 minimum : POO, paramètres typés, ...
Javascript ES6 Les promesses sont la base des fonctionnalités .kernelite
HTML 5 & CSS 3 Le front sera à la charge du développeur
Yaml Language de bibliothèque très simple d'utilisation
mustache (optionnel) moteur de templating (surcouché avec .kernelite)

Pourquoi Yaml ?

Yaml (.yaml) a sa propre syntaxe conviviale, et c'est un langage pratique à ajouter à votre arsenal de développement. Si vous connaissez JSON ou XML, alors vous ne serez pas perdu. L'avantage du Yaml est sa syntaxe réduite à son strict minimum.

Exemple de syntaxe Yaml :
        
            voiture :
                carrosserie : true
                roues : 4
                options : 
                  gps : true
                  abs : true
        
    
.kernelite utilise le Yaml pour :
  • Structures : décrivez très simplement les structures de vos objets en Yaml
  • Sécurité: établissez la sécurité et votre firewall en Yaml
  • Routing : déclarez une nouvelle route en quelques mots grace à Yaml (optionnel)

Installation & configuration

Vous retrouverez ici un guide étape par étape afin d'utiliser .kernelite sur votre projet.

Pré-requis techniques

.kernelite à besoin de certains pré-requis obligatoires afin de pouvoir fonctionner correctement. Assuez-vous de bien vérifier l'ensemble de ces critères avant même de procéder au téléchargement du framework.

Assurez-vous de vérifier les points suivants :
  • PHP 7.4+ : toute version anterieure de PHP ne permettra pas de lancer .kernelite
  • Apache 2 & .htaccess: .kernelite doit pouvoir utiliser son propres fichier .htaccess, verifiez vos virtualhosts et l'overwrite
  • Base MySQL / MS-SQL : assurez-vous d'avoir un accès MySQL ou SQL-server prêt

Système d'exploitation

.kernelite fonctionne aussi bien sous Windows que Linux

Téléchargement

Cliquez sur le bouton ci-dessous afin de télécharger la dernère version stable de .kernelite. Le fichier télécharger sera au format .zip, il vous faudra un outil de décompression. Une fois le zip décompressé, vous obtiendez un dossier "kernelite" contenant la structure du projet. Collez directement le contenu du dossier "kernelite" tout juste obtenu à la racine de votre projet.

Télécharger .kernelite v2.0 - 11/06/2024

Consulter les Release notes (cliquer pour ouvrir)

[6 Février 2023] v1.9 :
- Ajout de l'AutoUpdate du framework .kernelite en ligne de commande
- Correction d'un problème de redirection (lors d'un conflit de sécurité)
- Ajout des knotice() Javascript


[26 Janvier 2023] v1.8 :
- Ajout des fonctions templates : date_fr, asset, fragment, d, dd
- Ajout du HTTP Client
- Ajout du kJs : modal.prompt
- Ajout du Post
- Ajout de section de documentation
- Meilleures interceptions des différents messages d'erreur
- Possibilité de paramètrer le SALT des bases de données


[2 Janvier 2023] v1.7 :
- Multiple modifications et bugfix


[19 Décembre 2022] v1.6 :
- Ajout du système des Daemons .kernelite
- Le DataManager supporte le multi-base de données
- Les EasyBinds sont désormais attachés au document (et non plus aux objets)
- (JS) kernelite.navigate() accepte désormais un second paramètre pour ouvrir dans une nouvelle fenêtre
- (JS) kernlite.formToJson() prend en charge les tableaux de valeurs (ex : name="users[]" )
- (JS) Ajout de la méthode : kernelite.toArray() qui transforme un objet en Array si posssible

[22 Novembre 2022] v1.5 :
- Release note à venir
- Mise à jour de la documentation à venir

[28 Août 2022] v1.4 :
- Refonte du fichier de configuration au format YAML : my-project.php => project.yaml
- [project.yaml] Modification des user_uploads Voir
- [project.yaml] Ajout des mypaths Voir
- Ajout du support de Composer Voir
- Documentation d'installation & utilisation de Composer Voir
- Plugin : mPdf, installation & utilisation Voir


[27 juillet 2022] v1.3 :
- Ajout de $kParams disponible en php dans les templates afin d'accéder à toutes propriétés données en parametres à la méthode render
- Ajout dans defaultTemplateParameters : URL du projet, les profils de sécurité
- Ajout de la fonction template {% table() %} permettant de générer une table HTML automatiquement à partir d'un jeu de données
- Ajout de la fonction template {% btn() %}


[26 juillet 2022] v1.2 :
- Création automatique de la base de données si celle-ci n'existe pas
- Refonte de l'affichage de la Stacktrace de la KerneliteError page
- Ajout & renforcement des contrôles d'intégrité des structures et de leurs datas
- Injections de datas initiales des structures : format date dd/mm/yyyy autorisé


[10 juin 2022] v1.1 :
- Ajout du support de SQL Server dans le DataManager

Installation

Aucune installation particulière n'est à faire, déposez simplement le contenu du dossier "kernelite" présent dans le zip à la racine de votre projet.
Vous êtes prêts pour la configuration.

Exemple de dossier de projet .kernelite :
        
            var 
                www
                    monprojet
                        .conf
                        .kernelite
                        .structures
                        assets
                        controllers
                        templates
                        .htaccess
                        index.php
        
    

Configuration

Avant toute chose, il vous faudra vous rendre dans le dossier .conf du projet. C'est ici que vous devrez parametrer votre projet .kernelite. Ci-dessous, le contenu du dossier de configuration du projet.

.conf/project.yaml Configuration de votre projet, définition globales
.conf/security.yaml Définition des regles d'authentification & de sécurité
.conf/firewall.yaml Protection des règles de sécurité sur schéma
.conf/dump-style.php (optionnel) configurez l'apparence de vos dumps de développement

Afin de terminer la configuration, assurez-vous d'avoir rempli les champs obligatoires du fichier project.yaml. Un fois le fichier correctement renseigné, vous pouvez à présent vous rendre sur l'URL de votre projet afin d'afficher la page d'accueil de .kernelite.


La configuration : project.yaml

Définir votre public_url

Avant de démarer vos développements, la première chose à faire est de venir dans le fichier ./conf/project.yaml et préciser votre public_url.
C'est l'URL de votre projet.
Par exemple, si vous êtes en local, elle pourrait ressembler à : http://localhost/my_project

project.yaml : Dossier d'uploads des utilisateurs

Dans le fichier project.yaml, vous aurez à définir dans [directories] la diréctive [user_uploads] contenant : tmp et store.
Les propriétés tmp et store devront être des chemins vers des dossiers.
Ces deux chemins correspondent aux dossiers par défaut ou seront uploadés puis déplacés les téléchargements des utilisateurs du projet.
Il sera important de s'assurer que .kernelite a bien accès en lecture & écriture à ces chemins.

project.yaml : Mes chemins

Dans le fichier project.yaml, vous pouvez définir des chemins personnalisés. Vous pourriez avoir besoin de lire ou d'écrire dans un dossier autre que votre projet. Pour cela, .kernelite vous propose de définir l'ensemble des chemins que vous souhaitez utiliser facilement afin de vous en permettre une utilisation plus simplifiée.
Dans la configuration [directories] il est possible de définir [mypaths] qui sera une liste de chemin que vous souhaitez utiliser.


    directories :
        safe_mode : true
        user_uploads :
            tmp : .\tmp
            store : .\files
        mypaths : 
            - 
                name : project
                path : .\
                readOnly : false     
            - 
                name : library
                path : C:\Utilisateurs\Me\Library
                readOnly : true                  


Dans cet exemple, on définit deux chemins : project et library.

.kernelite va donc s'assurer que :

  • Le dossier existe
  • Qu'il est accessible en lecture
  • Qu'il est accessible en écriture (si [readOnly] non déclaré ou false)
Dans votre projet, vous pouvez à tout moment récupérer votre chemin grace à la super globale : myDir().

Dans l'exemple :
<?php echo myDir('library');?> affichera : C:\Utilisateurs\Me\Library

Mise à jour

Il existe deux facons de mettre à jour votre version de .kernelite.

1ère façon : En ligne de commande ( >= v1.9 )

S'il existe une version plus récente de .kernelite, en ouvrant une invite de commande, la mise à jour se fera automatiquement sans écraser vos fichiers de projets. Seuls les fichiers systèmes de .kernelite seront mit à jour.


    php index.php --update

2nde façon : Manuellement

Commencez par faire un backup de votre projet.
Téléchargez la dernière version disponible, puis décompressez là manuellement dans un dossier.
Ensuite, remplacez les dossiers systèmes par ceux de la nouvelle version :

  • .kernelite/
  • assets/ (attention à vos style.css & app.js à la racine !)
  • .htaccess
  • index.php

Créer des fichiers de conf.

Dans .kernelite, vous pouvez créer vos propres fichiers de configuration/variables en Yaml.
Pour cela, il suffit de placer votre fichier Yaml dans le dossier .conf.
Puis dans votre controller, il faudra utiliser la fonction getConf(<nom du fichier>)

Exemple fichier conf personnalisé :

var 
    www
        monprojet
            .conf
                [...]
                variables.yaml 
            .kernelite
            .structures
            assets
            controllers
            templates
            .htaccess
            index.php
            ...


Contenu exemple d'un fichier variables.yaml :

api :
    auth:
        prod : 
            user : apiUser001
            token : 7WK5T79u5mIzjIX...
        dev :
            user : apiUser001_dev
            token : i2oI9Fglmgivv7R...
    domains :
        product :
            url : https://monsite.com/products/api
            auth : true
        users :
            url : https://users.monsite.com/products/api
            auth : false                           
 
colors :
    [...]



Exemple de récupréation de la conf :

# ./controllers/ExempleController.php

class Exemple extends Controller {

    public function getAuth( $env = "dev" ) {

        # Pas besoin de l'extention ".yaml"
        $api = getConf('variables')['api'];
        return $api['auth'][$env] ?? null;

    }

}


Premier pas avec .kernelite

Vous avez terminé l'installation et la configuration de votre projet, vous êtes désormais prêt à faire vos premiers pas avec .kernelite.

Principes de base

Avant toute chose, il faut bien comprendre le schéma de fonctionnement de .kernelite. Le cycle de vie d'une requète kernelite passe par : une route, un controller puis un template.

Qu'est ce qu'une route ?

Lorsque d'un client fait un appel au serveur, que ce soit un appel classique pour afficher la page d'accueil de votre application ou un appel API, vous vous devez d'orienter l'appel du client vers la bonne méthode de votre application afin de répondre précisement à la requète.
Basiquement, une route c'est une liaison entre une URL et une méthode de votre application.

Voici quelques exemples d'utilisation d'une route :

  • URL "/" doit renvoyer l'affichage de la page d'accueil
  • URL "/User/18" doit renvoyer l'affichage du profil de l'utilisateur 18
  • URL "/User/Edit/18" attend des parametres pour mettre à jour l'utilisateur 18

Qu'est-ce qu'un controller ?

C'est la méthode de votre application qui sera appelé par la route qui correspond à l'URL envoyé par le client.
Un controller peut attendre des paramètres spécifiques ou aucun paramètre en fonction de la situation.
La valeur de retour d'un controller dépend aussi du cas d'utilisation. Dans le cas d'une API, un objet JSON peut être retourné par exemple, dans le cas d'un appel classique, un template peut être retourné.

Qu'est-ce qu'un template ?

Si vous souhaitez que votre controller retourne du HTML au client (dans le cas de l'affichage d'une page) de votre application par exemple, vous pouvez appeler l'un de vos template.
Afin de conserver au maximum un code propre, il est important d'utiliser les templates pour gérer l'affichage du HTML plutôt que gérer ca directement dans un controller.

Premiers fichiers

Lorsque vous intallez et configurez .kernelite, certains fichiers sont déjà en place afin d'afficher la page d'accueil de kernelite.
Afin de débuter votre projet, vous pouvez supprimer ces fichiers :

Liste des fichiers à supprimer :
  • routes/routes.yaml : Fichier de routes qui contient la route par défaut de la page d'accueil
  • controllers/DemoController.php : Le controller qui permet gere l'affichage de la page d'accueil de .kernelite
  • templates/demo : Le dossier de template qui contient le HTML de l'accueil de .kernelite
  • assets/css/templates/demo.css : Feuillez de style de l'accueil de .kernelite

Arborescence d'un projet

Voici une exemplication brève sur l'arborescence par défaut des dossiers à la racine d'un projet .kernelite

./conf Dossier de configuration du projet .kernelite
./kernelite Fichiers de fonctionnement du framework .kernelite (vous ne devriez pas avoir besoin d'y toucher)
./structures Contient vos structures .kernelite et les données initiales dans le sous dossiers ./structures/datas
./assets Contient tous les fichiers sucéptibles d'être délivrés au client : feuilles de styles, javascripts, images...
./controllers Contient la liste de vos controlleurs d'application
./routes Contient toutes les routes de vos applications
./services Contient la liste de vos services (classes secondaires n'étant pas des controlleurs)
./templates Contient vos templates de base ainsi que vos templates de controllers
./.htaccess Le fichier de configuration du virtualhost contenant la réécriture d'URL
./index.php Le fichier racine du projet qui iitialise .kernelite

Les routes

Les routes permettent d'aguiller les requetes du client vers les bonnes méthodes de votre application.

Fichiers de routes

Toutes les routes que vous écrirez pour votre application devront être écrites dans un fichier au format Yaml. Ce format permet de décrire très facilement le routage.
Vous pouvez créer autant de fichier Yaml que vous le souhaitez dans le dossier route.

Exemple de dossier ./routes :
        
            ./routes 
                routes.yaml
        
    
Segmantation logique :

La logique veut que vous segmentiez vos routes en plusieurs fichiers. Cela permet de retrouver facillement une route quand vous la recherchez.

Exemple de dossier ./routes bien segmenté :
        
            ./routes 
                index.yaml
                administration.yaml
                user.yaml
                blog.yaml
                gallery.yaml
                ...
        
    

Déclarer une route

Une fois que vous avez créé votre fichier de route (ex: routes.yaml) dans le dossier ./routes à la racine du projet .kernelite, voici comment déclarer à minima une route en Yaml.


    maroute :
        url : /maroute
        controller : Foo::bar        


Decription des lignes du fichier :
  • maroute (ligne 1) : Le nom de votre route en camelCase
  • url : /maroute (ligne 2) : Le matching d'url de votre route
  • controller : Foo::bar (ligne 3) Le controlleur qu'appellera votre route
Le nom d'une route :

Le nom d'une route devra être unique (parmis toutes les routes de votre application).
Par exemple, il ne peut pas y avoir deux routes nommées "index" dans vos fichiers de routes, peut importe que les parametres soient différents.

A quoi sert le nom d'une route ?

Le nom d'une route pourra être appelé depuis un template afin de récupérer l'URL d'une route à placer dans une balise lien.
Le nom d'une route sera aussi utilisé dans vos controllers afin de faire des redirections.

Options de déclaration

Dans l'exemple précédent, on a vu qu'il était possible de déclarer les parametres "url" et "controller" pour une route. Mais il existe plein d'autres paramètres qui permettent à vos routes de mieux cibler les requetes et sécuriser l'appel de vos controllers.

Liste des paramètres possibles lors de la déclaration d'une route :
Paramètre Valeur Défaut Description
url string obligatoire URL de matching de votre route
controller string obligatoire Le controller appelé par votre route sous la forme : Controller::methode
default boolean false Route par défaut de votre application (unique)
api boolean false Si true, cette route ne pourra être appelé qu'en API. Si false, cette route ne pourra pas être appelé en API. Si non définit, la route pourra être appelé en API ou non.
security string Le profil de sécurité du client pour accéder à la route (voir : Sécriser les routes)
securityRedirect string default route Redirection du client en cas de non respet de la règle de sécurité
params array null Liste des paramètres POST obligatoires pour l'appel de cette route (voir : Route & Paramètres)
infos array null Métadonnées supplémentaires que vous souhaitez ajouter à votre route (pour traitement futur)

Route & Paramètres

Vous aurez surement besoin d'envoyer des parametres lors de l'appel de certaines routes. Nottement lors d'un appel API.
Pour cela, vous pouvez définir dans votre route la liste des paramètres obligatoires que vous attendez de la part du client afin de procéder à l'appel du controller.

Exemple concret :

Vous avez un controller qui à jour l'age d'un utilisateur. Votre controller attendra alors un age en parametre afin de procéder à la sauvegarde de l'information. Cependant, dans un cas classique, vous devriez dans votre controller tester si le parametre age existe dans le POST/GET envoyé par le client. Puis vous devrez tester son type (int/string/array/...)
Grace à .kernelite, vous pouvez vous abstenir de toutes ces étapes en déclarant dans votre route le fait que vous attendez un parametre age de type INT.

Liste des paramètres possibles lors de la déclaration de l'option params d'une route :
Paramètre Valeur Défaut Description
nom du parametre string obligatoire Peut valoir : int, string, boolean, array, date
Exemple de route avec parametres

    maroute :
        url : /maroute
        controller : Foo::bar 
        params:
            id : int
            age : int
            nom : string
            prenom : string       


Dans cet exemple, si le client appelle l'URL "/maroute" et que sont appel ne contient pas les 4 paramètres attendus ou que les types de concordent pas, alors une erreur sera déclanchée.

Routes par annotation

Si vous avez bien saisit le concept de routes .kernelite, les routes par annotation vous feront gagner un temps fou.
Terminé les fichiers route.yaml grace aux annotations PHP : déclarez vos routes à la volée en même temps que vos méthodes de controller.

Pour cela, il vous faudra vous familiariser avec l'écriture JSON de vos routes
et les déclarer juste au dessus de votre méthode en commencant par : # @Route = {...}

Attention

L'annotation doit être collée juste au dessus de la déclaration de votre méthode.

Exemple de route "Mon Compte"

    myAccount :
        url : /MonCompte
        controller : User::myAccount
        security : connected       


Equivalent par annotation :

    # ./controllers/UserController.php
    
    class User extends Controller {
        
        # @Route = { "name" : "myAccount", "url" : "/MonCompte", "security" : "connected" }
        public function myAccount() {
            return $this->render();
        }

    }


Les paramètres des routes par annotation sont exactement les mêmes que pour les routes classiques. Les routes classiques au format YAML et les routes par annotation peuvent tout à fait coéxister.
Cepepdant, si vous souhaitez n'utiliser que les routes par annotation, alors il n'est plus necessaire de créer de fichiers de routes au format YAML.

Astuce

Si vous ne précisez pas l'attribut "name" d'une route par annotation, alors la route prendra automatiquement le nom de la méthode qu'elle décrit.

Exemple de route par annotation minimale

    # ./controllers/UserController.php
    
    class User extends Controller {
        
        # @Route = { "url" : "/Blog" }
        public function showBlog() {
            return $this->render();
        }

    }


Sécuriser les routes

Vous allez surement devoir vous assurer qu'à certains moments, le client soit par exemple identifié avant d'appeler une route spécifique, ou qu'il ait les droits necessaires afin de mener une action.
Grace à l'option security des routes, vous pourrez définir les profils de sécurité relatifs à l'accès de vos routes.

Qu'est ce qu'un profil de sécurité ?

Les profils de sécurité dans .kernelite sont relatifs au Logger.
Le Logger est le composant qui gère la sécurité dans le framework.
Il vous permet nottement de définir des profils clients en fonction des paramètres que vous souhaitez.

Pour plus d'informations, rendez-vous dans la séction "Logger" de la documentation.

Application des règles de sécurité

Par défaut, vos routes ne sont pas sécurisées. Cela veut dire que n'importe quel client peut appeler votre route et executer votre controller.
Afin d'appliquer une règle de sécurité, il vous suffit de déclarer l'option security et de lui mettre en valeur le profil de sécurité souhaité que doit respecter le client. Si le client ne respecte pas ce profil de sécurité, alors il ne pourra pas accéder à cette route.

Exemple d'application de la sécurité

Pour cet exmeple, nous partirons du principe qu'il existe un profil de sécurité connected qui correspond simplement au fait que notre client est connecté avec un compte sur notre application.
Nous allons donc créer une route qui permettra à notre client de se rendre sur l'espace "Mon Compte".

Exemple de route "Mon Compte"

    myAccount :
        url : /MonCompte
        controller : User::myAccount
        security : connected       


Dans notre exemple, si le client n'est pas connecté, alors l'accès à la route ne lui sera pas accordé.

Redirections de sécurité

Ce n'est pas parcequ'il n'a pas accès qu'il faut forcement renvoyer notre client sur l'accueil de l'application.
Dans le cadre d'un non respect d'une règle de sécurité de route, il vous est possible de rediriger votre client sur une route spécifique.
Pour cela, vous devrez déclarer le paramètre securityRedirect et lui donner en valeur le nom d'une route existante de votre application.

Dans notre exemple ci-dessus, il serait judicieux de renvoyer notre client sur la page de connexion si celui-ci n'est pas connecté.

Exemple de redirection de sécurité :

    myAccount :
        url : /MonCompte
        controller : User::myAccount
        security : connected  
        securityRedirect : login 
        
    login :
        url : /Connexion
        controller : User::connexion      


Attention

Assurez-vous bien que la route de redirection existe et prenez-garde aux boucles infinies de refirections !

Sécuriser avec le Firewall

Le firewall .kernelite agit en amont des règles de sécurité des routes. Il permet d'appliquer des règles de sécurité sur des schémas de routes. Vous trouverez la définition du firewall dans : .conf/firewall.yaml
Grace au firewall, vous pouvez gérer la sécurité d'une grande majorité des URL de votre application.

Exemple de route "Mon Compte" sans firewall

    myAccount :
        url : /MonCompte
        controller : User::myAccount
        security : connected       
        securityRedirect : index


Cette route a sa propre sécurité (définie avec "security"),
donc le firewall ne s'appliquera pas sur cette route.

Policies

Les Policies sont les règles de sécrutiré du firewall .kernelite et vous pouvez créer autant que necessaire.
Afin de déclarer une Policie, il faut déclarer ces champs :

match Le schéma d'URL à faire correspondre
rules Liste des profils de sécurité (séparés par une virgule) à vérifier
redirect Nom de la route de redirection si la vérification échoue (si policiesRedirection : true)
Exemple de déclaration de policies

    firewall :
        enable : true
        
        redirection :
            enableRedirection : true
            policiesRedirection : true

        policies :
            - 
            match : *
            rules : connected
            redirect : login
            -
            match : /Administration
            rules : admin 
            -
            match : /Membre
            rules : connected,membre
            redirect : home


Exemples d'URL soumises à ce firewall :

/Administration/Users : si l'utilisateur n'a pas de profil "admin", il sera redirigé vers la route par défaut du projet

/Membre/12 : si l'utilisateur n'a pas de profil "membre" et "connected", il sera redirigé vers la route "home"

/foo : si l'utilisateur n'a pas de profil "connected", il sera redirigé vers la route "login" (match : *)

/Admin : si l'utilisateur n'a pas de profil "connected", il sera redirigé vers la route "login" (match : *)

Le match : *

Si vous assignez * comme valeur au match, cela se traduit par : n'importe quelle autre route qui ne match aucune des policies définies.

Les controllers

Les controllers sont le coeur de votre application. Ce sont les méthodes qui vont vous permettre de traiter les demandes de votre client au sein de votre application. Ils sont appelés par les routes, et retournent en général des templates ou des objets.

Le dossier ./controllers

Vous pouvez créer autant de controllers que vous le souhaitez. La convention étant de ségmenter vos controllers de la même manière que vous segmente vos routes et vos templates afin de faciliter la recherche.

Nommage et convention

Nous allons prendre l'exemple de la création d'un controller User.
Par convention, le controller commencera par une Majuscule et s'écrira en camelCase.
Le nom du fichier de notre controller devra se terminer par : ...Controller.php

Exemple de dossier ./controllers :

    ./controllers
        IndexController.php
        UserController.php
        AdminController.php
        BlogController.php
        ...  


Attention

.kernelite sait aussi detecter les fichiers qui n'ont pas Controller dans leur nom. Mais ce n'est pas conventionnel.
Cependant, vous pouvez très bien si vous le souhaitez ne pas rajouter Controller dans le nom du fichier.

Exemple de dossier ./controllers mal nommé (mais fonctionnel) :

    ./controllers
        Index.php
        User.php
        Admin.php
        Blog.php
        ...  


Déclarer un controller

Dans .kernelite, un controller est une classe PHP qui étends la classe principale Controller

Exemple de déclaration d'un controller User :

    # ./controllers/UserController.php
    
    class User extends Controller {
        ...
    }


Avertissement

Si votre controller n'étends pas la classe principale Controller, vous ne pourrez pas pleinnement profiter des atouts offerts par .kernelite dans la communication de vos controllers.

Relier une route

Lorsque le client réalise un appel au serveur, .kernelite va tenter de trouver la route qui correspond à son appel. Une fois la route trouvée, celle-ci va donc invoquer l'un de vos controllers.

Exemple de route "Mon Compte"

    myAccount :
        url : /MonCompte
        controller : User::myAccount    
          

Exemple de controller pour cette route :

    # ./controllers/UserController.php
    
    class User extends Controller {
        
        public function myAccount() {
            echo 'Hello .kernelite !';
        }

    }


Paramètres des méthodes

Les méthodes de vos controllers vont la plus part du temps avoir besoin de ressources exterieures afin de pouvoir s'executer correctement.

Voici quelques exemples de ressources externes à votre méthode :
  • Des paramètres de routes
  • La Request .kernelite
  • Le DataManager
  • Le Logger
  • Un service personnalisé
  • ...

Grace à .kernelite et à la puissance de la Reflexion des paramètres, il vous suffit de demander et vous êtes livrés !

Exemple de route avec des paramètres

    exemple :
        url : /exemple
        controller : Exemple::maMethode  
        params :
            id : int
            age : int
            prenom : string
            nom : string 
        

Exemple de controller attendant les paramètres de sa route :

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        
        public function maMethode( Int $id, Int $age, String $prenom, String $nom ) {
            # ...
        }

    }


Exemple de demande de paramètres à .kernelite :

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        
        public function maMethode( DataManager $dm, Logger $logger, Request $req, MonService $serv ) {
            # ...
        }

    }


Redirection de route

Vous pourriez avoir besoin dans votre controller de rediriger l'appel client vers une autre route. Prenons par exemple la création d'un compte utilisateur qui redirigerait vers la page de connexion.

Pour cela, la classe principale Controller dont hérite votre controller vous donne accès à la méthode : redirectToRoute() qui attend en paramètre le nom de la route ou vous souhaitez reidiriger l'appel.

Exemple de redirection de route :

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        
        public function maMethode() {
            
            if( ... )
                return $this->redirectToRoute("index");

        }

    }


Valeurs de retour

Votre controller doit pouvoir retourner une valeur. Que ce soit un template HTML, un objet ou bien même juste dire qu'il a terminé son rôle.

Retourner un template :

La classe principale Controller met à votre disposition la méthode render qui permet de retourner un template HTML dans lequel .kernelite aura injecté vos variables.

Liste des paramètres de la méthode render() :
Paramètre Valeur Défaut Description
path string obligatoire Chemin vers votre template dans le dossier "./templates" de .kernelite
params array [] Tableau de paramètres fourni au template
Exemple d'appel à render :

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        
        public function maMethode() {
            
            return $this->render( 'exemple/maPage',[
                ...
            ]);

        }

    }


Dans cet exemple, .kernelite apellera le fichier de template situé : ./templates/exemple/maPage.php et utilisera mustache afin d'interpoler votre tableau de paramètres avec les variables du template.

Astuce & Raccourcis de nommage

Par convention, les templates sont rangés dans un dossier du nom du controller et portent le nom de la méthode qui les appelles.
Par exemple : un fichier ./templates/user/myAccount.php fera référence à un controller User et sa méthode myAccount.
Dans ce cas là, plus besoin de nommer votre path car si vous travaillez dans un controller User sur la méthode myAccount, alors .kernelite tentera de trouver s'il existe un template qui correspond.

Exemple d'appel à render avec un template ./templates/user/myAccount.php :

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        
        public function maMethode() {
            
            return $this->render( '' ); 
            # Le path du template est vide car il n'est pas utile
            # de le préciser si la nommanclature est en harmonie entre le controller et le template
            # Par défaut : ./templates/user/myAccount.php sera invoqué si le path est vide

        }

    }


Retourner un objet pour une API :

La méthode render permet de retourner du code HTML à générer par le navigateur. Hors lors d'un appel API, nous souhaitons retourner des données brutes (souvent encodées en JSON).
Pour cela, il suffira d'effectuer un return contenant vos données.

Exemple de méthode retournant un objet pour une API :

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode() {
            return [ 'pomme', 'bannane', 'poire' ];
        }
    }


.kernelite sait lorsque vous êtes en API, alors votre objet sera automatiquement transformé en JSON et renvoyé.

Attention !

Lorsque vous ne renvoyez pas d'erreur, .kernelite ajoute à votre réponse JSON la clé success à true dans votre réponse.
Il est donc conseillé de créer un tableau sépcifique pour votre réponse.

Bonne pratique :

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode() {
            $reponse = [ 'pomme', 'bannane', 'poire' ];
            return [ "datas" => $reponse ];
        }
    }

    # Réponse au client 
    { datas : { 0: 'pomme', 1: 'bannane', 2: 'poire' }, success: true}



Méthodes Controller

La classe mère Controller vous fournis des utilitaires que vous pouvez utiliser.

render( string|array, [array], [array] )

Permet de retourner le template passé en argument (string) en réalisant l'interpollation du tableau de paramètre [array] si présent. (Voir : Controller => Valeur de retour, Templates => Paramètres fournis)

Astuce :

Il est possible d'envoyer vos paramètres directement à render, en ignorant le path si vous ne souhaitez pas le préciser.
Cela revient à faire : $this->render([datas]) (qui équivaut à : $this->render('',[datas]))

Le 3ème paramètre de render correspond aux options de template. Pour le moment, la seule options supportée est : plugins


    // ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function testRender() {
            return $this->render(
                '',
                [ datas ],
                [ "plugins" => [ fichiers plugins ] ]
            );
        }
    }

apiError( string )

La méthode apiError vous permet lors d'un appel API de retourner un message d'erreur au client qui saura être interpretté par kerneliteJS.


    // ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function testApiError() {
            $this->apiError("Ceci est une erreur");
        }
    }


    // ./assets/js/app.js
    function testApiError() {
        kernelite.api('/testApiError')
    }


    // ./routes/routes.yaml
    testApiError :
        url : "/testApiError"
        controller : "Exemple::testApiError"
        api : true

redirectToRoute( string )

Cette méthode vous permet de rediriger le client vers une autre route de votre choix. Elle attend en paramètre le nom de la nouvelle route.

Attention : Cette méthode ne fonctionne pas en mode API
route( string )

Retourne l'URL d'une route dont vous avez passé le nom en paramètre

getImgLink( string )

Retourne l'URL d'une image placé dans le dossier ./assets/img/

getParams( ?string )

Depuis un template : retourne un tableau contenant les paramètres de templates passé à la méthode render().
Si le paramètre string est fournit, seul le paramètre à cette clé (si existante) sera retourné.

getLastURIParam()

Retourne le dernier paramètre de l'URL, par exemple : mondomaine.fr/projet/mapage => "mapage"

getURIParam( int )

Retourne le nieme paramètre de l'URL

getSlug()

Retourne le dernier paramètre au format int de l'URL , par exemple : mondomaine.fr/user/15 => 15

La Request

.kernelite met à votre disposition un objet qui contient tous les détails de la requete du client ainsi que son contexte et une partie de sa résolution.
Ainsi, vous pouvez demander à vous faire fournir la Request dans les paramètres de vos controllers.


    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( Request $req ) {
            d($req); # Utilisation de la super globale d()
        }
    }

IndexController.php - ligne 149

Kernelite→processQuery ► Kernelite→processCall ► Index→home ► Index→getChapter ► include

<?php
 object
(Request)#6 (8) {
  
["request":"Request":private]=>
  array(
7) {
    [
"queryString"]=>
    array(
5) {
      [
"raw"]=>
      
string(36"QUERY_STRING=index.php&QUERY_STRING="
      
["value"]=>
      
string(0""
      
["empty"]=>
      
bool(true)
      [
"splited"]=>
      array(
1) {
        [
0]=>
        
string(0""
      
}
      [
"parsed"]=>
      array(
1) {
        [
0]=>
        
string(0""
      
}
    }
    [
"files"]=>
    array(
0) {
    }
    [
"api"]=>
    
bool(false)
    [
"session"]=>
    array(
0) {
    }
    [
"route"]=>
    array(
3) {
      [
"url"]=>
      
string(1"/"
      
["controller"]=>
      
string(11"Index::home"
      
["default"]=>
      
bool(true)
    }
    [
"input"]=>
    array(
0) {
    }
    [
"post"]=>
    array(
0) {
    }
  }
  [
"queryString"]=>
  array(
5) {
    [
"raw"]=>
    
string(36"QUERY_STRING=index.php&QUERY_STRING="
    
["value"]=>
    
string(0""
    
["empty"]=>
    
bool(true)
    [
"splited"]=>
    array(
1) {
      [
0]=>
      
string(0""
    
}
    [
"parsed"]=>
    array(
1) {
      [
0]=>
      
string(0""
    
}
  }
  [
"files"]=>
  array(
0) {
  }
  [
"api"]=>
  
bool(false)
  [
"session"]=>
  array(
0) {
  }
  [
"route"]=>
  array(
3) {
    [
"url"]=>
    
string(1"/"
    
["controller"]=>
    
string(11"Index::home"
    
["default"]=>
    
bool(true)
  }
  [
"input"]=>
  array(
0) {
  }
  [
"post"]=>
  array(
0) {
  }
}
?>

Le Post

.kernelite met à votre disposition un objet Post qui contient toutes les variables envoyés via POST.
Les clés sont transformées en propriétés de classes.


    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( Post $p ) {           
            if( $p->id < 1 )
                err("Aucun id reçu"); // Si le clé $_POST['id'] est inferieure à 1, alors erreur
            return [ "prenom" => $p->prenom ];
        }
    }

Transformation du Post

Vous pouvez à tout moment modifier la valeur des variable de classe du POST et l'obtenir au format Array graca à la méthode toArray()


    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( Post $p, DataManager $dm ) {           
            $p->id = 12;
            if( $p->prenom == "Michel" ) $p->prenom = "Jean";
            $dm->create('user', $p->toArray() )
        }
    }

Créer un Post

Si vous souhaitez créer votre propre objet Post, il est possible de le faire en lui fournissant un tableau associatif lors de son initialisation :


    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode() {           
            $u = new Post([
                "prenom" => "Jean",
                "nom" => "Michel",
                "age" => 12
            ]);
            $u->age = 15;
            return $u->toArray();
        }
    }

Les assets de Controller

Lorsque d'une utilisation de render() on génère une page HTML avec l'aide du template de la méthode de notre Controller.
Chaque page peut avoir besoin de fichiers CSS ou JS qui lui sont dédiés.

Pour utiliser le chargement automatique des assets, il faudra bien veiller à appeller les fonctions
__kernel_load_styles et __kernel_load_scripts dans votre base template (Elles sont présentes par défaut).

Avec .kernelite, il existe plusieurs manières de joindre du CSS ou JS dans sa page :

→ De manière globale (déconseillé)

A la racine de vos dossiers ./assets/js et ./assets/css vous pouvez placer ou utiliser un fichier.
Par exemple : ./assets/js/function.js ou ./assets/css/style.css.
Le problème c'est ces fichiers seront automatiquement appelés sur la totalités des méthodes de vos Controllers.
Ces fichiers peuvent être utiles pour appliquer des styles globaux (resets par exemple) ou des fonctions JS transverses de votre application.

→ Au Controller

A la racine de vos dossiers ./assets/js et ./assets/css il existe un dossier templates.
Si vous créez un fichier du nom exacte de votre Controller à l'interrieur, celui-ci sera automatiquement injectés dans vos pages pour toutes les méthodes de ce controller faisant appel à render()

Par exemple, si j'ai un Controller "AdminController", je peux créer ./assets/js/templates/admin.js
Ce fichier sera donc inclus dans toutes les pages générées par les méthodes de mon AdminController.

→ A la méthode de Controller

A la racine de vos dossiers ./assets/js/templates/ et ./assets/css/templates/ il est possible de créer un dossier portant le nom de votre Controller et d'y placer des fichiers només exactement comme vos méthodes afin que ceux-ci ne soient invoqués que lorsque la méthode de ce Controller utilise render().

Par exemple, si j'ai une méthode "pageAccueil" dans un Controller "AdminController", je peux créer ./assets/js/templates/admin/pageaccueil.js
Ce fichier sera donc inclus uniquement lors de l'appel render() de ma méthode "pageaccueil" mon AdminController.

→ A l'unité

Vous pouvez charger un fichier de manière unitaire grace à la fonction template {% asset() %} (voir la section "Fonctions templates")

Les templates

Les templates sont les pages HTML ou leurs fragments que vous allez renvoyer à votre client.

Présentation

Les templates de .kernelite sont rangés dans le dossier templates à la racine de votre projet.
Il éxiste deux types de templates :

  • Les templates de base
  • Les templates de controller

Pour faire simple, les templates de bases sont l'habillage général du site (logo, menus, structure de la page... ) alors que les templates de controller sont le coeur de la page qui a été demandé par le client. Un template de base est fait pour accueillir dans sont body un template de controller.

Exemple de template de base minimaliste :

    <!DOCTYPE html>
    <html lang="fr">
        <head>
            <title>Mon app</title>
        </head>
        <body>
            {%CONTROLLER%}
        </body>
    </html>


Exemple de template de controller minimaliste :

    <h1>Bienvenue sur ma page</h1>
    <p>Ceci est le contenu de ma page...</p>


{%CONTROLLER%}, c'est quoi ?

C'est une instruction spéciale à placer de manière unique template de base afin que .kernelite place le template du controller. (Voir : Template de base)

Pourquoi 2 templates (base/controller) et pas un seul ?

Lors du développement d'une application, c'est souvent le corps de la page qui change et non pas l'intégralité du site. C'est pourquoi il est plus aisé de ne pas avoir besoin de réécrire pour chaque méthode de controller l'intégralité de la structure du site. C'est donc pour cela qu'on aura généralement une base qui sera utilisé par une multitude de controller.

Peut-on avoir plusieurs bases ?

Le plus souvent vous aurez au minimum deux templates de base. Un pour le front de votre application et autre pour le back. .kernlite vous permet d'avoir autant de bases que vous le souhaitez.

Template de base

Par défaut, quand vous installez .kernelite, il existe déjà un template de base nommé base.template.php. Vous pouvez modifier celui-ci ou le supprimer pour créer vos propres templates de base.

Emplacement

Les templates de bese doivent obligatoirement se situer à la racine du dossier ./templates de votre projet. Si vous avez plusieurs templates de base, ils seront donc tous placé dans ce dossier de la manière suivante :


            monprojet
                .conf
                .kernelite
                .structures
                assets
                controllers
                routes
                services
                templates
                    base.template.php
                    admin.template.php
                    blog.template.php
                    ...
                .htaccess
                index.php

        
Nomenclature

Par convention dans .kernelite, un template de base se nomme [nom].template.php. Le [nom] désignant un terme représentatif de la partie de l'application ciblé.
Par exemple :

  • base.template.php désignera l'habillage par défaut de l'application
  • admin.template.php désignera la partie administration
  • blog.template.php désignera la partie blog (si le site à un visuel différent pour cette partie)
  • ...
Contenu du fichier

Voici un exemple de template de base .kernelite :

1:  <!DOCTYPE html>
2:  <html lang="fr">
3:      <head>
4:          <title>Documentation Kernelite v2.0</title>
5:          <?php
6:              __kernel_load_styles( $this ); #, ["framework"=>false,"default"=>false] );
7:              __kernel_load_scripts( $this ); #, ["framework"=>false,"default"=>false] );
8:          ?>
9:      </head>
10:     <body>    
11:         {%CONTROLLER%}
12:     </body>
13: </html>

Description des lignes spécfiques :

Ligne Description
5-8 Ces deux méthodes PHP sont des super globales définies par .kernelite. Elles servent à charger toutes les assets (ceux de .kernelite, et ceux de vos controllers). Voir : Les super globales
11 Ceci est une instruction particulière qui vous permettra de dire à .kernelite que lorsque ce template de base est appelé, c'est à cet endroit que devra être injecté le template du controller qui à appelé cette base.

Changer de base

Maintenant que l'on sait créer des templates de base, il est important de voir comment les séléctionner dans nos controllers. Par défaut, si rien n'est précisé, .kernelite tentera de charger base.template.php si celui-ci existe.

Paramètre de template

Dans un controller, quand on fait appel à render(), on a vu qu'il était possible de préciser un tableau de paramètre en plus du nom du template du controller. C'est précisement dans ce tableau de paramètre que l'on va pouvoir préciser si l'on souhaite appeler un autre template que celui de base.

Exemple de changement de template de base :

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode() {
            $this->render( 'montemplate', [
                "base" => "admin.template"
            ]);
        }
    }

Appliquer une même base à tout un controller

Il est possible d'appliquer une même base pour toutes les méthodes d'un controller en déclarant la variable statique de votre controller : $baseTemplate

Exemple de changement de template de base :

    # ./controllers/AdministrationController.php
    class Administration extends Controller {

        public static $baseTemplate = 'admin';

        public function maMethode() {
            $this->render( 'montemplate', [
                ... # Pas besoin de préciser la base "admin", $baseTemplate du controller sera utilisé
            ]);
        }
    }

Template de controller

Tout controller est sucéptible de renvoyer son propre template. Par exemple, le controller de votre page d'accueil renvera le template de la page d'accueil, et de la même façon pour toutes les pages et fragments de votre application.
Il est donc important de bien ranger vos templates de controller de façon ordonnée afin de ne pas se retrouver avec des dizaines de templates au sein d'un même dossier.

Emplacement des templates d'un controller

Par convention de .kernelite, lorsque l'on créer un controller, il convient de créer un sous-dossier dans ./templates du nom du controller afin d'y ranger ses templates et de les retrouver facillement.

Exemple :
  • Etape 1 : création d'un controller "User" : ./controllers/UserController.php
  • Etape 2 : création de son dossier de templates : ./templates/user/
Nommenclature du template de controller

Votre controller étant composé de méthodes, et ces méthodes étant uniques, il convient de nommer votre template de part le nom de la méthode qui l'invoque.

Exemple de controller :

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode() {
            $this->render('exemple/maMethode');
        }
    }

Exemple de fichier template pour ce controller :

    ./templates
        ./exemple
            maMethode.php

        base.template.php
        ...

Le paramètre "template" de render()

Le premier argument de la méthode render() est le template de votre controller. Ainsi, dans l'exemple ci-dessus, on constate que .kernelite va aller chercher le fichier de template ./templates/exemple/maMethode.php.
Lors de l'appel à render(), il est inutile de préciser le dossier ./templates ni l'extension .php. Seul le nom du dossier et du template suffisent à .kernelite afin de charger votre fichier.

Astuce et bonne pratique

Vous avez tout à gagner en respectant les bonnes pratiques.
En effet, si le nom du dossier de template et le nom de votre template correspondent au noms de votre controller et méthode, .kernelite ira les chercher sans que vous ayez besoin de les lui préciser.

Par exemple, ceci est un appel valide à render() :

Exemple de controller :

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode() {
            $this->render('');
        }
    }

Exemple de fichier template pour ce controller :

    ./templates
        ./exemple
            maMethode.php

Paramètres fournis

.kernelite fourni de base un certain nombres de paramètres par défaut à votre template lors de son appel. Les paramètres que vous donnerez à render() depuis vos controllers seront alors ajoutés aux paramètres par défaut déjà existants.

Liste des paramètres par défaut des templates
  • title : le nom du controller qui a été invoqué
  • project_url : URL de votre projet
  • favicon : un lien vers le favicon par défaut ./assets/img/favicon.ico
  • logo : un lien vers le logo par défaut de votre application assets/img/logo.jpg
  • isConnected : Boolean du Logger
  • logoutRoute : lien vers la méthode de deconnexion du logger
  • user : si connecté, contient la ligne de l'utilisateur
  • rules : liste des profils de sécurité et leur valeur de matching avec l'utilisateur courant

Surcouchage

Vous pouvez surcoucher les paramètres par défaut en les déclarant dans votre controlleur.

Accès aux $kParams

A tout moment dans vos templates, vous pouvez ouvrir les balises PHP et accéder à la variable $kParams qui contient la totalité des paramètres fournis à votre template : les paramètres par défaut du template ainsi que ceux que vous avez fourni en second paramètre de la méthode render().

Dump le contenu des $kParams accessibles dans votre template :

    <!-- Template : ./templates/exemple/maMethode.php -->
    <div class="container mt-5">
        <php d( $kParams ); ?>
    </div>

{{ Mustache }}

.kernelite se base sur le moteur de templating mustache.
Voici le lien vers la documentation officielle : https://mustache.github.io/mustache.5.html

Vous pouvez utiliser mustache dans tous les templates (base & controller).

Afficher les parametres transmis à render() :
Exemple de controller :

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode() {
            $this->render('exemple/maMethode',[
                "title" => "Titre ma page",
                "message" => "Bienvenue chez Exemple::maMethode !",
                "contenu" => "<p>...</p>" 
            ]);
        }
    }

Exemple de fichier template pour ce controller :

    <!-- Template : ./templates/exemple/maMethode.php -->
    <div class="container mt-5">
        <h1>{{ message }}</h1>
        <div class="page-body">
            {{{ contenu }}}
        </div>
    </div>

  • {{ var }} double moustache : html non interpreté
  • {{{ var }}} triple moustache : html interpreté
Faire des conditions :
Exemple de controller :

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode() {
            $this->render('exemple/maMethode',[
                "statut" => methodeQuiRenvoieTrueOuFalse(),
                "msgTrue" => "ok",
                "msgFalse" => "ko"
            ]);
        }
    }

Exemple de fichier template pour ce controller :

    <!-- Template : ./templates/exemple/maMethode.php -->
    <div class="container mt-5">
        <p>
        {{ #statut }}
            {{ msgTrue }}
        {{ /statut }}
        {{ ^statut }}
            {{ msgFalse }}
        {{ /statut }}        
        </p>
    </div>

  • {{ #var }}...{{ /var }} Si var est vrai, alors executer ...
  • {{ ^var }}...{{ /var }} Si var est faux, alors executer ...
Boucler sur un tabeau :
Exemple de controller :

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode() {
            $this->render('exemple/maMethode',[
                "tableau" => [1,2,3,4,5]
            ]);
        }
    }

Exemple de fichier template pour ce controller :

    <!-- Template : ./templates/exemple/maMethode.php -->
    <div class="container mt-5">
        <p>
        {{ #tableau }}
            {{ . }} <br/>
        {{ /tableau }}
        {{ ^tableau }}
            Tableau vide
        {{ /tableau }}        
        </p>
    </div>

  • {{ #var }}...{{ /var }} Boucle sur chaque élément
  • {{ . }} Affiche la valeur courante
  • {{ ^var }}...{{ /var }} Si le tableau est vide
Valeur associative :
Exemple de controller :

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode() {
            $this->render('exemple/maMethode',[
                "user" => [
                    "prenom" => "Jean",
                    "nom" => "Dupont"
                ]
            ]);
        }
    }

Exemple de fichier template pour ce controller :

    <!-- Template : ./templates/exemple/maMethode.php -->
    <div class="container mt-5">
        <p>
        {{ #user }}
            {{ prenom }} {{ nom }} <br/>
        {{ /tableau }}       
        </p>
    </div>

Fonctions templates

.kernelite met a votre disposition quelques fonctions pratiques supplémentaires à utiliser dans vos templates. Ces fonctions s'écrivent dans vos templates sous cette forme : {% fonction(args) %}

Attention !

Les arguments [args] ne doivent surtout pas contenir de parenthèses sous peine de faire crasher la fonction template.
route() : Afficher un lien vers une route

Une fois votre route décrite dans son fichier Yaml, il convient de ne plus avoir à saisir son URL nul part ailleurs. En effet, il existe des méthodes .kernelite qui vous permettent d'obtenir l'URL d'une route en passant par son nom.

Exemple de route :

    login:
        url : "/Connexion"
        controller : "Security::authentification"

Faire un lien vers cette route dans un template

    <a href="{% route(login) %}">Aller à la page de connexion</a>

Ou bien, en PHP grace aux super globales .kernelite :

    <a href="<?php route('login');?>">Aller à la page de connexion</a>

Ou bien, en PHP grace à la classe principale Controller :

    <a href="<?php echo $this->route('login');?>">Aller à la page de connexion</a>

form() & form_widget() : Génération automatique de formulaires à partir d'une structure .kernelite

Il est possible de générer un seul élément ou la totalité d'un formulaire depuis une structure .kernelite. Pour cela, vous avez accès aux fonctions templates form(structure) et form_widget(structure,champ). Pour plus d'informations, voir : Structures .kernelite : Formulaires automatiques

get() : Obtenir une donnée en base sans passer par les parametres de template

Dans le cas ou un template est utilisé par plusieurs controllers (un template de base par exemple), il est possible que celui-ci doivent afficher une données provenant de la base de données. Pour éviter d'avoir à récupérer cette donnée dans chaque controller à l'utilisation du template, .kernelite met à disposition la fonction template get. Celle-ci vous permet d'aller récupérer une donnée précise en base directement depuis un template.

Parmètres de la fonction template get()
Paramètre Valeur Défaut Description
structure string obligatoire Structure ou table de la donnée
id int obligatoire Identifiant de la ligne de la donnée
champ string libelle Nom du champ de la ligne de donnée à retourner
Exemples d'appel à get()

    <span>{% get(user, {{ user.id }} ,prenom) %}</span>
    <span>{% get(params, 3 ,value) %}</span>
    <span>{% get(marque, 5) %}</span>
    
options() : Liste d'option depuis une structure

Dans le cas où vous auriez besoin d'une liste d'options basiques (id=>libelle) pour un select, vous pouvez faire appeler à la méthode options() qui prend en argument le nom d'une structure.
Il faudra impérativement que votre structure possède les champs id et libelle pour que cela fonctionne.
Cette fonction est dépréciée.

table() : Génère une table HTML à partir d'un jeu de données

En fournissant à la méthode render() une table multi-dimensionelle, il est possible grace à la fonction de template table() de générer un tableau HTML automatiquement.

Parmètres de la fonction template table()
Paramètre Valeur Défaut Description
datas string obligatoire Nom d'une table de données fournie en paramètre de la méthode render()
id string vide Attribut #id de la table générée
headers string headers de datas Nom d'une table de données fournie en paramètre de la méthode render()
Exemple de basique d'utilisation de table() :
Exemple de controller :

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode() {
            $this->render('exemple/maMethode',[
                "mesUtilisateurs" => [
                    [
                        "prenom_user" => "Jean",
                        "nom_user" => "Dupont",
                        "age_user" => 20
                    ],
                    [
                        "prenom_user" => "Pierre",
                        "nom_user" => "Dulac",
                        "age_user" => 30
                    ],
                ]
            ]);
        }
    }

Exemple de fichier template pour ce controller :

    <!-- Template : ./templates/exemple/maMethode.php -->
    <div class="container">
        {% table( mesUtilisateurs ) %}
    </div>

Affichage de la table :

prenom_user nom_user age_user
Jean Dupont 20
Pierre Dulac 30
Exemple de génération de table avec ID et Headers :
Exemple de controller :

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode() {
            $this->render('exemple/maMethode',[
                "mesUtilisateurs" => [
                    [
                        "prenom_user" => "Jean",
                        "nom_user" => "Dupont",
                        "age_user" => 20
                    ],
                    [
                        "prenom_user" => "Pierre",
                        "nom_user" => "Dulac",
                        "age_user" => 30
                    ],
                ],
                "mesHeaders" => [ "Prénom", "Nom", "Age" ]
            ]);
        }
    }

Exemple de fichier template pour ce controller :

    <!-- Template : ./templates/exemple/maMethode.php -->
    <div class="container">
        {% table( mesUtilisateurs, monTableau, mesHeaders ) %}
    </div>

Affichage de la table : #monTableau

Prénom Nom Age
Jean Dupont 20
Pierre Dulac 30
btn() : Génère un bouton avec ses paramètres

Une fonction simple de génération de boutton. Il est possible de lui passer en paramètres un ID, une ou plusieurs classes ainsi que des attributs.

Parmètres de la fonction template btn()
Paramètre Valeur Défaut Description
libelle string obligatoire Libellé affiché sur le bouton
id string vide Attribut #id du bouton
classes string btn-success Attribut .class du bouton ajouté à "btn"
attributes string vide Attributs supplémentaires à ajouter au bouton
date_fr() : Affiche une date au format français

Prend en argument une date au format YYYY-MM-DD (HH:II:SS) et l'affiche au format DD/MM/YYYY (à HHhIIm)

Exemple d'utilisation de date_fr() :
        
            <!-- Template : ./templates/exemple/maMethode.php -->
            <div class="container">
                {{date_creation}}<br/>
                {% date_fr( {{date_creation}} ) %}
            </div>

        
2023-01-26 14:41:13
23/01/2023 à 14h41
asset() : retourne l'URL d'un asset

Cette fonction sert à obtenir le lien direct d'un fichier de votre dossier ./assets dans votre template

Exemple d'utilisation de asset() :

            <!-- Template : ./templates/exemple/maMethode.php -->
            <div class="container">
                <img src="{% asset( img/user.jpg ) %}" />
                <script src="{% asset( js/dir/user.js ) %}" />
                <link href="{% asset( css/dir/user.css ) %}" />
            </div>

d() & dd() : Dumper les paramètres du template

Votre controller envoi des paramètres à votre template. Si vous souhaitez lors de vos développement "dumper" un, plusieurs ou tous ces paramètres, la fonction d() vous sera utile.

Exemple d'utilisation de d() & dd() :

        <!-- Template : ./templates/exemple/maMethode.php -->
        <div class="container">

            # Via la fonction template

            {% d() %}                 # Dump tous les paramètres
            {% dd() %}                # Dump tous les paramètres et kill le script
            {% d(titre) %}            # Dump le paramètre "titre" du template
            {% dd(titre) %}            # Dump le paramètre "titre" du template et kill le script
            {% d(titre,logo,user) %}  # Dump tous les paramètres passés en arguments

            # Equivalent via PHP :

            <?php d( $kParams ); ?>
            <?php dd( $kParams ); ?>
            <?php d( $kParams['title'] ); ?>
            <?php dd( $kParams['title'] ); ?>
            <?php d( $kParams['title'] ); d( $kParams['logo'] ); d( $kParams['user'] ); ?>

        </div>

Multiples interpolations

L'interpolation c'est le concept de remplacer les variables de templating {{ ... }} et {% ... %} que vous allez écrire dans vos templates par leurs vraies valeurs qui sont définies en PHP dans les paramètres de render();

Pourquoi multiples ?

Il se peut que vous ayez besoin dans une fonction de template qu'une valeur soit interpollée avant que la fonction ne se résolve. C'est pourquoi .kernelite interpole à plusieurs reprises les données de vos templates.

Exemples d'une double interpolation

    Avant interpolation : 
        <span>{% get(user, {{ user.id }} ,prenom) %}</span>

    1ere interpolation (mustache) :
        <span>{% get(user, 1 ,prenom) %}</span>

    2nde interpolation (.kernelite template functions)
        <span>Jean</span>

Limites

En plus de l'interpolation initiale, et celle des fonction templates, .kernelite peut recommencer l'interpolation jusqu'à 10 fois.
Tant qu'une occurence de variable de template est trouvée, l'interpolation recommencera.
Passé la limite des 10 interpolations, le résultat sera retourné.

Les fragments

L'objectif d'un fragment est d'éviter la répétitivité d'un morceau de template. Si vous avez un bout de template qui est à placer dans plusieurs templates, alors vous pouvez définir un fragment et l'appeller quand vous en avez besoin. L'interpolation fonction de la même manière dans les fragments.

Le dossier des fragment

Pour utiliser les fragments il faut créer le dossier ./templates/.fragments
Ce dossier à la racine de vos templates contiendra la totalité de vos fragments.

Créer un fragment

Créer son fragment en créant un fichier php dans : ./templates/.fragments
Par exemple : ./templates/.fragments/test.php


            <!-- Template : ./templates/.fragments/test.php -->
            <header class="navigation">
                Ceci est un fragment qui affiche : <br/>
                {{title}}
            </header>

Invoquer un fragment

Depuis votre template de controller vous pouvez invoquer votre fragment en utilisant les fonctions templates {% fragment() %} ou {% frag() %}



            <!-- Template : ./templates/index/home.php -->
            <div id="page">
                {% fragment(test) %}
            </div>




            <!-- Rendu final -->
            <div id="page">
                <header class="navigation">
                    Ceci est un fragment qui affiche : 
                    Documentation Kernelite v2.0
                </header>
            </div>

Les structures .kernelite

Le concept de structure est un des atouts majeurs de .kernelite. Leur utilisation est un gain de temps phénoménal pour le développeur.

Présentation

Il y a beaucoup à dire sur les structures car elles remplissent plusieurs rôles au sein de votre application. Ce sont des fichiers .yaml très simples à concevoir pour les développeurs.
Voici une liste des rôles qu'endossent les structures dans .kernelite :

  • Base : possibilité de générer automatiquement une table
  • Formulaire : possibilité de générer automatiquement des formulaires
  • Validation : possibilité de valider automatiquement des données
Emplacement & nomenclature

Les structures .kernelite sont toutes stockées à la racine du dossier ./structures. Un fichier de structure se nomme parle nom de la structure qu'il représente. Ainsi, si l'on souhaite créer une structure user, alors on créera un fichier ./structures/user.yaml.

Structure == Table ? Pas forcement !

Ce serait aller bien vite que de définir une structure simplement comme une table de base de données.
Une structure pourrait très bien n'être constituée que de champs qui n'ont pas d'existance en base et dans ce cas là, cette strucutre n'aurait pas de table en base de données.
Mais dans cas, a quoi sert cette structure ?
La structure peut très bien aussi servir comme base de formulaire ou modèle de validation de données.

Définition

Une structure est composée de champs, un peu comme une table SQL. Donc pour décrire une structure, il faudra à minima énumérer ses champs en précisant leurs types.

Exemple de définition de structure

    exemple :
        libelle :
            is : string


Explications des lignes

    Ligne 1 : nom de la structure (doit reprendre celui du nom fichier)
    Ligne 2 : nom du premier champ de la structure (ici : libelle)
    Ligne 3 : parametre "is" du champ "libelle" qui précise le type du champ


Le fichier .yaml de définition d'une structure doit forcement commencer à la première tabulation par reprendre le nom de la structure. Ainsi dans l'exemple ci-dessus, on constate que le fichier ./structures/exemple.yaml début bien par exemple : sur sa première ligne.

La propriété "is" vitale

Lors de la définition d'un champ de structure, la propriété is est obligatoire.
Cette prorpiété permet deux choses :
- savoir si ce champ correspond à de la persistance de données (stockage en base)
- si oui, quel type de données sera stockée dans ce champ

Valeurs possibles de is :
  • integer ou int
  • double ou float
  • string
  • text
  • boolean
  • date
  • null (spécial)
is : null

Si vous ne souhaitez pas que ce champ soit concerné par le stockage de données en base il vous faudra alors définir la propriété is à null.

Génération automatique de table en base

Une fois que vous avez finit de décrire votre structure, si vous actualisez votre application, .kernelite va analyser celle-ci. Si cette nouvelle structure comporte des champs dont la propriété is n'est pas null, alors une table sera automatiquement créée portant le nom de la structure et contenant les champs (is!=null) de la structure.

Exemple de structure

    exemple :

        libelle :
            is : string
        nom :
            is : string
        prenom :
            is : string
        age :
            is : int
        naissance :
            is : date
        accept :
            is : null

Table générée automatiquement par .kernelite
Table et champs par défaut

Comme on peut le constater dans l'exemple ci-dessus, lorsque .kernelite génère une table à partir d'une structure, certains champs sont automatiquement créés dans la table correspondante :

  • id : INT, UNSIGNED, AUTO_INCREMENT
  • date_creation : TIMESTAMP, DFAULT CURRENT_TIMESTAMP
  • date_modification : TIMESTAMP, ON UPDATE CURRENT_TIMESTAMP
  • deleted : TINYINT DEFAULT 0
Donner des valeurs par défaut

Il est possible de donner des valeurs par défaut à vos champs de structure. Pour cela, il vous faut préciser en plus de is la propriété default.


    exemple :
        libelle :
            is : string
            default : "vide"
        age :
            is : int
            default : 18

Modification

Il est possible de modifier une structure dans .kernelite, mais il y a certaines limites.
Pour des raisons de sécurité, .kernelite autorise la répercution en base de l'ajout de nouveau champ, mais pas leurs modifications ou suppression.

Ajout de champs

Si vous modifiez le fichier de structure .yaml et que vous y ajoutez un nouveau champ, alors celu-ci sera prit en compte dès la prochaine actualisation de votre application. Si necessaire, .kernelite ajoutera un nouveau champ dans la table correspondante à l'endroit exact ou il a été placé dans la structure.

Modifier l'ordre des champs dans la structure

Cela n'a aucune répercution sur la base, donc aucune modification ne sera effectuée. Les champs de la table resteront dans leur ordre originel.

Modification de champ

Si vous changez le type is d'un champ de structure, aucune modification ne sera effectuée automatiquement en base. Ce sera donc au développeur manuellement de répercuter sur la base la modification.

Supression de champ

Si vous supprimez un champ de structure, aucune modification ne sera effectuée automatiquement en base. Ce sera donc au développeur manuellement de répercuter sur la base la modification.

Supression de structure

Si vous supprimez une structure, aucune modification ne sera effectuée automatiquement en base. Ce sera donc au développeur manuellement de répercuter sur la base la modification.

Pourquoi aucune modification n'est automatique ?

Si une modification a été faite par erreur ou un fichier supprimé par erreur, il serait dommage que .kernelite supprime ou altère toutes vos données.
Pour prévenir de ce genre de cas, il a été décidé que .kernelite ne toucherait pas de manière automatique à ce qui pourrait altérer les données.

Récuperation

Depuis n'importe où en PHP dans votre projet, .kernelite peut vous fournir la définition d'une de vos structures. Pour cela, il existe plusieurs méthodes.

Récupérer la définition de exemple.yaml :

    $obj = Structure::get('exemple');
    # ou
    $obj = structure('exemple'); // super globale
    # ou
    $obj = s('exemple'); // super globale

La récuperation de structure retourne le contenu de votre fichier .yaml de déclaration sous forme d'un tableau PHP multidimensionnel.

Injections initiales

Lors de la génération de votre structure, si celle-ci à une persistence en base de données, il est possible de lui injecter des données de manière statique.
Cela peut servir à pré-remplir des référentiels ou à utiliser des jeux de données lors des développements.

Quand à lieu l'injection ?

Uniquement lors de la construction en base de la structure. Lors de l'appel de votre application, .kernelite analyse vos structures et regarde s'il y a des taches à réaliser. Si l'une de vos structures necessite la création d'une table en base de données, alors une fois la table créées, si des données à injecter existe, elles seront traitées.

Le dossier .structures/datas/

Par défaut, dans votre dossier .kernelite ./structures il existe un dossier datas qui est vide. C'est dans ce dossier que devront être placés les fichiers d'injection de données statiques.

Nomenclature et structure du fichier d'injection

Dans le dossier datas, vos fichier d'injection devront porter exactement le nom de la structure dans laquelle les données doivent être injectées.

Structure d'exemple :

    # ./structures/marque.yaml
    marque :
        libelle :
            is : string

        actif :
            is : int

Données à injecter :

    # ./structures/datas/marque.yaml
    datas :
        -
            libelle : Nike
            actif : 1
        -
            libelle : Adidas
            actif : 0
        -
            libelle : Dior
            actif : 1
Outils pratiques pour l'injection

Il existe plein d'outils sur internet permettant de convertir des fichiers de données au format Yaml.
Par exemple : https://www.convertcsv.com/csv-to-yaml.htm peut convertir vos fichiers CSV au format Yaml.

Formulaire de structure

Il est possible d'enrichir vos structures afin de générer des formulaires automatiquement.

Propriétés des champs de structures

Afin de pouvoir générer des formulaire, la propriété is de vos champs de structure ne nous servira pas. Il faut définir des propriétés supplémentaires. A minima, il faudra définir le champ type. Dans un template, si vous souhaitez afficher un formulaire automatique, il vous suffira de faire appel aux fonctions de template form() ou form_widget()

Structure :

    exemple :
        libelle :
            is : string
            type : text

        nom :
            is : string
            type : text

        prenom :
            is : string
            type : text

Template (fonction template ou PHP):

    <div class="container">
        {% form(exemple) %}
    </div>


    <div class="container">
        <?php form('exemple'); ?>
    </div>


    <div class="container">
        <?php echo Structure::getForm('exemple'); ?>
    </div>

Rendu :
Ajouter des labels :
Structure :

    exemple :
        libelle :
            is : string
            type : text
            label : Libellé

        nom :
            is : string
            type : text
            label : Votre nom

        prenom :
            is : string
            type : text
            type : "Prénom :"

Template :

    <div class="container">
        {% form(exemple) %}
    </div>


Rendu :
Afficher les champs un par un avec form_widget() :
Structure :

    exemple :
        libelle :
            is : string
            type : text
            label : Libellé

        nom :
            is : string
            type : text
            label : Votre nom

        prenom :
            is : string
            type : text
            type : "Prénom :"

Template (fonction template ou PHP):

    <div class="container">
        {% form_widget(exemple) %}
    </div>


    <div class="container">
        <?php form_widget('exemple','prenom'); ?>
    </div>

Rendu :
Ne pas générer un champ avec hide :
Structure :

    exemple :
        libelle :
            is : string
            type : text
            label : Libellé

        nom :
            is : string
            type : text
            label : Votre nom
            hide : true

        prenom :
            is : string
            type : text
            type : "Prénom :"

Template :

    <div class="container">
        {% form(exemple) %}
    </div>


Rendu :

Les différents types

.kernelite sait gérer différents types de champs lors de la génération automatique de formulaires. Pour cela, vous devez définir la prpriété type des champs de vos structures parmi les valeurs suivantes.

text Un input type="text" sera généré
hidden un input type="hidden" sera généré
textarea un textarea sera généré
select un select sera généré, il vous faudra préciser la propriété options
autre toute autre valeur sera génété comme input type="..." (number,mail,...)
Définir les options d'un select

Si votre champ est définit de type select, il est impératif de définir des options. Pour cela, vous devrez ajouter la propriété options à votre champ de structure. Les options peuvent être définies de deux façons différentes :

  • via des options statiques : directement décrite dans votre structure
  • via une structure : une paire (id,libelle) sera utilisé sur la structure pour générer les options
Options statiques
Structure exemple :

    exemple :
        actif :
            is : int
            default : 1
            type : select
            label : "Actif ?"
            options : 
                0 : Non
                1 : Oui

Options via structure
Structure exemple :

    exemple :
        id_marque :
            is : int
            type : select
            label : "Marque :"
            options : marque

Structure marque :

    marque :
        libelle :
            is : string

Template (fonction template ou PHP):

<div class="container">
    {% form_widget(exemple,id_marque) %}
</div>

Rendu :

La validation

Avant de faire persister les données soumises par le client,
.kernelite met à votre disposition un outil de vérification et de validation des données soumises : le FormValidator
Afin de pouvoir l'utiliser, il faut commencer par ajouter des propriétés de validation dans vos structures.

La propriété check

Cette propriété vous permet de définir quel type le vérification le FormValidator devra effectuer sur la donnée de ce champ.
En fonction de la valeur de check, il vous faudra renseigner des champs complémentaires.

Vérification de longueur avec check : length

    exemple :
        libelle :
            is : string
            type : text
            label : "Libellé"
            check : length
            min : 5
            max : 50

Vérification d'entier avec check : int

    exemple :
        age :
            is : int
            type : numeric
            label : "Age"
            check : int

Vérification de mail avec check : mail

    exemple :
        email :
            is : string
            type : text
            label : "Libellé"
            check : mail

Vérification n° de téléphone avec check : phone

    exemple :
        telephone :
            is : string
            type : text
            label : "Numéro de téléphone"
            check : phone

Vérification de mot de passe avec check : password

    exemple :
        pass :
            is : string
            type : password
            label : "Mot de passe"
            check : password
            rules :
                min : 5
                max : 50
                alphaNum : true

Confirmation de mot de passe check : confirm

    exemple :
        confirm :
            is : null
            type : password
            label : "Confirmer le mot de passe"
            check : confirm
            match : pass

Utiliser le FormValidator

Après avoir définit les check de vos structures, vous pouvez désormais automatiser la validation de vos formulaires grace au FormValidator.


    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( Request $req ) {
            $validation = new FormValidator( 'user', $req->post );
            $status = $validation->getStatus();
            $errors = $validation->getErrors();
        }
    }

La contrstuction d'un FormValidator prend deux arguments :

  • structure : le nom d'une de vos structures
  • params : un tableau associatif de données que vous souhaitez faire valider
Liste des méthodes disponibles du FormValidator :
Nom Valeur de retour Description
getStatus() boolean Retourne true si la validation a réussi, sinon false
getErrors() array Retourne un tableau d'erreurs pour chaque validation échouée

La suggestion

Lors de la saisie dans champ, vous pourriez avoir besoin de suggérer des résultats à votre utilisateur, et qu'en fonction de sa saisie, vous puissiez interroger le serveur. Pour cela, .kernelite met à votre disposition un outil de suggestion automatique.

.kernelite utilise autocomplete par jQuery UI. Doc : https://jqueryui.com/autocomplete/
La propriété suggest

La propriété suggest attend plusieurs paramètres et il y existe deux modes d'utilisations. Voici la liste de toutes les propriétés possibles :

structure nom d'une structure .kernelite contenant les données que l'on souhaite suggérer
fields propriétés de la structure cibles sur lesquelles on souhaite rechercher
return propriétés de la structure que l'on souhaite retourner au client
filter tableau de filtres à appliquer lors de la recherche
callback fonction javascript à appeller lors de la séléction d'une suggestion par le client
idField Si précisé, #id du champ devant contenir l'ID du réstulat séléctionné
controller Méthode à appeler afin de surcoucher les suggestions .kernelite
La cas classique d'utilisation

Dans la plus part des cas, nous avons une structure qui sert de référentiel (par exemple : marque), et seconde structure qui utilise ce référentiel (par exemple : mobile, qui à une propriété id_marque).

Structure mobile :

    mobile :
        libelle :
            is : string
            type : text
            label : "Nom du modèle"

        marque :
            is : null
            type : text
            label : "Marque"
            suggest :
                structure : marque
                idField : id_marque
                # field : libelle
                # return : libelle
        
        id_marque :
            is : int
            type : hidden
    
Si vous ne précisez pas les champs field et return, .kernelite tentera de rechercher automatiquement dans le champ "libelle" s'il existe dans la structure
Structure marque :

    marque :
        libelle :
            is : string

Données injectées dans marque :

datas :
  -
    libelle : Nike
  -
    libelle : Adidas
  -
    libelle : Dior
  -
    libelle : Carrefour
  -
    libelle : Dell
  -
    libelle : AliExpress
  -
    libelle : Aigle
  -
    libelle : Armani
  -
    libelle : Abercombie & Fitch
  -
    libelle : American Eagle  
Génération du formulaire avec form('mobile') :
Recherchez un des éléments de la liste des données injectées
Si vous inspectez le champ marque, vous trouverez aussi le champ id_marque de type "hidden" qui aura la valeur de l'option séléctionné lors de la suggestion.
Autre exemple avec des filtres :

    exemple :
        user :
            is : null
            type : text
            label : "Chercher un utilisateur"
            suggest :
                structure : user
                field : nom,prenom,poste
                return : prenom,nom
                filter :
                    id_profile : id_profile # $("#id_profile").val()

Surcoucher la suggestion .kernelite ( 🚧 experimental )

Il vous est possible de surcoucher la suggestion .kernelite avec votre propre méthode de controller, mais il faudra respecter certaines règles :


    exemple :
        user :
            is : null
            type : text
            label : "Chercher un utilisateur"
            suggest :
                structure : user
                controller : "Exemple::maSuggestion"  


    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maSuggestion( DataManager $dm, Request $req, String $search, String $filters ) {
            ...
            $return = [];
            ...
            $return[] = [
                "id" => $id,
                "label" => $label,
                "value" => $value
            ];
            ...
            die(json_encode($return));
        }
    }

Le DataManager

Le DataManager est l'outil de gestion de données de .kernelite. C'est grace à lui que vous pourrez faire persister les informations dans vos structures ainsi que les récupérer.

Pour une approche un peu plus "SQL", que vous soyez sur une base MySQL ou SQL Server, vous pourrez utiliser les méthodes du DataManager pour requeter vos tables de la même manière.

Configuration

Vous pouvez configurer une ou plusieurs bases de données dans votre projet dans le fichier project.yaml.

Exemple de configuration :

    databases :
        -
            name : main
            mode : mysql
            host :  localhost
            user :  user-database
            password : 123456
            base : mon_projet
            passwords :
                salt : ""
                saltOrder                


Pour chacune des bases de votre projet, voici les options obligatoires et optionelles

name Le nom que vous souhtaiez donner a cette connexion (utilisé lors de la création d'instance)
mode Type de connexion : mysql / sql
host Adresse de votre base (localhost, IP,...)
user Identifiant de connexion
password Mot de passe lié à cet identifiant
base Nom de la base de données à sélectionner une fois connecté
salt Chaine de caractère utilisée pour salée les mots de passe de cette connexion
saltOrder Ordre du sallage :
  • 1 : SEL + MDP
  • 2 : MDP + SEL
  • 3 : SEL + MDP + SEL
  • default : MDP
Votre base de données principale doit toujours s'apeller "main".
Ce sera la base de données par défaut de votre Datamanager.
Exemple de configuration multi-bases :

    databases :
        -
            name : main
            mode : mysql
            host :  localhost
            user :  user-database
            password : 123456
            base : mon_projet
            passwords :
                salt : ""
                saltOrder     
        -
            name : statistiques
            mode : mysql
            host :  192.168.1.5
            user :  admin
            password : abcdefgh
            base : project_stats
            passwords :
                salt : ""
                saltOrder                             


Utilisation

Vous pouvez demander à .kernelite de vous fournir le DataManager sur la base main via les paramètres de votre méthode de controller :


    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( DataManager $dm ) {
            ...
        }
    }

Ceci ne fonctionne que pour vos méthodes invoquées via des routes.
Si vous appelez vous même une méthode d'un service par exemple, il vous faudra lui envoyer depuis votre controller, l'instance du DataManager.
Appeler un DataManager sur une autre base que la main

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode() {
            
            # Via constructeur
            $dm = new DataManager('statistiques');

            # Via la super globale
            $dm = dm('statistiques');

        }
    }

Rechercher

Afin de rechercher des données, le DataManager met à votre disposition deux méthodes efficaces : find et findAll.

Attention ! Les méthodes de recherche ne retournent aucun résultat.
Il faut utiliser les méthodes de récupération afin d'obtenir les résultats que vous avez cherché.
find

Cette méthode permet de retourner une ligne précise dans une table en base de données en se basant sur son identifiant unique.
La méthode find prend en argument 2 paramètres obligatoires :

Paramètre Valeur Défaut Description
table string obligatoire Table ou structure ou vous souhaitez faire votre recherche
id int obligatoire Identifiant [id] de la table
Exemple :

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( DataManager $dm, Int $id_marque ) {
            $dm->find('marque', $id_marque );
        }
    }

findAll

Cette méthode à pour objectif de retourner un ou plusieurs résultats basés sur les paramètres fournis (et non pas juste un ID commde pour find).
La méthode findAll prend en argument 2 paramètres obligatoires :

Paramètre Valeur Défaut Description
table string obligatoire Table ou structure ou vous souhaitez faire votre recherche
@params array [] Liste des paramètres de la recherche
Détails des paramètres possibles @params :
Paramètre Valeur Défaut Description
@filter array [] Filtre sur les valeurs des champs de la table
operator string AND Valeurs possibles : "AND" / "OR". Opérateur logiques à placer entre les filter
order string ASC Valeurs possibles : "ASC" / "DESC". ordre logique de la recherche
orderBy array [] Liste des champs pour l'application de order
limit int aucun Liste du nombre de résultats
offset int 0 Offset des résultats
Détails des @filters :

@filter est un tableau associatif (clé=>valeur) qui permet de préciser des filtres de recherche. En clé, il faudra placer le nom du champ, et en valeur la valeur recherchée. Il est possible de placer un opérateur logique dans le nom du champ afin de faire varier les critères de recherche.

Liste des opérateurs logiques autorisés :

  • aucun : test d'égalité
  • ! : différent de
  • % : LIKE '%...%'
  • > : supérieur
  • >= : supérieur ou égal
  • < : inférieur
  • <= : inférieur ou égal
Exemples :

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( DataManager $dm ) {
            $dm->findAll('marque',[
                "filter" => [
                    "prenom" => "Jean",  # Le prénom doit valoir : "Jean"
                    "%prenom" => "ean",  # Le prénom doit comporter les caractères "ean"
                    "!prenom" => "Jean", # Le prénom doit être différent de "Jean"
                    ">age" => 18         # L'age doit être supérieur à 18
                    ">=age" => 18        # L'age doit être supérieur ou égal à 18
                    "<age" => 18         # L'age doit être inférieur à 18
                    "<=age" => 18        # L'age doit être inférieur ou égal à 18                    
                ]
            ]);
        }
    }

Exemple de recherche :

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( DataManager $dm ) {
            $dm->findAll('user',[
                "filter" => [
                    ">age" => 18,
                    "actif" => 1,
                    "<supersuer" => 1
                ],
                "limit" => 30,
                "order" => "DESC",
                "orderBy" => ["prenom","nom"]
            ]);
        }
    }

query

Dans le cas ou il vous faudrait réaliser une opération MySQL complexe non couverte par les méthodes de .kernelite, vous avez accès à la méthode : query qui attend en paramètre votre requête MySQL.

Exemple de query :

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( DataManager $dm ) {
            $dm->query("SELECT * FROM user")->get();
        }
    }

Attention !
Lors de l'utilisation de query() il est impératif pour le développeur d'échapper les caractères de ses requetes.
Pour cela, il est vivement recommendé d'utiliser la méthode du DataManager : escape()

Exemple de query avec escape:

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( DataManager $dm ) {
            $q = $dm->escape("SELECT * FROM user");
            $dm->query($q)->get();
        }
    }

Récupérer les résultats

Après avoir recherché avec find ou findAll, vous allez devoir récupérer vos résultats. Le DataManager vous propose plusieurs façons de récupérer vos résultats en fonction de vos besoins.

get()

Retourne un tableau multi-dimensionnel contenant tous vos résultats.

Exemple de recherche :

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( DataManager $dm ) {
            $marques = $dm->findAll('marque')->get();
            d($marques); # Utlisation de la super globale d()
        }
    }

Sortie :

8-get.php - ligne 28

Kernelite→processQuery ► Kernelite→processCall ► Index→home ► Index→getChapter ► include ► Exemple→getMarques

<?php
 
array(10) {
  [
0]=>
  array(
5) {
    [
"id"]=>
    
string(1"1"
    
["libelle"]=>
    
string(4"Nike"
    
["date_creation"]=>
    
string(19"2022-03-24 16:34:33"
    
["date_modification"]=>
    
NULL
    
["deleted"]=>
    
string(1"0"
  
}
  [
1]=>
  array(
5) {
    [
"id"]=>
    
string(1"2"
    
["libelle"]=>
    
string(6"Adidas"
    
["date_creation"]=>
    
string(19"2022-03-24 16:34:33"
    
["date_modification"]=>
    
NULL
    
["deleted"]=>
    
string(1"0"
  
}
  [
2]=>
  array(
5) {
    [
"id"]=>
    
string(1"3"
    
["libelle"]=>
    
string(4"Dior"
    
["date_creation"]=>
    
string(19"2022-03-24 16:34:33"
    
["date_modification"]=>
    
NULL
    
["deleted"]=>
    
string(1"0"
  
}
  [
3]=>
  array(
5) {
    [
"id"]=>
    
string(1"4"
    
["libelle"]=>
    
string(9"Carrefour"
    
["date_creation"]=>
    
string(19"2022-03-24 16:34:34"
    
["date_modification"]=>
    
NULL
    
["deleted"]=>
    
string(1"0"
  
}
  [
4]=>
  array(
5) {
    [
"id"]=>
    
string(1"5"
    
["libelle"]=>
    
string(4"Dell"
    
["date_creation"]=>
    
string(19"2022-03-24 16:34:34"
    
["date_modification"]=>
    
NULL
    
["deleted"]=>
    
string(1"0"
  
}
  [
5]=>
  array(
5) {
    [
"id"]=>
    
string(1"6"
    
["libelle"]=>
    
string(10"AliExpress"
    
["date_creation"]=>
    
string(19"2022-03-24 16:34:34"
    
["date_modification"]=>
    
NULL
    
["deleted"]=>
    
string(1"0"
  
}
  [
6]=>
  array(
5) {
    [
"id"]=>
    
string(1"7"
    
["libelle"]=>
    
string(5"Aigle"
    
["date_creation"]=>
    
string(19"2022-03-24 16:34:34"
    
["date_modification"]=>
    
NULL
    
["deleted"]=>
    
string(1"0"
  
}
  [
7]=>
  array(
5) {
    [
"id"]=>
    
string(1"8"
    
["libelle"]=>
    
string(6"Armani"
    
["date_creation"]=>
    
string(19"2022-03-24 16:34:34"
    
["date_modification"]=>
    
NULL
    
["deleted"]=>
    
string(1"0"
  
}
  [
8]=>
  array(
5) {
    [
"id"]=>
    
string(1"9"
    
["libelle"]=>
    
string(18"Abercombie & Fitch"
    
["date_creation"]=>
    
string(19"2022-03-24 16:34:34"
    
["date_modification"]=>
    
NULL
    
["deleted"]=>
    
string(1"0"
  
}
  [
9]=>
  array(
5) {
    [
"id"]=>
    
string(2"10"
    
["libelle"]=>
    
string(14"American Eagle"
    
["date_creation"]=>
    
string(19"2022-03-24 16:34:34"
    
["date_modification"]=>
    
NULL
    
["deleted"]=>
    
string(1"0"
  
}
}
?>
get( string)

Dans le cas ou l'on recherche une seule valeur dans une seule ligne de résultat, on peut fait appel à get avec en paramètre le nom du champ.

Exemple de recherche :

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( DataManager $dm ) {
            $marque = $dm->findAll('marque',[
                "filter"=>[
                    "%libelle"=>"adidas"
                ]
            ]);
            $value = $dm->get('libelle');
            d($value);
        }
    }

Sortie :

8-get.php - ligne 62

Kernelite→processQuery ► Kernelite→processCall ► Index→home ► Index→getChapter ► include ► Exemple→getMarques4

<?php
 string
(6"Adidas"
?>
Revient au même que :
$dm->findAll(...)->getRow()['libelle'];
getRow

Retourne la première ligne de résultat sous forme de tableau associatif.

Exemple de recherche :

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( DataManager $dm ) {
            $marque = $dm->findAll('marque')->getRow();
            d($marque);
        }
    }

Sortie :

8-get.php - ligne 96

Kernelite→processQuery ► Kernelite→processCall ► Index→home ► Index→getChapter ► include ► Exemple→getMarques2

<?php
 
array(5) {
  [
"id"]=>
  
string(1"1"
  
["libelle"]=>
  
string(4"Nike"
  
["date_creation"]=>
  
string(19"2022-03-24 16:34:33"
  
["date_modification"]=>
  
NULL
  
["deleted"]=>
  
string(1"0"
}
?>
Exemple de recherche spécifique :

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( DataManager $dm ) {
            $marque = $dm->findAll('marque',[
                "filter"=>[
                    "%libelle"=>"adidas"
                ]
            ]);
            $dm->getRow();
            d($marque);
        }
    }

Sortie :

8-get.php - ligne 124

Kernelite→processQuery ► Kernelite→processCall ► Index→home ► Index→getChapter ► include ► Exemple→getMarques3

<?php
 
array(5) {
  [
"id"]=>
  
string(1"2"
  
["libelle"]=>
  
string(6"Adidas"
  
["date_creation"]=>
  
string(19"2022-03-24 16:34:33"
  
["date_modification"]=>
  
NULL
  
["deleted"]=>
  
string(1"0"
}
?>
getByField( [string key], [string value] )

Si key est précisé, alors il sera utilisé comme clé du tableau, sinon id sera utilisé.
Si value est précisé, alors ce sera la seule valeur de chaque résultats.

Exemple de recherche :

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( DataManager $dm ) {
            $marques = $dm->findAll('marque')->getByField();
            d($marques);
    }

Comme aucune clé n'est précisée, alors l'id est mit en clé de table
Sortie :

8-get.php - ligne 155

Kernelite→processQuery ► Kernelite→processCall ► Index→home ► Index→getChapter ► include ► Exemple→getMarques5

<?php
 
array(10) {
  [
1]=>
  array(
5) {
    [
"id"]=>
    
string(1"1"
    
["libelle"]=>
    
string(4"Nike"
    
["date_creation"]=>
    
string(19"2022-03-24 16:34:33"
    
["date_modification"]=>
    
NULL
    
["deleted"]=>
    
string(1"0"
  
}
  [
2]=>
  array(
5) {
    [
"id"]=>
    
string(1"2"
    
["libelle"]=>
    
string(6"Adidas"
    
["date_creation"]=>
    
string(19"2022-03-24 16:34:33"
    
["date_modification"]=>
    
NULL
    
["deleted"]=>
    
string(1"0"
  
}
  [
3]=>
  array(
5) {
    [
"id"]=>
    
string(1"3"
    
["libelle"]=>
    
string(4"Dior"
    
["date_creation"]=>
    
string(19"2022-03-24 16:34:33"
    
["date_modification"]=>
    
NULL
    
["deleted"]=>
    
string(1"0"
  
}
  [
4]=>
  array(
5) {
    [
"id"]=>
    
string(1"4"
    
["libelle"]=>
    
string(9"Carrefour"
    
["date_creation"]=>
    
string(19"2022-03-24 16:34:34"
    
["date_modification"]=>
    
NULL
    
["deleted"]=>
    
string(1"0"
  
}
  [
5]=>
  array(
5) {
    [
"id"]=>
    
string(1"5"
    
["libelle"]=>
    
string(4"Dell"
    
["date_creation"]=>
    
string(19"2022-03-24 16:34:34"
    
["date_modification"]=>
    
NULL
    
["deleted"]=>
    
string(1"0"
  
}
  [
6]=>
  array(
5) {
    [
"id"]=>
    
string(1"6"
    
["libelle"]=>
    
string(10"AliExpress"
    
["date_creation"]=>
    
string(19"2022-03-24 16:34:34"
    
["date_modification"]=>
    
NULL
    
["deleted"]=>
    
string(1"0"
  
}
  [
7]=>
  array(
5) {
    [
"id"]=>
    
string(1"7"
    
["libelle"]=>
    
string(5"Aigle"
    
["date_creation"]=>
    
string(19"2022-03-24 16:34:34"
    
["date_modification"]=>
    
NULL
    
["deleted"]=>
    
string(1"0"
  
}
  [
8]=>
  array(
5) {
    [
"id"]=>
    
string(1"8"
    
["libelle"]=>
    
string(6"Armani"
    
["date_creation"]=>
    
string(19"2022-03-24 16:34:34"
    
["date_modification"]=>
    
NULL
    
["deleted"]=>
    
string(1"0"
  
}
  [
9]=>
  array(
5) {
    [
"id"]=>
    
string(1"9"
    
["libelle"]=>
    
string(18"Abercombie & Fitch"
    
["date_creation"]=>
    
string(19"2022-03-24 16:34:34"
    
["date_modification"]=>
    
NULL
    
["deleted"]=>
    
string(1"0"
  
}
  [
10]=>
  array(
5) {
    [
"id"]=>
    
string(2"10"
    
["libelle"]=>
    
string(14"American Eagle"
    
["date_creation"]=>
    
string(19"2022-03-24 16:34:34"
    
["date_modification"]=>
    
NULL
    
["deleted"]=>
    
string(1"0"
  
}
}
?>
Exemple de recherche :

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( DataManager $dm ) {
            $marques = $dm->findAll('marque')->getByField('libelle');
            d($marques); 
        }
    }

Comme la clé "libelle" est précisée, alors elle est utilisée en clé de table
Sortie :

8-get.php - ligne 181

Kernelite→processQuery ► Kernelite→processCall ► Index→home ► Index→getChapter ► include ► Exemple→getMarques6

<?php
 
array(10) {
  [
"Nike"]=>
  array(
5) {
    [
"id"]=>
    
string(1"1"
    
["libelle"]=>
    
string(4"Nike"
    
["date_creation"]=>
    
string(19"2022-03-24 16:34:33"
    
["date_modification"]=>
    
NULL
    
["deleted"]=>
    
string(1"0"
  
}
  [
"Adidas"]=>
  array(
5) {
    [
"id"]=>
    
string(1"2"
    
["libelle"]=>
    
string(6"Adidas"
    
["date_creation"]=>
    
string(19"2022-03-24 16:34:33"
    
["date_modification"]=>
    
NULL
    
["deleted"]=>
    
string(1"0"
  
}
  [
"Dior"]=>
  array(
5) {
    [
"id"]=>
    
string(1"3"
    
["libelle"]=>
    
string(4"Dior"
    
["date_creation"]=>
    
string(19"2022-03-24 16:34:33"
    
["date_modification"]=>
    
NULL
    
["deleted"]=>
    
string(1"0"
  
}
  [
"Carrefour"]=>
  array(
5) {
    [
"id"]=>
    
string(1"4"
    
["libelle"]=>
    
string(9"Carrefour"
    
["date_creation"]=>
    
string(19"2022-03-24 16:34:34"
    
["date_modification"]=>
    
NULL
    
["deleted"]=>
    
string(1"0"
  
}
  [
"Dell"]=>
  array(
5) {
    [
"id"]=>
    
string(1"5"
    
["libelle"]=>
    
string(4"Dell"
    
["date_creation"]=>
    
string(19"2022-03-24 16:34:34"
    
["date_modification"]=>
    
NULL
    
["deleted"]=>
    
string(1"0"
  
}
  [
"AliExpress"]=>
  array(
5) {
    [
"id"]=>
    
string(1"6"
    
["libelle"]=>
    
string(10"AliExpress"
    
["date_creation"]=>
    
string(19"2022-03-24 16:34:34"
    
["date_modification"]=>
    
NULL
    
["deleted"]=>
    
string(1"0"
  
}
  [
"Aigle"]=>
  array(
5) {
    [
"id"]=>
    
string(1"7"
    
["libelle"]=>
    
string(5"Aigle"
    
["date_creation"]=>
    
string(19"2022-03-24 16:34:34"
    
["date_modification"]=>
    
NULL
    
["deleted"]=>
    
string(1"0"
  
}
  [
"Armani"]=>
  array(
5) {
    [
"id"]=>
    
string(1"8"
    
["libelle"]=>
    
string(6"Armani"
    
["date_creation"]=>
    
string(19"2022-03-24 16:34:34"
    
["date_modification"]=>
    
NULL
    
["deleted"]=>
    
string(1"0"
  
}
  [
"Abercombie & Fitch"]=>
  array(
5) {
    [
"id"]=>
    
string(1"9"
    
["libelle"]=>
    
string(18"Abercombie & Fitch"
    
["date_creation"]=>
    
string(19"2022-03-24 16:34:34"
    
["date_modification"]=>
    
NULL
    
["deleted"]=>
    
string(1"0"
  
}
  [
"American Eagle"]=>
  array(
5) {
    [
"id"]=>
    
string(2"10"
    
["libelle"]=>
    
string(14"American Eagle"
    
["date_creation"]=>
    
string(19"2022-03-24 16:34:34"
    
["date_modification"]=>
    
NULL
    
["deleted"]=>
    
string(1"0"
  
}
}
?>
Exemple de recherche :

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( DataManager $dm ) {
            $marques = $dm->findAll('marque')->getByField('id','libelle');
            d($marques); 
        }
    }

La clé id et la valeur libelle sont précisés, alors sera retourné un tableau associatif id=>libelle.
Sortie :

8-get.php - ligne 208

Kernelite→processQuery ► Kernelite→processCall ► Index→home ► Index→getChapter ► include ► Exemple→getMarques7

<?php
 
array(10) {
  [
1]=>
  
string(4"Nike"
  
[2]=>
  
string(6"Adidas"
  
[3]=>
  
string(4"Dior"
  
[4]=>
  
string(9"Carrefour"
  
[5]=>
  
string(4"Dell"
  
[6]=>
  
string(10"AliExpress"
  
[7]=>
  
string(5"Aigle"
  
[8]=>
  
string(6"Armani"
  
[9]=>
  
string(18"Abercombie & Fitch"
  
[10]=>
  
string(14"American Eagle"
}
?>
getOneField

Retourne un tableau non associatif d'une seule valeur par résultat

Exemple de recherche :

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( DataManager $dm ) {
            $marque = $dm->findAll('marque')->getOneField("libelle");
            d($marque);
        }
    }

Sortie :

8-get.php - ligne 233

Kernelite→processQuery ► Kernelite→processCall ► Index→home ► Index→getChapter ► include ► Exemple→getMarques8

<?php
 
array(10) {
  [
0]=>
  
string(4"Nike"
  
[1]=>
  
string(6"Adidas"
  
[2]=>
  
string(4"Dior"
  
[3]=>
  
string(9"Carrefour"
  
[4]=>
  
string(4"Dell"
  
[5]=>
  
string(10"AliExpress"
  
[6]=>
  
string(5"Aigle"
  
[7]=>
  
string(6"Armani"
  
[8]=>
  
string(18"Abercombie & Fitch"
  
[9]=>
  
string(14"American Eagle"
}
?>

Manipuler des données

Afin de manipuler les données du DataManager (mettre à jour, supprimer) vous devrez utiliser la méthode use

use( table, id )

Cette méthode permet de positionner le DataManager sur un objet à manipuler. Elle prend en argument une table et un id.

Paramètre Valeur Défaut Description
table string obligatoire Table à séléctionner
id int obligatoire Identifiant de la ligne de la table

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( DataManager $dm, Int $id_user ) {
            $dm->use('user', $id_user);
        }
    }

use retourne $this afin de permettre le chainage d'instructions
useFrom( table, field, value )

Cette méthode permet de positionner le DataManager sur un objet à manipuler. Elle prend en argument une table, un champ et une valeur.

Paramètre Valeur Défaut Description
table string obligatoire Table à séléctionner
field string obligatoire Champ de la table sur lequel se fixer
value string obligatoire Valeur du champ de la table

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( DataManager $dm, String $prenom ) {
            $dm->useFrom('user', 'prenom', $prenom);
        }
    }

useFrom cherchera la première occurence de $field = $value dans la table afin d'en récupérer l'id et faire appel à use()
off()

Permet de déselectionner l'objet courant du DataManager précédement séléctionné avec use.


    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( DataManager $dm, Int $id_user ) {
            $dm->use('user', $id_user);
            ...
            $dm->off(); # Le DataManager n'est plus raccoriché à 'user'#$id_user
        }
    }

getValue( field )

Retourne la valeur du champ field dans l'objet courant.


    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( DataManager $dm, Int $id_user ) {
            $dm->use('user', $id_user);
            $prenom = $dm->getValue('prenom');
        }
    }

getArray()

Retourne l'objet courant sous forme de tableau associatif.


    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( DataManager $dm, Int $id_user ) {
            $dm->use('user', $id_user);
            $user = $dm->getArray();
        }
    }

getFields()

Retourne les clefs de l'objet courant sous forme de tableau.


    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( DataManager $dm, Int $id_user ) {
            $dm->use('user', $id_user);
            return $dm->getFields(); # @return : ["id","prenom","nom","age",...]
        }
    }

refresh()

Rafraichit l'objet courant. Peut être utile si une autre source serait ammené à modifier l'objet.


    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( DataManager $dm, Int $id_user ) {
            $dm->use('user', $id_user);
            $dm->refresh();
        }
    }

set( field, value )

Met à jour la valeur d'une propriété de l'objet (dans l'instance de l'objet courant et en base).


    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( DataManager $dm, Int $id_user ) {
            $dm->use('user', $id_user);
            $dm->set('prenom', 'Jean');
        }
    }

multiSet( array )

Met à jour les valeurs de propriétés de l'objet (dans l'instance de l'objet courant et en base) grace à un tableau associatif clé => valeur.


    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( DataManager $dm, Int $id_user ) {
            $dm->use('user', $id_user);
            $dm->multiSet([
                'prenom' => 'Jean',
                'nom'   => 'Dupont',
                'age' => 18
            ]);
        }
    }

delete()

Supprime l'objet courant (l'instance et la ligne en base).


    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( DataManager $dm, Int $id_user ) {
            $dm->use('user', $id_user);
            $dm->delete();
        }
    }

Attention !
La méthode delete supprime définitivement la ligne de la table en base de données.
Pour un "safe-delete" utilisez plutôt : $dm->set('deleted', 1) et pensez à séléctionnez les données de vos applications avec un deleted = 0

Insertions de données

Le DataManager vous permet de différentes façons d'insérer de nouvelles données dans vos structures/tables.

create( table, datas, ignore )

Permet l'insertion de nouvelles données dans la table en base.

Paramètre Valeur Défaut Description
table string obligatoire Table dans laquelle insérer les données
datas array obligatoire Tableau associatif unidimensionnel ou multidimensionnel de données
ignore boolean true Ignorer les champs inconnus
Exemple avec un jeu de données unidimensionnel :

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( DataManager $dm, Int $id_user ) {
            $dm->create('user',[
                "prenom" => "Jean",
                "nom"    => "Dupont",
                "age"    => 18
            ]);
        }
    }

Exemple avec un jeu de données multidimensionnel :

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( DataManager $dm, Int $id_user ) {
            $users = [
                [ "prenom" => "Jean", "nom" => "Dupont" , "age" => 18 ],    
                [ "prenom" => "Paul", "nom" => "Dupré" , "age" => 20 ],
                [ "prenom" => "Pierre", "nom" => "Dujardin" , "age" => 22 ],
            ]
            $dm->create('user',$users);
        }
    }

La méthode create retourne $this afin de pouvoir chainer les instructions
create( table ) : utilisation de la Request

Lors de la soumission d'un formulaire
il est fort probable que toutes les données necessaires à la création d'une entrée en base soit présentent dans la Request (voir : Request).
Sachant ceci, le DataManager vous permet de réaliser une insertion dite "à l'aveugle" en se basant sur le contenur de Request->post.

Exemple de création à partir de la Request :

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( DataManager $dm ) {
            $dm->create('user');
        }
    }

Revient à faire :

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( DataManager $dm, Request $req ) {
            $dm->create('user', $req->post );
        }
    }

Dump du post de la request ( $req->post ) :

IndexController.php - ligne 274

Kernelite→processQuery ► Kernelite→processCall ► Index→home ► Index→getChapter ► include

<?php
 
array(3) {
  [
"prenom"]=>
  
string(4"Jean"
  
["nom"]=>
  
string(6"Dupont"
  
["age"]=>
  
int(18)
}
?>
getLastId()

Retourne le dernier id inséré en base via la méthode create.

getCreatedIds()

Retourne un tableau des derniers id inséré en base via la méthode create dans le cas d'une multiple-insertion.

Les entités (.kernelite v2.0)

Une entité est classe PHP qui représente une instance d'une de vos structure.
Par exemple, si vous avez une sutructure "user", alors une entité serait l'un de vos "user" spécifique.
Son rôle est de centraliser les fonctionnalités d'un objet et augmenter drastiquement la réutilisabilité de l'objet.

Fonctionnement

Emplacement et nomenclature

Tous les entités doivent être placés dans le dossier ./entities à la base du projet .kernelite.
Le nom du fichier devra être identique au nom de la structure correspondante :
la structure user pourrait avoir une entité ./entities/User.php.

Exemple d'entité à minima :

    # ./entities/User.php
    class User extends Entity {
        public function create() {
            return 0;
        }
    }

Emplacement de cette entité :

    ./entities
        User.php


Délivrance au controller

Afin d'utiliser une entité depuis un controller, il suffit de le demander en paramètre de vos méthodes.


    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( User $u ) {
            $u->...
        }
    }

Créer une entité

Création d'une entité

Afin de pouvoir créer une entité .kernelite, il faudra respecter à minima les règles suivantes.

  • Etendre "Entity" : votre entité devra étendre la classe .kernelite "Entity"
  • Définir la méthode "create():Int" : méthode de création d'une nouvelle entité, rentournant un ID d'entité créée
Exemple d'entité à minima :

    # ./entities/User.php
    class User extends Entity {

        # Création d'un nouvel utilisateur
        public function create() : Int {
            $datas = (new Post())->toArray();
            // logic...
            return $this->dm->create($this->structure, $datas );
        }

    }

Initialisation

Initialisation d'une entité

Le but d'une entité est de représenter une instance unique de votre structure.
Afin d'y parvenir, il faut initaliser votre entité avec l'ID de sa structure correspondante.
Pour cela, il faut faire parvenir un ID à .kernelite.

Ordre de priorité de detection des ID d'entité :
  • (1 - contructeur : new User(12) )
  • 2 - Slug : si le dernier paramètre de votre URL est un id (ex : /user/12 )
  • 3 - Post->id : si une clé "id" est trouvée dans le tableau $_POST
  • 4 - findIdCustom() : votre propre méthode de récupération d'ID
Exemple d'entité :

    # ./entities/User.php
    class User extends Entity {

        # Création d'un nouvel utilisateur
        public function create() : Int {
            $datas = (new Post())->toArray();
            // logic...
            return $this->dm->create($this->structure, $datas );
        }

        # Retourne le champ "name" de la structure "User"
        public function getName() {
            return $this->name;
        }

    }

Emplacement d'utilisation depuis un controller :

    # ./controllers/ExempleController.php

    class Exemple extends Controller {

        /* Api call : /user/12 */
        #@Route = { "url" : "/user", "api" : true }
        public function getUserName( User $u ) {
            return ["name" => $u->name];
        }

    }

Dans cet exemple, .kernelite a détécté automatiquement l'id "12" dans la route d'appel.
Comme le controller demande une injection de dépendance d'une entité "User", l'entité va être automatiquement initialisée sur l'id 12.
Initialiser son entité sans ID public

Si vous ne souhaitez pas utiliser publiquement l'ID de votre instance de structure pour initialiser votre entité, .kernelite vous permet de définir la méthode findIdCustom() qui attend un ID en retour.

Exemple d'entité :

    # ./entities/User.php
    class User extends Entity {

        ...
        # Trouve un ID utilisateur à partir du dernier paramètre d'URL étant un numero de badge
        public function findIdCustom() : Int {
            return dm()->findAll('user',[
                "filter" => [
                    "numero_badge" => (new Controller())->getLastURIParam()
                ]
            ])->get('id');
        }

    }

Méthodes

Liste des méthodes built-in d'une entité

Une fois votre entité initialisée, .kernelite vous offre un pannel de propriétés et méthodes incluses en plus de celles que vous souhaiteriez implémenter.

__init( $id )

Initialise une entité à partir d'un ID (fait automatiquement par .kernelite lors de l'injection de dépendance).

getId()

Retourne l'ID sur lequel l'entité a été initialisé

_exists( Int $id )

Retourne true sur l'ID $id a été trouvé dans la structure

String className

Propriété contenant le nom de votre entité (par ex: User)

String structure

Propriété contenant le nom de la structure de l'entité (par ex: user)

_loadDatas()

Charge la propriété "object" avec les donées de la structure à la position de l'ID

Array object

Propriété contenant les données de l'entité

_objectify()

Transforme toutes les données "object" en propriété de l'entité (ex : $this->object['name'] => $this->name )

get()

Retourne sous forme de tableau la valeur de toutes les propriétés de l'entité (ex : $this->name => $this->object['name'] )

_unset()

Défait et remet à zéro l'entité, elle devient alors vide et n'est plus une référence.

_me()

Positionne le DataManager sur l'entité. $this->_me() est équivalent à $this->dm->use($this->structure,$this->id)

_updateField( String $field, mixed $value )

Met à jour la valeur de $field avec $value dans l'entité, et fait persister la modification.

Exemple

Exemple d'entité :

    # ./entities/User.php
    class User extends Entity {

        # Création d'un nouvel utilisateur
        public function create() : Int {
            $datas = (new Post())->toArray();
            // logic...
            return $this->dm->create($this->structure, $datas );
        }

        # ID depuis N°badge
        public function findIdCustom() : Int {
            return dm()->findAll('user',[
                "filter" => [
                    "numero_badge" => (new Controller())->getLastURIParam()
                ]
            ])->get('id');
        }

        # Retourne le nom complet de l'utilisateur
        public function getNomComplet() {
            return implode(" ", [ $this->prenom, $this->nom] );
        }

        # Supprime l'utilisateur
        public function delete() {
            $this->_me()->delete(); # Supression de la structure
            $this->_unset();        # Vidage de l'entité
            return;
        }

        # Retourne la photo d'un utilisateur
        public function getPhoto() {
            $photo = "/assets/user/{$this->id}.jpg";
            $default = "/assets/user/default.jpg";
            return file_exists( $photo ) ? $photo : $default;
        }

    }

Emplacement d'utilisation depuis un controller :

    # ./controllers/UserInterfaceController.php

    class UserInterface extends Controller {

        /* Api call : /user/12 */
        #@Route = { "url" : "/user", "api" : true } 
        public function getUser( User $u ) {
            return ["user" => $u->object ];
        }

        /* Api call : /user/edit/12 */
        #@Route = { "url" : "/user/edit", "api" : true } 
        public function editUser( User $u, Post $p ) {
            $u->_updateField( $p->field, $p->value );
        }

        /* Api call : /user/photo/12 */
        #@Route = { "url" : "/user/photo", "api" : true } 
        public function getPhoto( User $u ) {
            return ["photo" => $u->getPhoto()];
        }


    }


Logger & Sécurité

Le composant Logger permet de gérer l'authentification et la persistence de la session des utilisateurs. Il permet aussi la génération de profiles de sécurités afin de protéger vos routes.

Configuration

Avant toute chose, il vous faut commencer par configurer le fichier sercurity afin de définir le comportement du Logger.

Le fichier ./config/security.yaml

Ce fichier est découpé en 4 sections qui sont toutes facultatives :

  • logger : parametrage de l'authentification
  • logout : parametrage de la deconnexion
  • rules : définition des profiles de sécurité
  • suggest : parametrage de sécurité du module Suggest

Si la section logger n'est pas définie, tout le reste sera ignoré.

Séction : logger
Paramètre Valeur Défaut Description
table string obligatoire Table à utiliser pour l'authentification
@fields array obligatoire Définition les deux noms des champs identifiant et mot de passe
hash boolean false Si true, .kernelite tentera de hasher le mot de passe pour comparaison.
Attention : ne fonctionne que si le mot de passe a été inséré en base avec la méthode hash de mot de passe de .kernelite.
@conditions array [] Conditions d'authentification sur la table
Définition des paramètres de @fields :
Nom du paramètre Valeur
login La valeur doit etre le nom du champ de la table qui fera office de login
password La valeur doit etre le nom du champ de la table qui fera office de mot de passe
Définition des paramètres de @conditions :

Les conditions sont des critères simples que doivent respecter les lignes de la table pour autoriser l'authentification. Par exemple : "deleted : 0"


Exemple de structure et de logger :

    # ./structures/user.yaml
    user :
        mail :
            is : string
        pass :
            is : string
            hash : true
        actif : 
            is : int
            default : 1


    # ./config/security.yaml
    logger :
        table: user
        fields : 
            login : mail
            password : pass
        hash : true
        conditions :
            actif : 1
            deleted : 0

Séction : logout
Paramètre Valeur Défaut Description
url string obligatoire URL de la route de deconnexion automatique du Logger
redirect string obligatoire Nom de la route de redirection après la déconnexion

Authentification

Une fois la configuration du logger terminé, vous pouvez désormais tenter de vous connecter à votre application. Pour se connecter via le Logger, il vous suffit d'envoyer une requete au serveur sur n'importe quelle route ne comportant que deux paramètres post : les deux champs définis dans security.yaml

Fonctionnement

Lors d'une requete, si le client n'est pas déjà connecté, le Logger analysera toujours les paramètres de celle-ci. Si le Logger ne trouve uniquement que les deux champs qui lui ont été définis comme étant les champs d'authentification, alors celui-ci tentera une connexion.

Authentification synchrone

Rien de plus simple, il vous suffit de générer un formulaire avec vos deux champs d'authentification, et de submit. Dans votre controller, vous pouvez réclamer le Logger et vérifier l'état de l'authentification.


    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( Logger $logger ) {
            if( $logger->loginAttemptStatus === true ) {
                echo "Il y a eu une tentative de connexion";
                if( $logger->loginAttemptSuccess === true )
                    echo "La tentative de connexion a reussi";
                else 
                    echo "La tentative de connexion a échoué";
            }           
        }
    }

  • loginAttemptStatus : (boolean) tentative de connexion
  • loginAttemptSuccess : (boolean) statut de la réussite de la connexion
Authentification asynchrone via API

De la même façon qu'en synchrone, n'importe quel appel au serveur avec les 2 champs d'authentification sera reconnu par le Logger comme une tentative de connexion si le client n'est pas déjà connecté.
Le serveur renverra alors un objet JSON avec la propriété login qui sera un boolean.

Exemple via jQuery :

   function connexion() {
      $.ajax({
          url : URL,
          method : 'POST',
          dataType : 'JSON',
          data : { mail : "jean@snew.fr", pass : "abcdef" },
          success : (e) => {
              if( e?.login == true ) alert('Connexion réussie')
              else alert('Connexion échouée')
          }
      }) 
   }

Exemple via .kerneliteJS :

   function connexion() {
      kernelite.login({ mail : 'jean@snew.fr', pass : 'abcdef' })
      .then( 
        resolve => kernelite.success('Connexion réussie'),
        reject => kernelite.error('Connexion échouée')          
      )
   }

Méthodes et propriétés

Voici la liste des propriétés et méthodes du Logger que vous pouvez utiliser.

Nom Type Description
loginAttemptStatus boolean Retourne true si il y a eu une tentative de connexion (réussie ou échouée)
loginAttemptSuccess boolean Retourne true s'il y a eu une tentative réussie de connexion
isConnected() boolean Retourne true si le client est connecté
logout() null Déconnecte le client
getLogoutRoute() string Retourne la route de deconnexion
userMatchRule( String:rule ) boolean Retourne true si le client match la règle de sécurité rule
Obtenir les informations de session

Dans votre controller, il est possible de récupérer les informations de session du Logger grace à la Request. Celle-ci possède une propriété session.


    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( Request $req ) {
            $session = $req->session; # La ligne de la table ayant servit à l'authentification
        }
    }

La globale USERID

Une fois le client identifié, le Logger définit une variable globale PHP : USERID qui contient l'id de la ligne utilisée dans la table d'authentification.


    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( Logger $logger ) {
            if( $logger->isConnected() )
                echo USERID;
        }
    }

Profils de sécurité

Grace au Logger, il est possible de définir différents profils de sécurité. La définition d'un profil est limité aux seules conditions présentes dans la table d'authentification. Les profils de sécurité permettent de sécuriser des routes ou de s'assurer que le client respecte des conditions spécifiques avant la réalisation d'une action.

Séction : rules

Dans le fichier ./config/security.yaml, il existe une section : rules. C'est ici que vous allez pouvoir décrire tous vos profils de sécurité.
Voici quelles sont les propriétés des profils de sécurité :

Nom Type Description
logger boolean Définit si l'état du logger doit être connecté ou pas
@fields array Tableau de paramètre des conditions de validation du profil

    # ./conf/security.yaml
    ...
    rules :
        connected :
            logger : true
        disconnected :
            logger : false
        admin : 
            logger : true
            fields :
                admin : 1 # correspond à un champ "admin" dans la table d'authentification
                deleted : 0
                actif : 1
        user : 
            logger : true
            fields :
                admin : 0
                deleted : 0
                actif : 1            
    ...

Sécuriser une route

Grace aux profils de sécurité, vous pouvez sécuriser l'accès à vos routes. Pour cela, il vous suffit d'ajouter la propriété security à votre route, et de lui donner en valeur un profil de sécurité.

Exemple de route "Mon Compte"

    myAccount :
        url : /MonCompte
        controller : User::myAccount
        security : connected       


Pour plus d'informations, voir Les routes : Sécuriser les routes

Tester un profil

Dans vos controllers, si vous avez besoin de tester si le client correspond à un profil de sécurité, vous pouvez utiliser la méthode du Logger userMatchRule qui prend en argument le nom d'un profil de sécurité et renvoi un boolean.


    # ./conf/security.yaml
    ...
    rules :
        ...
        admin : 
            logger : true
            fields :
                admin : 1
        ...      
    ...

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( Logger $logger ) {
            if( $logger->userMatchRule('admin') )
                echo "Vous correspondez au profil admin";
            else
                echo "Vous ne correspondez pas au profil admin";
        }
    }

Sécuriser la suggestion

Si vous utilisez le module de suggestion des structures .kernelite, vous pourriez avoir besoin de vous assurer qu'un client respecte certaines conditions afin de lui proposer une liste de suggestion pouvant être sensibles.
Pour cela, vous pouvez dans le fichier de configuration définir les profils de sécurité à respecter afin de permettre la suggestion sur vos structures.


    # ./conf/security.yaml
    ...
    suggest :
        ...
        user : admin
        marque : disconnected
        ...      
    ...

Dans cet exemple :

- on autorise la suggestion sur "user" uniquement aux clients qui respectent le profil de sécurité "admin"

- on autorise la suggestion sur "marque" uniquement aux clients qui respectent le profil de sécurité "disconnected"

Gestion des erreurs

.kernelite met à votre disposition plusieurs outils pour gérer les cas d'erreurs dans vos controllers.

La KernelError

Vous pouvez invoquer dans vos scripts la KernelError de .kernelite avec un message de votre choix :


    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( ) {
            throw new KernelError("Ceci est une erreur");
        }
    }


    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( ) {
            err("Ceci est une erreur"); # via la super globale err()
        }
    }

Lors d'une KernelError en synchrone et si vous êtes en DEV,
vous aurez alors accès à un dump de la Request ainsi que de l'historique du DataManager.

Error handler

.kernelite gère en DEV les erreurs PHP via la KernelError. Il vous est possible de modifier l'erreur handler vous même en dev et en prod.

Handler .kernelite

L'erreur handler par défaut de .kernelite est définit ici : ./kernelite/__initKernel.php et voici la portion de code concernée dans le fichier :


    # ./kernelite/__initKernel.php
    # Dev errors
    if( ENV == "DEV" ) {
        ini_set('display_errors', 1);
        ini_set('display_startup_errors', 1);
        error_reporting(E_ALL);
        set_error_handler("devErrorHandler", E_ALL);    
    }
    function devErrorHandler($errno, $errstr) { 
        throw new KernelError($errstr);
    }

Comme on peut le constater, aucun handler n'est définit par défaut en environnement de production.
Si vous le souhaitez, vous pouvez ajuster les alertes à souhait et même mettre en place votre propre error handler.

API Error

La méthode apiError vous permet lors d'un appel API de retourner un message d'erreur au client qui saura être interpretté par kerneliteJS.


    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( ) {
            $this->apiError("Ceci est une erreur");
        }
    }

Les services

Un service .kernelite est une classe PHP utilitaire pouvant être appelé si besoin par des controllers.
Par exemple, si nous avons une classe qui gère des calculs de taxe, cette classe est un utilitaire qui peut être utilisé par les controllers qui necessiteront un calcul de taxe.

Fonctionnement

Emplacement et nomenclature

Tous les services doivent être placés dans le dossier ./services à la base du projet .kernelite.
Le nom du fichier de serice devra être identique au nom de la classe du service.

Exemple de service :

    # ./services/MyClass.php
    class MyClass {
        public function add( Int $a = 0, Int $b = 0 ) {
            return $a + $b;
        }
    }

Emplacement de ce service :

    ./services
        MyClass.php


Délivrance au controller

Afin d'utiliser un service depuis un controller, il suffit de le demander en paramètre de vos méthodes.


    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( MyClass $obj ) {
            $somme = $obj->add(2,3); // 5
        }
    }

Service depuis service

Afin d'apeller un service depuis un service, la délivrance n'est pas disponible, il vous faudra l'instancier


    # ./services/MyClass.php
    class MyClass {
        public function add( Int $a = 0, Int $b = 0 ) {
            return $a + $b;
        }
    }

    # ./services/MyClass2.php
    class MyClass2 {
        public function addition( Int $a = 0, Int $b = 0 ) {
            $obj = new MyClass();
            return $obj->add($a,$b);
        }
    }
    

Les events .kernelite

Les events interviennent à différents moments clés lors du traitement .kernelite. Ils permettent d'intercepter des données générées automatiquement par .kernelite, de les modifier ou d'en ajouter.

Fonctionnement

Afin de déclarer des events, il faut commencer par créer un dossier events à la racine de votre projet.

Emplacement du dossier events :
        
            var 
                www
                    monprojet
                        .conf
                        .kernelite
                        .structures
                        assets
                        controllers
                        events                  # Créer le dossier à la racine du projet
                            fichier1.php        # Exemples de fichiers d'events
                            fichier2.php
                            fichier3.php
                        routes
                        services
                        templates
                        .htaccess
                        index.php

        
    

Dans le dossier events seront placés tous vos fichiers PHP d'interceptions d'evenements.

Liste des évenements

Voici la liste des évennements sur lesquels il est possible d'intervenir dans .kernelite.

Nom de l'event Paramètres Retour Description
define.superglobales aucun aucun Appelé lors de la déclaration des super globales PHP.
Permet de définir vos super globales.
kernelite.beforeStart aucun aucun Avant l'initialisation de .kernelite
define.favicon Controller String Appelé lors de la definition du favicon par défaut
define.defaultTemplateParameters Controller Mixed Appelé lors de la definition des paramètres par défaut de template
Les éléments retournés seront disponibles dans : $kParams['customs'] ou {{customs.<x>}}
kernelite.endInitialisation aucun aucun Après l'initialisation de .kernelite, avant le traitement de la requette
kernelite.beforeCall aucun aucun Appelé juste avant Controller::methode()

Intercepter un event

Afin d'intercepter un event, il est necessaire d'enregistrer un callable sur cet event.
Pour commencer, il faut créer un fichier PHP dans le dossier event : (peu importe son nom)

Création d'un fichier test d'event :
        
            var 
                www
                    monprojet
                        ...
                        events
                            test.php   
                        ...

        
    
Choisir un event :

Avant de commencer à coder votre event, il vous faudra vous rendre sur la Liste des évennements afin de trouver sur quel event .kernelite vous souhaitez intervenir.
Une fois votre event choisit, il ne vous reste plus qu'à déclarer votre callable lorsque cet event sera déclancé par .kernelite.

Exemples de déclaration de callable sur des event :

    # ./events/myFavicon.php
    # Remplacer le favicon par défaut
    Events::on('define.favicon',function( Controller $c ) {
        return 'https://kernelite.snew.fr/assets/img/favicon.ico';
    });


    # ./events/defaultParams.php
    # Ajouter aux paramètres de templates par défaut des données supplémentaires
    Events::on('define.defaultTemplateParameters',function( Controller $c ) {
        return [
            "date" => date('d/m/Y'),        # => Accessible via {{customs.date}}
            "time" => date('G\hi\ms')       # => Accessible via {{customs.time}}
        ];
    });


Mes super fonctions

Il possible de profiter du système de déclaration d'events afin de créer des super fonctions.
Dans .kernelite, la déclaration des events se fait très tôt dans le traitement, et donc en amont de toute forme d'initialisation.
C'est pour cela que c'est un endroit parfait afin de créer vos propres super fonctions qui seront par la suite accessibles partout dans .kernelite.

Qu'est ce qu'une super fonction ?

C'est une fonction PHP classique, déclarée en globale, et donc accessible partout.

Déclarer une super fonction :

Afin de déclarer une super fonction, il suffit de créer un fichier dans le dossier event, et d'y déclarer sa fonction (en faisant attention de ne pas écraser une fonction existante).

Création du fichier de super fonctions :

    monprojet
        ...
        events
            super.php   
        ...

    
Déclaration de super fonctions :

    # ./events/super.php

    if( !function_exists('abcde') ) {
        function abcde() {
            return 'abcde';
        }
    }
    if( !function_exists('addition') ) {
        function addition( Int $a, Int $b ) {
            return $a + $b;
        }
    }    

Utilisation de super fonctions :

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function test() {
            echo abcde();
            return addition( 5, 10);
        }
    }

Les super globales

.kernelite définit un certain nombre de variables et fonctions disponibles depuis n'importe ou afin d'en faciliter l'accès : ce sont les super globales .kernelite.

Les super globales sont accessibles depuis :

  • Vos controllers
  • Vos templates
  • Vos services
  • Vos events
  • Vos daemons

Certaines des fonctions super globales ont plusieurs alias.
A vous de choisir la manière que vous préférez pour les appeler.

Fonctions

Voici la liste des fonctions PHP définies en super globales dans .kernelite.

d( objet, ?buffer, ?caller )

La fonctions d() agit à peu près de la même manière qu'un var_dump. La différence est que d() est personnalisable.

Paramètre Type Défaut Description
objet mixed obligatoire Objet à dump, peut être de tout type
buffer boolean false Si true, retourne le dump sous format string et n'affiche rien
caller array debug_backtrace Pile d'execution des méthodes précédentes

🦄 Personnalisation : vous pouvez personnaliser l'apparence de vos dump d() en modifiant le fichier : ./conf/dump-styles.php


    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode( Request $req ) {
            d($req);
        }
    }

IndexController.php - ligne 400

Kernelite→processQuery ► Kernelite→processCall ► Index→home ► Index→getChapter ► include

<?php
 object
(Request)#6 (8) {
  
["request":"Request":private]=>
  array(
7) {
    [
"queryString"]=>
    array(
5) {
      [
"raw"]=>
      
string(36"QUERY_STRING=index.php&QUERY_STRING="
      
["value"]=>
      
string(0""
      
["empty"]=>
      
bool(true)
      [
"splited"]=>
      array(
1) {
        [
0]=>
        
string(0""
      
}
      [
"parsed"]=>
      array(
1) {
        [
0]=>
        
string(0""
      
}
    }
    [
"files"]=>
    array(
0) {
    }
    [
"api"]=>
    
bool(false)
    [
"session"]=>
    array(
0) {
    }
    [
"route"]=>
    array(
3) {
      [
"url"]=>
      
string(1"/"
      
["controller"]=>
      
string(11"Index::home"
      
["default"]=>
      
bool(true)
    }
    [
"input"]=>
    array(
0) {
    }
    [
"post"]=>
    array(
0) {
    }
  }
  [
"queryString"]=>
  array(
5) {
    [
"raw"]=>
    
string(36"QUERY_STRING=index.php&QUERY_STRING="
    
["value"]=>
    
string(0""
    
["empty"]=>
    
bool(true)
    [
"splited"]=>
    array(
1) {
      [
0]=>
      
string(0""
    
}
    [
"parsed"]=>
    array(
1) {
      [
0]=>
      
string(0""
    
}
  }
  [
"files"]=>
  array(
0) {
  }
  [
"api"]=>
  
bool(false)
  [
"session"]=>
  array(
0) {
  }
  [
"route"]=>
  array(
3) {
    [
"url"]=>
    
string(1"/"
    
["controller"]=>
    
string(11"Index::home"
    
["default"]=>
    
bool(true)
  }
  [
"input"]=>
  array(
0) {
  }
  [
"post"]=>
  array(
0) {
  }
}
?>
dd( objet )

Les initiales dd signifient "dump and die", cette méthode fait donc appel à d() puis effectue un die(). Cette fonctions est souvent utilisée afin de dump un objet et interrompre le script afin d'en debugger le contenu.

route( String:name ) r( String:name )

Fait un echo de l'URL de la route dont le nom a été fournit en paramètre.


    <a href="<?php route( 'myAccount' );?>" >Mon compte</a>

err( String:message )

Génère une erreur captée. Voir Gestion des erreurs : KernelError

sendmail( array ) 🚧

Version primitive. Consulter la version avancée : Envoi de mail
Envoi d'un mail rapide depuis un tableau associatif passé en paramètre.

Paramètre Type Défaut Valeur
to string obligatoire Adresse mail du destinataire
title string obligatoire Titre du mail
body string obligatoire Corps du mail
dm()

Retourne le DataManager global.

dm( string )

Retourne une nouvelle instance du DataManager sur la base de données passée en argument.
Revient au même que de faire : new DataManager( base )

req()

Retourne la Request globale.

structure( String:name ) s( String:name )

Retourne sous forme de tableau la définition de la structure dont le nom a été passé en paramètre.

form( String:structure )

Génère un formulaire à partir d'une structure (voir Structures .kernelite : Formulaires de structures)

form_widget( String:structure, String:propriété )

Génère un élément de formulaire à partir d'une structure (voir Structures .kernelite : Formulaires de structures)

__kernel_load_styles( Controller, Array:params )

Permet le chargement automatique des styles necessaires pour vos templates.

__kernel_load_scripts( Controller, Array:params )

Permet le chargement automatique des scripts necessaires pour vos templates.

join_paths( Array )

Retourne un chemin en ayant concaténé les différents éléments du tableau passé en paramètre avec le DIRECTORY_SEPARATOR

myDir( name )

Retourne le path du dossier name définit dans conf.yaml

Constantes

Voici la liste des constantes disponibles :

  • ENV : Environnement : "DEV" ou "PROD" selon la configuration
  • PROJECT_NAME : Nom de votre projet
  • URL : Lien vers votre application
  • TMP : Chemin vers le fichier de stockage temporaire des fichiers
  • FILES : Chemin vers le stockage des fichiers
  • USERID : Valeur de l'identifiant du client loggé avec le Logger

Core functions

La classe core de .kernelite contient des fonctions utilisées globalement par le système.
Le développeur peut aussi librement utiliser ces fonctions dans son projet.

core::getFilesFromDir( path )

Retourne la liste des fichiers d'un répertoire

core::minMaxLength( string $str, int $min, int $max )

Retourne true si la longueur de $str est comprise entre $min et $max

core::dateOutput( $date )

Retourne au format dd/mm/YYYY une date passée au format yyyy-mm-dd

core::dateInput( $date )

Retourne au format yyyy-mm-dd une date passée au format dd/mm/YYYY

core::dateCourte( $date )

Retourne au format yyyy-mm-dd une date passée au format dd/mm/YYYY hh:ii:ss ou yyyy-mm-dd hh:ii:ss

core::dateFrom( $date )

Retourne la durée textuelle écoulée depuis la date passée en paramètre, par exemple : "Il y a deux semaines"

core::mustacheIt( $string, array $params )

Applique le render de Mustache sur la chaine passée en paramètre.
Attention : cette fonction n'applique pas le render de .kernelite mais uniquement celui de Mustache.

core::isMailValid( $string )

Retourne true si le mail passé en argument est un mail valide.

core::arrayToHtmlTable( array $table, string $id, array $headers )

Retourne une string contenant une version HTML d'un tableau passé en argument.

core::normalizePath( $string )

Retourne une chemin syntaxiquement valide sur le système à partir du chemin passé en paramètre.

core::generateString( int $length, boolean $alphaOnly = false )

Retourne une chaine alphanumérique aléatoire d'une longueur $length.
Cette chaine sera uniquement alpha si le paramètre $alphaOnly est passé à true.

core::readableSize( int $bytes, int $precision = 2 )

Retourne une version lisible humainement d'un poids en bytes

core::getTrace()

Retourne une string contenant la debug backtrace PHP.

Les Daemons (cron) .kernelite

Les daemons .kernelite sont des scripts d'execution de taches planifiées.
Communément appelées "cron" sous Unix, ces taches sont programmées pour tourner à des moments précis.
.kernelite facilite l'accès et l'intégration de ces taches.

Installation

Environnement

Pour la suite des explications, l'environnement utilisé sera Unix. Il est théoriquement possible de procéder aux mêmes opérations sous Windows ou MAC mais la documentation l'installation des daemons pour ces environnements arrivera plus tard.

Initialisation la CRONTAB Unix

Afin d'activer la fonctionnalité des daemons .kernelite,
Il vous faudra un accès SSH sur le serveur afin d'accéder à la modification de la crontab.
Une fois connecté au serveur, saisissez la commande suivante afin d'ouvrir la crontab en édition :


    $> crontab -e

Une fois la crontab ouverte en édition, placez-vous au bas du fichier et collez cette ligne :
en remplacant bien : /chemin/vers/mon/projet/ par le chemin de votre projet.


 * * * * * /usr/bin/php /chemin/vers/mon/projet/index.php  >/dev/null 2>&1

Enregistrez puis quitter le fichier (En général : CTRL+X pour quitter puis enregistrer).
La crontab étant désormais à jour, vos daemons peuvent désormais s'executer.

Créer un fichier daemon

Dossier des daemons

Afin de créer votre premier daemon, il faudra créer le dossier des daemons .kernelite.
Pour cela, il suffit de créer un nouveau dossier .daemons à la racine de votre projet.

Création d'un fichier de daemon :
        
            var 
                www
                    monprojet
                        ...
                        .daemons
                            test.php   
                        ...

        
    
Fichiers des daemons

Dans le dossier .daemons, vous pouvez créer autant de fichiers nommés comme il vous plaira.
Un fichier peut contenir un ou plusieurs daemons.

Déclarer un daemon

Dossier des daemons

Afin de déclarer un daemon, placer vous dans votre fichier daemon (par exemple : ./dameons/test.php), et enregistré votre script comme ceci :

Enregistrement d'un daemon :

    Daemon::register(String $name, String $timing , Callable $function);

Paramètres de déclaration d'un daemon :
Nom Type Valeur
name string Le nom de votre daemon (utilisé pour les executions manuelles)
timing string La fréquence d'execution du daemon
function callable La fonction (script) de votre daemon ($Kernelite sera envoyé en paramètre optionnel)
Exemple de déclaration d'un daemon :

    # Daemon qui, une fois par jour, insère dans la table "date_execution", une ligne contenant le moment d'execution
    Daemon::register("testDaemon", "daily", function( $Kernelite ) {
        dm()->create('execution_daemon',[
            "date_execution" => date('Y-m-d H:i:s')
        ]);
    });

Timing des daemons

Liste des différents timming possibles de daemon :
Valeur Description
* Toutes les minutes
hourly Toutes les heures à la minute 0
daily Touts les jours à 00h00
m/x Toutes les x minutes (ex : m/11 = toutes les 11 minutes)
h/x Toutes les x heures à la minute 0 (ex : h/2 = toutes les 2 heures)

Tester les daemons

Une fois votre daemon terminé, vous devez le tester avec le compte utilisateur qui a déclaré la crontab afin d'éviter les eventuels problèmes de droits.
En effet, c'est bien l'utilisateur avec lequel vous vous êtes connecté en SSH qui executera la crontab et donc le script de votre daemon.

Pour la suite des exemples, imaginons que notre projet .kernelite se situe dans : /var/www/projet/

Tester manuellement tous les daemons :

Pour cela, il suffit d'appeler en ligne de commande, le fichier index.php situé à la racine de votre projet .kernelite.
Les timings de vos daemons seront prit en compte au moment de l'execution manuelle.


    $> php /var/www/projet/index.php

Le mode verbose :

Il est vivement consillé d'utiliser le mode verbose afin de comprendre ce qu'il se passe lors de l'excution test des daemons.
.kernelite affichera dans la console toutes les étapes d'excution des daemons.


    $> php /var/www/projet/index.php --verbose

Forcer l'execution d'un daemon manuellement :

Si vous définissez que votre daemon ne doit d'excuter qu'une fois par jour, vous n'allez pas attendre minuit prochain pour tester votre script.
Pour cela, .kernelite propose l'option --only:[name] afin de forcer l'excution d'un daemon spécifique.


    $> php /var/www/projet/index.php --verbose --only:"testDaemon"

Logs d'excution

Logs d'execution manuelle :

La méthode register peut attendre en retour un Array ou String qui sera concidéré comme votre log personnel d'execution du daemon.
Lors de l'execution manuelle en mode --verbose, votre log sera affiché dans la console.

Exemple de déclaration d'un daemon qui retourne des logs :

    Daemon::register("testDaemon", "daily", function( $Kernelite ) {
        $log = [];
        $log[] = "Début d'execution de mon script : testDaemon";
        ...
        $log[] = "Tout se passe bien";
        ...
        $log[] = "Fin d'execution de mon script : testDaemon";
        return $log[];
    });

Les connecteurs

.kernelite propose de vous simplifier la vie avec ses propres connecteurs.
Les fonctionnalités sont surcouchées afin d'aller au plus simple et à l'essentiel des connections.

Les connecteurs ne sont pas préchargés dans .kernelite, il vous faudra les invoquer avec la méthode connector()

Imap

Si vous avez besoin de vous connecter à une boite mail en Imap, .kernelite vous propose un connecteur simplifié.
Celui-ci peut générer une boite mail virtuelle (image de l'originale) sous forme d'un tableau PHP facile à lire et à manipuler.

Invoquer le connecteur et l'initialiser

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function testImap() {
            connector("Imap");                                  # Invoquer le connecteur Imap de .kernelite

            $imapString = "mail.provider.net:443/imap/ssl";
            $user = "user@domain.fr";
            $pass = "123456"

            $i = new Imap( $imapString, $user, $pass );         # Initilisation de la connexion
        }
    }

Debugger la connexion

Si vous n'arrivez pas à vous connecter, vous pouver, lors des développements, passer la connexion Imap en mode debug en ajoutant le paramètre true au constructeur.


    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function testImap() {
            connector("Imap");                                  # Invoquer le connecteur Imap de .kernelite

            $imapString = "mail.provider.net:443/imap/ssl";
            $user = "user@domain.fr";
            $pass = "123456"

            $i = new Imap( $imapString, $user, $pass, true );   # Initilisation de la connexion en mode DEBUG
        }
    }

Liste des méthodes du connecteur Imap :
getImapInfos()

Retourne un tableau avec les proriétés suivantes de la boite mail :

  • Date - date système de la boite mail
  • Driver - protocole de connexion utilisé (IMAP)
  • Mailbox - nom de la boite mail
  • Nmsgs - nombre de messages dans la boite mail
  • Recent - nombre de messages récents dans la boite mail

getMailBox( $flag = "ALL" )

Cette méthode lit la totalité de la boite mail courante et retourne un tableau multidimensionnel facile à exploiter contenant tous les mails et leurs détails.
Le paramètre $flag permet de filtrer le contenu de la boite mail.
Par défaut, tous les mails sont retournés, mais il possible de choisir un flag parmit cette liste :

  • ALL - return all messages matching the rest of the criteria
  • ANSWERED - match messages with the \\ANSWERED flag set
  • BCC "string" - match messages with "string" in the Bcc: field
  • BEFORE "date" - match messages with Date: before "date"
  • BODY "string" - match messages with "string" in the body of the message
  • CC "string" - match messages with "string" in the Cc: field
  • DELETED - match deleted messages
  • FLAGGED - match messages with the \\FLAGGED (sometimes referred to as Important or Urgent) flag set
  • FROM "string" - match messages with "string" in the From: field
  • KEYWORD "string" - match messages with "string" as a keyword
  • NEW - match new messages
  • OLD - match old messages
  • ON "date" - match messages with Date: matching "date"
  • RECENT - match messages with the \\RECENT flag set
  • SEEN - match messages that have been read (the \\SEEN flag is set)
  • SINCE "date" - match messages with Date: after "date"
  • SUBJECT "string" - match messages with "string" in the Subject:
  • TEXT "string" - match messages with text "string"
  • TO "string" - match messages with "string" in the To:
  • UNANSWERED - match messages that have not been answered
  • UNDELETED - match messages that are not deleted
  • UNFLAGGED - match messages that are not flagged
  • UNKEYWORD "string" - match messages that do not have the keyword "string"
  • UNSEEN - match messages which have not been read yet

Attention !
Cette méthode retourne tous les mails de la boite ainsi que leurs pièces jointes encodées en base64.
Soyez prudent si vous décidez de dumper le contenu de la boite.
Exemple d'un mail obtenu par getMailBox()
    
    array(2) {
        ["header"]=>
            array(7) {
                ["msg_id"]=>
                    string(64) "<5c2c4376-d6fc-4b88-880c-fb0920bbbd9e@smtp-relay.monrelais.com>"
                ["msg_no"]=>
                    int(15)   # Correspond à l'index du mail dans la boite mail courante
                ["date"]=>
                    string(19) "2023-02-14 11:01:11"
                ["subject"]=>
                    string(56) "Sujet du mail"
                ["from"]=>
                    string(22) "adresse mail du from"
                ["sender"]=>
                    string(22) "adresse mail du sender"
                ["size"]=>
                    string(6) "134396"
            }
        ["content"]=>
            array(6) {
                ["params"]=>
                    array(2) {
                        ["name"]=>
                            string(55) "document.pdf"
                        ["filename"]=>
                            string(55) "document.pdf"
                    }
                ["attachments"]=>
                    array(1) {
                        ["document.pdf"]=>
                            string(35) "Pièce jointe encodée en base64..."
                    }
                ["charset"]=>
                    string(0) "charset du corps du mail"
                ["html"]=>
                    string(0) "contenu du mail en html"
                ["plain"]=>
                    string(0) "contenu du mail en plain text"
                ["subparts"]=>
                    array(0) {
                        // sub parts
                    }
            }
    }
    
markAsRead( Int )

Place le flag "READ" sur le mail à l'index passé en argument dans la boite courante

deleteMail( Int )

Supprime le mail à l'index passé en argument dans la boite courante.
Il ne faut pas que la boite mail soit en READONLY.

.kerneliteJS

Le framework .kernelite met à votre disposition une multitude de fonctionnalité javascript client fonctionnant a merveille avec la partie PHP Serveur de .kernelite. C'est ce que l'on appelle .kerneliteJS.
.kerneliteJS se repose sur plusieurs librairies externes (jQuery, Swal, notyf,...) et vous concentre un maximul de fonctionnalité en une seule librairie dont l'utilisation a été simplifiée au maximum.

.kerneliteJS est une librairie client au même titre que jQuery et non un language serveur comme l'est NodeJS
.kerneliteJS est faite pour fonctionner avec .kernelite et ne peut donc pas être exportée vers d'autres projets
Utiliser .kerneliteJS

Toutes les méthodes de .kerneliteJS sont accessibles comme ceci :


    // ./assets/js/app.js
    function maFonction() {
        kernelite.success('.kerneliteJS !')
    }

    
Alias de confort

Si vous souhaitez raccourcir kernelite dans vos JS, il existe par défaut l'alias : kJS :


    // ./assets/js/app.js
    function maFonction() {
        kJS.success('.kerneliteJS via kJS !')
    }

    

Mais sachez que vous pouvez créer vos propres alias :


    // ./assets/js/app.js
    const µ = kernelite;
    function maFonction() {
        µ.success('.kerneliteJS via µ !')
    }

    

Appel API

kernelite.api( URL, {json} )

Afin de réaliser des appels API vers vos routes .kernelite, vous pouvez utiliser la méthode api :

Paramètre Type Défaut Description
URL string obligatoire URL de la route à appeller
params json {} Paramètres post à transmettre à votre route

Via l'utilisation de kernelite.api, le catch et le apiError sont gérés automatiquement.


    // ./assets/js/app.js
    function maFonction() {
        kJS.api('/maRouteApi',{
            prenom : "Jean"
        }).then( reponse => {
            kJS.modal.fire({
                icon : 'info',
                text: reponse.message
            }) 
        })
    }

    
La méthode kernelite.api retourne une promesse

Notifications

kernelite.success( message )

Affiche une notification qui disparait seule sur fond vert avec votre message


    // ./assets/js/app.js
    function maFonction() {
        kernelite.success('ok')
    }
    
kernelite.error( message )

Affiche une notification qui disparait seule sur fond rouge avec votre message


    // ./assets/js/app.js
    function maFonction() {
        kernelite.error('ko')
    }
    
kernelite.progress( message )

Affiche une notification qui ne disparait pas sur fond rouge avec votre message


    // ./assets/js/app.js
    function maFonction() {
        kernelite.progress('En train de faire un truc...')
    }
    
kernelite.dismiss()

Masque et supprime toutes les notifications visibles


    // ./assets/js/app.js
    function maFonction() {
        kernelite.progress('Disparition dans 2 secondes...')
        setTimeout( () => {
            kernelite.dismiss()
        },2000);
    }
    

Les modales

.kernelite fait appel à la puissance de la librairire https://sweetalert2.github.io/ afin d'offrir au développeur l'une des meilleures solutions de gestion des modales.

Intégration de SweetAlert2 à .kernelite :

Par défaut, SweetAlert2 est déjà intégré à .kernelite de cette façon :


    // ./assets/js/.kernelite/kenerlite.js
    kernelite.modal = Swal;

Ainsi, vous pouvez appeler toutes les méthodes de la documentation de SweetAlert2 de cette manière :


    // ./assets/js/app.js
    kernelite.modal.fire({
        icon: 'error',
        title: 'Oops...',
        text: 'Something went wrong!',
        footer: '<a href="">Why do I have this issue?</a>'
    })

kernelite.modal.success( message )

Invoque une une modale de type success avec votre message


    // ./assets/js/app.js
    kernelite.modal.success("Ceci est une réussite.")
    
kernelite.modal.error( message )

Invoque une une modale de type erreur avec votre message


    // ./assets/js/app.js
    kernelite.modal.error("Ceci est une erreur.")
    
kernelite.modal.confirm( {params} )

Invoque une modale SweetAlert2 avec demande de confirmation et retourne une promesse


    // ./assets/js/app.js
    kernelite.modal.confirm({
        "title" : "Mon titre",
        "text" : "Voulez-vous valider cette fenêtre ?",
        "confirmButtonText" : "Avec plaisir !",
        "denyButtonText" : "Finallement, non."
    }).then(
        (ok) => {
            kernelite.success('Resolve() !');
        },
        (ko) => {
            kernelite.error('Reject() !');
        }
    )
    
kernelite.modal.prompt( title, text, [preval] )

Invoque une modale SweetAlert2 avec un prompt et retourne une promesse contenant la saisie du prompt


    // ./assets/js/app.js
    kernelite.modal.prompt("Quel est votre prénom ?", "Veuillez saisir votre prénom dans le champ ci-dessous", "Michel")
    .then( prenom => kernelite.modal.success(prenom) )
    
kernelite.successReload( message )

Invoque une une modale de type success avec votre message, puis recharge la page


    // ./assets/js/app.js
    kernelite.successReload("Ceci est une réussite qui va recharger la page.")
    
kernelite.errorReload( message )

Invoque une une modale de type error avec votre message, puis recharge la page


    // ./assets/js/app.js
    kernelite.errorReload("Ceci est une erreur qui va recharger la page.")
    

Le layer

Toujours basé sur la librairire SweetAlert2, le Layer permet d'afficher un fragment HTML ou bien même une page (via iframe) dans un caclque superposé au contenu de votre application.

kernelite.layer( {params} )
Paramètre Type Défaut Description
html string null Contenu HTML du Layer
width string 90% Taille en pourcentage du Layer par rapport à la fenêtre
confirmButtonText string "Fermer" Texte du bouton pour fermer le calque
class string kernelite-layer-class Classe CSS pour afficher le layer (./assets/css/vendor/kernelite.css)
Exemple d'utilisation basique :

    // ./assets/js/app.js
    kernelite.layer({
        html : '<p class="text-center"><strong>Voici un lien :</strong> <a href="#">Lien</a></p>',
        width : '50%'
    })
    
Insérer une iframe dans le Layer

Exemple d'utilisation du Layer avec une iframe


    // ./assets/js/app.js
    kernelite.layer({html : '<iframe src="//snew.fr" style="width:100%;min-height:500px;"></iframe>' })
    
API + Layer

Exemple d'utilisation du Layer après être allé chercher le contenu via API


    // ./assets/js/app.js
    kjs.progress("Chargement...");
    kernelite.api('/getPageTest')
    .then( reponse => {
        kernelite.layer({
            html : reponse.page
        })
        kjs.dismiss();
        kernelite.success('Layer chargé !');
    })  
    

Authentification

Il est possible de procéder à l'authentification .kernelite en assynchrone via un appel API au serveur ne comportant que les champs d'authentification. Pour cela, .kernelite vous facilite cette action en vous proposant une méthode pré-construite assurant ce rôle.

kernelite.login( {params} )

La méthode login retourne une promesse. Voici un exemple d'authentification en partant du principe que le Logger attends les champs : mail et pass :


    // ./assets/js/app.js
    kernelite.login({
        mail : 'jean@snew.fr',
        pass : 'abcdef'
    }).then(
        (success) => kernelite.success('Vous êtes connecté'),
        (fail) => kernelite.error('Authentification échouée'),
    )
    
Pour plus d'informations sur l'authentification, voir Logger & Sécurité : Authentification

Utilitaires

.kerneliteJS contient une multitude de fonctionnalités utilitaires qui pourront vous rendre service.

klog( mixed, backtrace? )

Surcouche .kernelite du console.log() avec la possibilité d'activer la backtrace de l'appel.

kernelite.isNull( mixed )

Cette méthode retourne true si l'objet passé en argument est null,vide,undefined ou égal à zéro. Fonctionne sur tous les types.

kernelite.length( mixed )

Retourne la longueur de l'objet passé en paramètre. Fonctionne sur tous les types.

kernelite.reload() kernelite.refresh()

Recharge la page

kernelite.getURL()

Retourne l'URL courante de l'application

kernelite.inURL( string )

Retourne true si la chaine de caractères passé en argument est trouvée dans l'URL de l'application

kernelite.humanFileSize( bytes )

Retourne une version lisible et compréhensible d'un nombre de bytes (ex : '25 Mo' à la place de '26214400 bytes' )

kernelite.formToJson( string )

Serialize le formulaire d'id #string passé en paramètre et le retourne au format JSON

kernelite.toArray( object )

Retourne un Array à partir de l'object envoyé en paramètre

kernelite.navigate( URL, boolean ) kernelite.nav( URL, boolean )

Envoi le client vers l'URL passé en paramètre. Le second paramètre est un Booléan (par défaut : false) pour ouvrir le lien dans une nouvelle fenêtre

kernelite.tooltips()

Active tous les tooltips Bootstrap5 de la page pour les éléments ayants l'attribut : data-bs-toggle="tooltip"

/async/ kernelite.isConnected()

Cette méthode permet de savoir de façon asynchrone si le client est connecté avec le Logger


    // ./assets/js/app.js
    async function maMethode() {
        await kernelite.isConnected() ? kernelite.success('Connecté !') : kernelite.error('Déconnecté !');
    }
    
Les dates

Accès aux informations facilité pour les données de dates :

kernelite.date.getTimestamp( string )

Retourne un timestamp de la date passée en paramètre ou de la date actuelle


    // ./assets/js/app.js
    kernelite.date.getTimestamp();                  # Output : 1648118478882
    kernelite.date.getTimestamp( "2022-03-24" );    # Output : 1648080000000

kernelite.date.get( format, full, value )

Retourne la date du jour (ou celle passée en value) sous forme formatée

Paramètre Type Défaut Description
format boolean false Si true, format francais : jj/mm/YYYY. Si false, format US : YYYY-mm-jj
full boolean false Date complète en ajoutant les heures, minutes et secondes
value string null Applique la méthode get sur la value plutot que sur la date actuelle

    // ./assets/js/app.js
    kernelite.date.get();                                       # Output : '2022-03-24'
    kernelite.date.get( true );                                 # Output : '24/03/2022'
    kernelite.date.get( fase, true );                           # Output : '2022-03-24 11:48:53'
    kernelite.date.get( true, true );                           # Output : '24/03/2022 11h48min53'
    kernelite.date.get( true, false, "2022-03-24 11:48:15" );   # Output : '23/03/2022 11h48min15'

Easy-binds

Les EasyBinds .kernelite vous permettent de créer des binds efficacement et rapidement.
Ces binds sont rattachés au document (et non pas sur l'élément lui même) afin d'éviter d'avoir à redéclarer les binds en cas de mise à jour du DOM.
L'object jQuery $(this) sera envoyé en paramètre à la fonction callback.

kernelite.binds( [ [object,event,callback] ] )

    // ./assets/js/app.js
    kernelite.binds([
        ["#btn1","click","foo"],
        ["#div2","mouseleave","bar"],
    ])
    const foo = () => alert('foo')      # Alerte "foo" si on clique sur #btn1
    const bar = () => alert('bar')      # Alerte "bar" si on la souris quitte #div2

kernelite.clicks( [ [object,callback] ] )

    // ./assets/js/app.js
    kernelite.clicks([   # Alias de kernelite.binds, avec uniquement : click
        ["#btn1","foo"],                
        ["#div2","bar"],
    ])
    const foo = () => alert('foo')          # Alerte "foo" si on clique sur #btn1
    const bar = () => alert('bar')      # Alerte "bar" si on clique sur #div2

kernelite.click( [object,callback] )

    // ./assets/js/app.js
    kernelite.click("#btn1","foo")
    const foo = () => alert('foo')
    
    // Peut aussi d'écrire
    kernelite.click("#btn2", () => alert('bar') )



Parametres

Si vous avez besoin de stocker des informations temporaires dans le navigateur de votre client, les Paramètres .kernelite sont là pour cela.

Fonctionnement via Cookies

Les Paramètres .kernelite utilisent les Cookies du navigateur du client pour exister.
Tous vos paramètres sont encodés dans une chaine, et stockés dans les Cookies du navigateur.

kernelite.params.set( name, value )

Sert à stocker un paramètre name de valeur value dans les Paramètres .kernelite.


    // ./assets/js/app.js
    kernelite.params.set('prenom','Jean');
    kernelite.params.set('user', { prenom : 'Jean', nom : 'Dupont' });
    kernelite.params.set('lastConnexion', kernelite.date.get(true) );

kernelite.params.get( name )

Sert à récupérer la valeur d'un Paramètre .kernelite stocké à la clé name


    // ./assets/js/app.js
    kernelite.params.get('prenom');             # Output : Jean
    kernelite.params.get('user');               # Output : { prenom : 'Jean', nom : 'Dupont' }
    kernelite.params.get('lastConnexion');      # Output : 24/03/2022
    
kernelite.params.reset()

Efface tous les Paramètres .kernelite des Cookies de navigation du client.

Attention !
Les Cookies de navigation sont des données clients et sont stockés en clair.
Ils peuvent donc être modifiés par le client à tout moment.
Veillez à ne pas utiliser les Paramètres .kernelite pour stocker des données sensibles.

Upload de fichier

L'upload de fichier de .kernelite vous permet de charger simplement un fichier sur le serveur.
En retour, .kernelite retourne l'emplacement temporaire du fichier déposé.


    // ./assets/js/app.js
    kernelite.upload( <params?> ).then( reponse => {
        klog(reponse); // Voir console
    })
    
Que fait kernelite.upload() ?

Cette méthode génère un upload de fichier unique.
Puis créé un repertoire temporaire dans le dossier TMP du serveur
Puis dépose les fichiers dans ce répertoire temporaire
Puis renvoi au client le nom du dossier temporaire ainsi que la liste des fichiers

Liste des paramètres possibles (aucune option n'est obligatoire) :

    // ./assets/js/app.js
    kernelite.upload({
        size : int,                        // Taille maximale du fichier en bytes
        formats : array,                   // Liste des formats (extensions) autorisés
        progressMessage : string,          // Message d'upload, "Chargement..." par défaut
        multiple : boolean,                // Permission de charger plusieurs fichiers (par défaut : false)
        accept : string,                   // Contenu de l'attribut HTML 5 "accept" afin de cibler des types de fichiers
    }).then( reponse => {
        klog(reponse); // Voir console
    })
Que retourne kernelite.upload() ?

Cette méthode retourne un JSON contenant ce qui a été uploadé et les emplacements.


    {
        success : true,
        tmp : "d9dcfdc566349bffe7f4cb32bb777196",
        files : [
            'monfichier.pdf'
        ]
    }

Emplacement des fichiers

Dans le cas de l'exemple ci-dessus, les fichiers sont :


    monprojet/
        ...
        tmp/
            d9dcfdc566349bffe7f4cb32bb777196/
                monfichier.pdf

Le dossier tmp correspond à la variable de configuration générale user_tmp_files qui se situe dans le fichier : ./conf/my-project.php
Que faire de ces informations ?

Une fois l'upload .kernelite terminé, vous pouvez appeler l'un de vos controllers via API (en lui envoyant les données sur les fichiers obtenus) afin d'effectuer vos traitements.


    // ./assets/js/app.js
    kernelite.upload().then( reponse => {
        kernelite.api('/TraitementDeMonFichier',{
            directory : reponse.tmp,
            files : reponse.files
        })
    })
Comment déplacer mon fichier ?

Dans votre méthode de controlleur, vous aurez certainement besoin de déplacer votre fichier du répertoire temporaire. Pour cela, .kernelite met à la disposition du développeur le FileManager.


    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function TraitementDeMonFichier( FileManager $fm, String $dirTemp, Array $files ) {
            $destination = myDir('mes-fichiers'); # Emplacement de destination
            foreach( $files as $file ) {
                $tmpPath = join_paths(kRoot(),TMP,$dirTemp,$file);
                $destinationFile = join_paths($destination,$file);
                $fm->moveFile($tmpPath,$$destinationFile);
            }
            return;
        }
    }

Comment supprimer le dossier temporaire ? Avec kernelite.removeTmp( tmpDir )

Une fois votre traitement terminé, si vous souhaitez supprimer le dossier temporaire de dépose,
vous pouvez utiliser la méthode kernelite.removeTmp( tmpDir ) qui prend en argument le nom du dossier temporaire.


    // ./assets/js/app.js
    kernelite.upload().then( reponse => {
        kernelite.api('/TraitementDeMonFichier',{
            directory : reponse.tmp,
            files : reponse.files
        }).then( () => {
            kernelite.removeTmp( reponse.tmp )
        })
    })

kernelite.removeTmp supprime le dossier et son contenu s'il reste des éléments dans le dossier

Librairies externes

.kernelite fonctionne en se reposant sur plusieurs librairies. Si vous voulez en savoir plus, vous trouverez ici les liens vers leurs documentations.

Toutes ces librairies sont incluses par défaut dans .kernelite

Documentations

Bootstrap 5.1.3 CSS & JS

Lien vers la documentation : https://getbootstrap.com/docs/5.1/getting-started/introduction/

Fontawesome 6.1.1

Lien vers la documentation : https://fontawesome.com/

Mustache 5

Lien vers la documentation : https://mustache.github.io/mustache.5.html

Notyf

Lien vers la documentation : https://carlosroso.com/notyf/

SweetAlert2

Lien vers la documentation : https://sweetalert2.github.io/

jQuery 3.6.0

Lien vers la documentation : https://api.jquery.com/

jQuery UI 1.13.1

Lien vers la documentation : https://api.jqueryui.com/

Popper JS 2.10.2

Lien vers la documentation : https://popper.js.org/docs/v2/

js-cookie 3.0.1

Lien vers la documentation : https://github.com/js-cookie/js-cookie

Thèmes .kernelite

Vous retrouverez ici une bibliothèque de projets "préfabriqués" pour .kernelite.

Dashboard

Démo Télécharger

Plugins & Composer

Grace à la puissance de composer et la maniabilité de .kernelite, vous pouvez installer vos plugins avec une grande aisance.

Plugins .kernelite

Les plugins .kernelite sont des fichiers (JS/CSS) qui peuvent être invoqués à la demande dans vos templates.
Si un module (JS/CSS) est utilisé à deux endroits distinct de votre projet et par des controllers différents, afin d'éviter de dupliquer le code du module, il vous suffit d'utiliser le système de plugins .kernelite.

Créer plugin .kernelite :

Pour commencer, il faut créer un dossier du nom de votre plugin dans ./assets/plugins/.
Par exemple : ./assets/plugins/test/

A l'interieur de ce dossier, nous allons placer des fichiers JS & CSS qui concernent notre plugin.

Par exemple :

  • ./assets/plugins/test/test.js
  • ./assets/plugins/test/test.css

Importer un plugin .kernelite :

Une fois votre plugin .kernelite en place, il ne vous reste plus qu'a demander à render() de vous le fournir.


    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function maMethode() {
            $this->render(
                '/path/template',           # Fichier template
                [...],                      # Paramètres de template
                [                   
                    "plugins" => [          # Auto-chargement des fichiers du plugin
                        'test/test.js',
                        'test/test.css',
                    ]
                ]
            );
        }
    }

Ainsi, le plugin ne sera chargé que pour les méthodes qui y feront appel et il ne polluera la totalité de pages de votre projet.

Installer Composer

Composer est un logiciel gestionnaire de dépendances libre écrit en PHP. Il permet à ses utilisateurs de déclarer et d'installer les bibliothèques dont le projet principal a besoin.

Installation

Pour commencer il vous faudra installer composer : https://getcomposer.org/download/

Utiliser composer

Afin d'utiliser composer, il vous faudra vous placer à la racine de votre projet en ligne de commande.
Si vous utilisez VScode, dans l'onglet "Terminal" > "Nouveau terminal" > "<mon projet>".

Ajouter un plugin

Pour ajouter un nouveau plugin avec Composer, il vous faudra taper dans votre invitation de commande : composer require library (library représente le nom du plugin).

Structure du projet

Lors de l'installation d'un plugin, Composer va alors créer de nouveaux dossiers & fichiers à la racinne de votre projet.

  • ./vendor : contient toutes les dépendances necessaires au fonctionnement des plugins
  • composer.json : liste les plugins installés et leurs versions
  • composer.lock : liste figée de l'état des packages composer (à ignorer)

mPdf - Générer des PDF


    composer require mpdf/mpdf

Lien vers la documentation de mpdf : https://mpdf.github.io/

Exemple d'utilisation pour générer un PDF content "Hello World" :

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function generatePDF() {
            $mpdf = new \Mpdf\Mpdf();
            $mpdf->WriteHTML('Hello World');
            $mpdf->Output();
        }
    }

Pour faire simple, mpdf prend en argument de sa fonction WriteHTML( ... ) une chaine de caractères et la transorme en PDF.

Exemple d'utilisation pour générer un PDF dans .kernelite :

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function generatePDF() {
            $file = join_paths( [myDir('templates'),"exemple.php"] );

            /* Via buffer */
            ob_start();
            include( $file ); 
            $html = ob_get_contents();
            ob_end_clean();

            /* Via lecture */
            $html = file_get_contents($file);

            $mpdf = new \Mpdf\Mpdf();
            $mpdf->WriteHTML($html);
            $mpdf->Output();
        }
    }

Envoi de mails


    composer require phpmailer/phpmailer

Lien vers la documentation de PHPMailer : https://github.com/PHPMailer/PHPMailer

Ajouter PHPMailer dans votre projet.yaml :

    conf :
        ...
        PHPMailer :
            debug : true        # Mode verbose
            smtp :
                use : true      # Utilisation d'un SMTP 
                host :          # Adresse du SMTP
                auth : true     # Authentification au près du serveur 
                login :         # Utilisateur
                password :      # Mot de passe
                port :          # Port de connexion
                secure :        # vide, "ssl" ou "tls"


Utilisation basique via kPHPMailer (Surcouche .kernelite de PHPMailer) :

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function envoieMail( kPHPMailer $mail ) {
            $mail->to( 'jeanjean@snew.fr' );
            $mail->setSubject('Ceci est un mail');
            $mail->setBody('Contenu du mail');
            $mail->send();
        }
    }

configureSMTP( Array )

Permet de charger un serveur SMTP dynamiquement.


    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function envoieMail( kPHPMailer $mail ) {
            $mail->configureSMTP([
                "host" => '',
                "port" => '',
                "auth" => '',
                "login" => '',
                "password" => '',
                "secure" => '',
            ]);
        }
    }

testSMTPConfiguration()

Cette méthode permet de tester la connexion au serveur SMTP. Elle retourne un booléen.

to( String|Array )

Permet d'ajouter un ou plusieurs destinataires

cc( String|Array )

Permet d'ajouter un ou plusieurs destinataires en copie

bcc( String|Array )

Permet d'ajouter un ou plusieurs destinataires en copie cachée

attachment( String|Array )

Permet d'ajouter un ou plusieurs fichiers en pièces jointes. Le chemin absolu vers chaque fichier est attendu.

setSubject( String )

Permet de définir le titre du mail

setBody( String )

Permet de définir le corps du mail (au format HTML).

setAltBody( String )

Permet de définir le corps alternatif du mail (au format texte).

send()

Permet d'envoyer le mail, retourne un booléen.

Exemple complet d'envoi avec SMTP dynamique

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function testEnvoiMail( String $adresse_mail, kPHPMailer $mail ) {
            $datas = $this->getSmtpInfos(); # Va chercher les informations SMTP en base par exemple
            $mail->configureSMTP([
                "host" => $datas['adresse'],
                "port" => $datas['port'],
                "auth" => $datas['auth'],
                "login" => $datas['login'],
                "password" => $datas['mdp'],
                "secure" => $datas['type'],
            ]);
            $mail->to( $adresse_mail );
            $mail->setSubject("Test d'envoi de mail via SMTP");
            $body = '
                <p style="color:red">Ceci est un test d\'envoi de mail</p>
                <p style="color:green">Ce mail a été envoyé à '.$adresse_mail.'.</p>
                <p style="color:blue">Ce mail a été envoyé via le SMTP '.$datas['adresse'].'.</p>
            ';
            $mail->setBody($body);
            if( !$mail->send() ) err("Erreur lors de l'envoi du mail");
            return;  
        }
    }

Http Client & CURL

Le client HTTP est automatiquement inclus dans .kernelite.

Utilisation basique du HttpClient :

    # ./controllers/ExempleController.php
    class Exemple extends Controller {
        public function envoieMail( HttpClient $http ) {
                        
            $http
                ->setURL('http://monsite.fr/api/user')
                ->setMethod('POST')
                ->setPostDatas( ["id"=> 1500] );

            $state = $http->execute();

            if( !$state )
                err( $http->getError() )

            return $http->response();

        }
    }

Liste des méthodes du HttpClient :
setMethod( String )

Définit la méthode de l'appel. Sont aurotisés : HEAD, GET, POST, PUT, UPDATE, DELETE, INSERT

setURL( String )

Définit l'URL a appeler.

setPostDatas( Array )

Définit le tableau associatif des données POST à envoyer.

setHeaders( Array )

Définit les headers de votre appel (Tableau non associatif : valeur des headers entiers uniquement).

setConnectTimeout( Int )

Nombre de secondes avant le timeout de connexion au serveur distant.

setCurlTimeout( Int )

Nombre de secondes avant le timeout de traitement du serveur distant.

response()

Retourne la réponse au format JSON de l'execution de l'appel

getError()

Retourne la dernière chaine d'erreur de l'execution de l'appel