MMF : My Micro Framework
My Micro Framework est un framework php minimaliste qui ne procure donc pas beaucoup de fonctionnalités mais qui en contrepartie est très simple à appréhender.
Le but est de ne rien avoir à apprendre de plus que ce que vous savez déjà si connaissez le php.
Commencer avec mmf
Une fois téléchargé et décompressé où vous voulez sur votre serveur web vous obtiendrez ceci :
/var/www/html/…/mydirectory/
app/
assets/
libs/
mmf/
scripts/
.htaccess
index.php
A partir de là vous pouvez accéder à mmf dans un navigateur. Une première page de test est livrée.
Dans la suite de la documentation on considérera que mmf est installé à la racine du site http://test.mycorp.com
Quelques concepts de base
Le répertoire app/ est celui où vous travaillerez le plus souvent.
Le répertoire assets/ est celui qui contient tout ce qui doit être accessible directement sans traitement : css, javascript, images ou librairies clientes combinant ces éléments (jQuery, twitter bootstrap …)
Le répertoire libs/ est destiné à accueillir les librairies php.
Dans le dossier app/ vous trouverez 3 sous-répertoires (en fait plus, mais nous y reviendrons):
controllers/ ← les traitements
models/ ← les modèles de données (la couche métier et le DAO)
views/ ← les vues (le html en gros)
La première chose à savoir est que dans mmf on n'a pas besoin de déclarer des routes/chemins pour que ça fonctionne. Les routes sont implicites, c'est à dire que si je crée un fichier test.php dans controllers/
controllers/test.php
<?php
echo "Hello !";
?>
Un appel à http://test.mycorp.com/test affichera
Hello !
Supprimons ce fichier et créons dans views/ un fichier test.phtml
views/test.phtml
Hello !!
Un appel à http://test.mycorp.com/test affichera cette fois

ce qui est mieux.
En fait le simple fait de créer un contrôleur ou un vue, crée une page du nom du contrôleur ou de la vue, la différence est qu'une vue est (par défaut) insérée dans un layout (main.phtml par défaut).
En réalité, la bonne pratique à adopter (que vous utiliserez dans 90 % des "pages" d'une application) est de créer 2 fichiers pour un même page :
controllers/test.php
<?php
$view_params['nom'] = "Toto";
?>
et
views/test.phtml
Hello <?= $view_params['nom']?> !!
<br><br>
ce qui affichera :

Les variables déclarées dans un controleur sont toutes accessibles dans la vue correspondante. Le nom de variable $view_params n'est donc pas obligatoire, et il n'est pas non plus obligatoire que ce soit un tableau. Vous pouvez donc l'appeler comme vous voulez, mais il est bon de lui donner un nom qui vous permettra de la différencier des autre variables que vous aurez à déclarer dans vos controleurs pour vos traitements. Il sera aussi plus simple, si c'est un tableau de retrouver les noms de variables à utiliser au moment d'écrire la vue.
En résumé
- Si vous devez écrire une page statique, vous n'écrirez qu'une page pure html dans views/.
- Si vous ne devez faire qu'un traitement, vous n'écrirez qu'un fichier php dans controllers/, à la fin duquel vous ferez une redirection.
- Si vous devez faire une page contextualisée, vous écrirez un controleur dans lequel vous ne ferez que des traitements et une vue correspondante pour l'affichage.
- On s'efforcera donc de ne jamais faire de 'echo' dans les controleurs.
- Les urls que l'on appelle sur un site développé avec MMF, ne portent pas l'extension '.php'
Le fichier de configuration
Le fichier mmf/config.php est le fichier central de configuration de votre application MMF. Il contient les constantes qui définissent le comportement du framework.
Configuration des sessions
- MMF_SESSION_NAME : Définit le nom de la session PHP. Utile lorsque vous faites tourner plusieurs applications MMF sur le même serveur pour éviter les conflits de sessions.
- MMF_SESSION_LIFETIME : Durée de vie maximale de la session en secondes. Par défaut : 1800 (30 minutes).
Configuration du mode de développement
- MMF_DEV : Booléen qui active/désactive le mode développement. En mode DEV, les erreurs sont affichées dans le navigateur et le niveau de log est automatiquement mis à DEBUG. Attention : ne jamais activer en production !
Configuration des logs
- MMF_LOGLEVEL : Niveau de verbosité des logs :
- 0 : ERROR (uniquement les erreurs)
- 1 : WARNING (erreurs et avertissements)
- 2 : INFO (erreurs, avertissements et informations)
- 3 : DEBUG (tous les messages)
Si MMF_DEV est à true, cette variable est ignorée et le niveau est automatiquement DEBUG.
Configuration de la sécurité (CSP)
MMF intègre une protection CSP (Content Security Policy) pour renforcer la sécurité de votre application :
- MMF_CSP_ENABLED : Active/désactive la politique CSP.
- MMF_CSP_ALLOWED_EXTRA_DOMAINS : Liste des domaines externes autorisés (séparés par des virgules). Exemple : ".mydomain.com,.myotherdomain.com".
- MMF_CSP_REPORT_ONLY : Si true, la politique est en mode "report only" (les violations sont loguées mais non bloquées).
- MMF_CSP_REPORT_URI : URL où envoyer les rapports de violation CSP.
Ce que fournit MMF
- Un mécanisme de layouts
- Quelques fonctions statiques utiles
- Quelques constantes utiles
- Un mécanisme d'extensions automatiques
- Des fonctions d'autoload
- Un mécanisme de fichiers privés
- Une gestion d'évènements
Un mécanisme de layouts
Cela a été évoqué plus haut : toutes vos pages vont être insérées dans un layout. C'est une structure commune à plusieurs ou toutes les pages de votre application. Un layout minimal est fournit, mais vous le modifierez et en créerez peut-être d'autres.
Quelques choses à savoir concernant les layouts
- Les layouts sont des fichiers phtml.
- Tout layout doit contenir une ligne :
echo $mmf_rendered_content;
- Tous les layouts doivent être déposés dans le répertoire _layouts.
Vous pouvez, pour une ou plusieurs pages données désactiver le layout ou préciser d'utiliser un autre layout que celui par défaut. Pour cela, dans le controleur (généralement à la fin), vous devrez appeler la méthode :
MMF::disableLayout();
ou
MMF::setLayout('myLayout'); //sans préciser d'extension (nous y reviendrons plus tard)
Quelques fonctions statiques utiles
Vous pourrez toujours explorer le code de la classe MMF pour voir ce que vous pouvez faire, mais le but de MMF étant de ne rien avoir à apprendre, aucune des fonctions de MMF n'est nécessaire pour développer avec ce framework. Ceci dit, par commodité, MMF fournit quand même quelques fonctions (mécanismes) qui permettent de gagner un peu de temps et de faire les choses proprement.
Les 2 premières méthodes sont celles dont nous avons parlé ci-dessus :
- MMF::disableLayout() et MMF::setLayout() : je n'en reparlerai pas ici.
MMF propose ensuite 2 méthodes particulièrement intéressantes : MMF::redirect() et MMF::error()
-
MMF::redirect() vous permettra comme son nom l'indique de rediriger l'utilisateur sur une autre page du site passée en paramètre
-
MMF::error() prend en paramètre un chaîne de caractère (un message d'erreur) et/ou une exception, et redirigera l'utilisateur sur une jolie page d'erreur.
Quelques constantes utiles
MMF fournit quelques constant utiles, dont une particulièrement qui vous fera gagner du temps : ASSETS.
C'est une constante recalculée à chaque page appelée et qui indique la racine du répertoire assets relativement à la page qui a été appelée. Ainsi, dans vos vues (et vos layouts), pour vous simplifier la tache, vous pouvez utiliser cette constante pour inclure une image ou une feuille de style par exemple.
Ex :
<img src="<?php echo ASSETS?>/images/logo.png />
ou
<link href="<?= ASSETS ?>/css/myStyle.css" rel="stylesheet"> <!-- en utilisant les shorttags -->
Un mécanisme d'extensions automatiques
Dans votre application web vous voudrez parfois que le serveur renvoie autre chose que du html. Par exemple pour un export pdf ou un appel ajax censé retourner du json.
Pour cela, si on reprend l'exemple du début, il suffit de créer dans le répertoire views/, un nouveau fichier : test.json.php
views/test.json.php
<?php
echo json_encode($view_params);
?>
Dès lors un appel à http://test.mycorp.com/test.json affichera dans le navigateur :
{"nom":"Toto"}
Remarquez que le fichier test.json.php peut cohabiter avec le fichier test.phtml. Ce sont 2 vues différentes d'un même controleur. Cela pourra être utile pour des tableaux de bord par exemple où on pourra présenter un tableau (html) élaboré (dans une vue phtml) à partir de données recueillies dans le controleur, et où un lien permettra d'obtenir ces mêmes données présentées dans un fichier pdf ou un fichier excel, en appelant implicitement le même controleur avec des vues différentes (vues pdf.php ou xls.php)
- Un controleur est toujours un fichier portant l'extension .php
- Une vue html porte l'extension .phtml
- Tous les autres type de vues portent l'extension qu'on veut (relative au type) suivie de .php
Des fonctions d'autoload
MMF fournit 2 fonctions d'autoload qui devraient normalement retrouver les classes que vous utilisez dans les dossiers libs/ et app/models/. Notez que dans ce dernier les classes ne seront trouvées que si l'arborescence respecte les namespaces à partir de ce répertoire.
Pour les libs/ on est plus tolérant, les librairies php que l'on trouve ci et là n'utilisant pas toujours les namespaces et utilisant des conventions de nommage diverses et variées.
Pour en savoir plus sur l'autoloading dans MMF vous pouvez regarder le fichier mmf/autoload.php
Un mécanisme de fichiers privés
MMF offre une possibilité de créer des fichiers qui ne pourront être accédés directement : le préfixe "_".
Comme cela a été dit plus haut, la simple déclaration d'un controleur ou d'une vue crée rend une nouvelle url accessible. Mais on peut avoir besoin de créer des fichiers à but d'inclusion sans pour autant vouloir que ces fichiers soient accessibles directement.
Pour cela, il suffit de préfixer le nom de fichier par un "_" et le fichier sera ignoré par MMF.
Ce même mécanisme fonctionne pour les répertoires, et tous les fichiers contenus dans un répertoire commençant par "_" seront ignorés, même si ceux-ci ne commencent pas par un "_"
Ex :
app/controllers/admin/
index.php ← vérification qu'on est authentifié et qu'on a les droits adéquats
et inclusion du controleur demandé dans l'url
_console.php ← une console de gestion
_add.php ← pour ajouter un objet
_modify.php ← pour modifier un objet
…
Le fichier index.php pourrait ressembler à ceci :
<?php
$actions = array('console','add','modify',...);
if(isset($_SESSION["user"])) {
$user = unserialize($_SESSION['user']);
if($user->getProfile() == 'administrator'){
$action = isset($_GET['action']) && in_array($_GET['action'], $actions) ? $_GET['action'] : $actions[0];
include('_'.$action.".php");
}
else{
MMF::redirect('/not_authorized') ;
}
}
else{
MMF::redirect('/login') ;
}
?>
Ainsi l'utilisateur ne pourra pas accéder aux traitements console.php, add.php ou modify.php directement sans passer par l'index et une tentative d'accès à http://test.mycorp.com/admin/_console produira une erreur 'not found'. Le fichier est caché.
On aurait pu aussi regrouper les 3 fichiers dans un répertoire '_include/' ce qui aurait caché tout ce qui se trouve en dessous (même si les fichiers ne sont pas préfixés).
En résumé
- Un fichier qui ne doit pas être accessible directement peut être caché s'il est préfixé par '_'.
- Si un répertoire commence par un '_', tout ce qui est en dessous de ce répertoire est caché.
Une gestion d’évènements
Imaginons que le fichier suivant ait été inclus dans notre controleur :
<?php
// Callback functions
function onAddUser($id){
// some actions for other app for example
...
}
// Register callbacks
MMF::registerListener("addUserEvent", "onAddUser");
?>
Alors, ailleurs dans notre traitement, on peut faire un appel :
...
//le code pour ajouter un utilisateur
...
MMF::fireEvent("addUserEvent", array($userId));
La fonction "onAddUser" sera alors appelée avec les paramètres passés en argument.
Cela peut permettre d'appliquer certains traitements qui sortent du cadre de notre logique principale en les sortant de notre controleur.
Notes sur les évènements
- Une évènement peut être enregistré plusieurs fois pour jouer plusieurs fonctions
- On peut déterminer l'ordre dans lequel seront appelées les fonctions (voir MMF::registerListener())
- Les fonctions de callback sont appelées dans le cours de l’exécution courante (pas de mécanisme asynchrone)