une (r)évolution à la portée de Tous
Modèle MVC
Symfony 2
POO avancée
« Ceci est une Révolution »
« J'comprends rien à c'truc, j'peux pas l'faire à l'arrache ? »
« Il n'y a qu'une seule voie, celle de la vertu »
S. Jobs
M. Robespierre
Dev PHP du dimanche
Premières réactions
Ce qui change
Ce qui ne change "presque" pas
Drupal 7
Drupal 8
mon_module
mon_module
name = "Mon module"
description = "Blabla"
package = "Mon package"
core = "7.x"
version = "7.x-1.0"
dependencies[] = dependance_1
dependencies[] = dependance_2
name: Mon module
type: module
description: Blabla
package: mon package
core: '8.x'
version: '8.x-1.0'
dependencies:
- dependance_1
- dependance_2
mon_module_permission () {
return array(
'ma_permission' => array(
'title' => t('Ma permission'),
'description' => t('STOP'),
),
);
}
'ma permission':
title: 'Ma permission'
description: 'STOP'
Drupal 7
Drupal 8
mon_module.module
mon_module.permissions.yml
Drupal 7
Drupal 8
// Utiliser l'utilisateur courant
global $user;
// Utiliser l'utilisateur courant
$user = \Drupal::currentUser();
// Charger un utilisateur
$user2 = user_load(2) ;
// L'utilisateur est-il authentifié ?
if(user_is_logged_in()) {
/* ... */
}
// L'utilisateur a-t-il la permission ?
if(user_access('ma_permission')){
/* ... */
}
// Charger un utilisateur
$user2 = \Drupal\user\Entity\User::load(2);
// L'utilisateur a-t-il la permission ?
if($user->hasPermission('ma_permission')) {
/* ... */
}
// L'utilisateur est-il authentifié ?
if($user->isAuthenticated()) {
/* ... */
}
Déclaration :
/* Utilisation du hook_form(). */
function mon_module_formtest_form() {
/* ... */
}
/* paramètre de drupal_get_form() */
function mon_module_form_deux() {
/* ... */
}
Validateur(s) :
// Dans une déclaration de formulaire
// ou un hook_form_alter
$form['#validate'][] = "form_validator";
}
function form_validator($form, &form_state) {
/* ... */
}
// ou un hook_form_validate
Contrôle(s) de soumission :
// Dans une déclaration de formulaire ou un hook_form_alter
$form['#submit'][] = "control_submit";
}
function control_submit($form, &form_state) {
/* ... */
}
/* Utilisation du hook_form_submit(). */
function mon_module_formtest_form_submit($form, &form_state) {
/* ... */
}
namespace Drupal\mon_module\Form;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
class FormTest extends FormBase {
}
dans le fichier formtest.php
situé : mon_module/src/Form
public function getFormId() { return 'Formulaire_de_test'; }
public function buildForm(array $form, FormStateInterface $form_state) {
// Utilisation de la formAPI
/* ... */
return $form;
}
méthodes de la classe " FormTest "
class FormTest extends FormBase {
public function getFormId() { return 'id_du_formulaire'; }
public function buildForm(array $form, FormStateInterface $form_state) {
/* ... */
}
}
public function validateForm(array &$form, FormStateInterface $form_state) {
// accès aux values
$values = $form_state->getValues();
// marquer une erreur
$form_state->setErrorByName($field_name, $this->t('Error on field'));
}
public function submitForm(array &$form, FormStateInterface $form_state){
/* ... */
}
$form = \Drupal::formBuilder()->getForm('Drupal\mon_module\Form\FormTest');
Ex-drupal_get_form
mon_module.testform:
path: '/mon_module/testform'
defaults:
_title: 'Formulaire de test'
_form: 'Drupal\mon_module\Form\FormTest'
Page de formulaire
hook_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id)
hook_form_FORM_ID_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id)
hook_form_BASE_FORM_ID_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id)
Par des fonctions
Par un objet
namespace Drupal\mon_module\Form;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
class AlterFormTest extends FormTest {
public function getFormId() { return 'Formulaire_de_test_modif'; }
public function buildForm(array $form, FormStateInterface $form_state) {
$form = parent::buildForm($form, $form_state);
unset($form['field_mail']);
}
}
Drupal 6
Drupal 7
function mon_module_block ( $op, $delta, $edit) {
switch($op){
function mon_module_block_view($delta = '') {
if($delta == 'mon_block') {
// fabrique mon block
$blocks['content'] = $outHTML;
}
/* ... */
return $blocks;
}
function mon_module_block_info() {
$blocks['mon_block'] = array(
'info' => t('mon block'),
);
/* ... */
return $blocks;
}
case 'view' :
// fabrique les blocs
/* ... */
break;
case 'list' :
// declare les blocs
/* ... */
break;
}
}
Drupal 7
Drupal 8
namespace '...';
use '...';
class blockOne extends BlockBase {
}
function mon_module_block_info() {
$blocks['mon_block'] = array(
'info' => t('mon block'),
);
/* ... */
return $blocks;
}
mon_module.module
dans le fichier BlockOne.php
situé : mon_module/src/Plugin/Block
function mon_module_block_view($delta = '') {
if($delta == 'mon_block') {
// fabrique mon block
$blocks['content'] = $outHTML;
}
/* ... */
return $blocks;
}
/**
* @Block(
* id = "block_one",
* admin_label = "Block One",
* )
*/
public function build() {
// fabrique mon block
return $themable_array;
}
La Théorie
Drupal 7
Drupal 8
Un hook pour les trouver tous.
Un hook pour les gouverner tous.
Un hook pour les agréger tous
et dans les menus les lier
La prophétie du hook
Le monde décentralisé
Chacun son chemin
Chacun sa nature
Chacun son ascendance
Chacun son type
Un hook unique utilisé partout
Une multitude de fichiers
Drupal 7
Drupal 8
Type par défaut
menu_item
menu_callback
Callback de page
Fonction
Objet
Paramètre de requête
"path/%/%" et "page_argument"
auto-chargement possible
"path/{one}/{two}"
Prédéclaration des variables
Les routes
Route simple
Drupal 7
Drupal 8
mon_module
mon_module.routing.yml
mon_module_menu () {
$items['go'] = array(
'page callback' => 'runGo',
'access arguments' =>
array('ma_permission'),
'title' => 'le titre de ma page'
'type' => MENU_CALLBACK
);
/* ... */
return $items;
}
monmodule.go:
path: 'go'
defaults:
_content:
'\Drupal\mon_module\Controller\GoController::runGo'
_title: 'le titre de ma page'
requirements:
_permission: 'ma_permission'
Route avec paramètres
Drupal 7
Drupal 8
mon_module
mon_module.routing.yml
mon_module_menu () {
$items['go/%/%'] = array(
'page arguments' => array(1,2),
'page callback' => 'run_go',
'access arguments' =>
array('ma_permission'),
'title' => 'le titre de ma page'
'type' => MENU_CALLBACK
);
/* ... */
return $items;
}
monmodule.go:
path: 'go/{one}/{two}'
defaults:
_content:
'\Drupal\mon_module\Controller\GoController::runGo'
_title: 'le titre de ma page'
requirements:
_permission: 'ma_permission'
Déclarer une page
Dans le fichier GoController.php
situé : mon_module/src/Controller
namespace Drupal\mon_module\Controller;
use Drupal\Core\Controller\ControllerBase;
class GoController extends ControllerBase {
public function runGo($one,$two) {
// je fabrique ma page
return $theming_array;
}
}
Les arborescences
Classique
mon_module.links.menu.yml
menu.go_results:
title: 'Resultat'
parent: mon_module.go
description: 'Resultats'
route_name: mon_module.go_results
menu.go_results_more:
title: 'Plus de Resultat'
parent: mon_module.go_results
description: 'Plus de Resultats'
route_name: mon_module.go_results_more
Local task
mon_module.links.task.yml
mon_module.root:
title: 'page de configuration'
route_name: mon_module.conf
base_route : mon_module.conf
mon_module.advanced:
title: 'Configuration avancée'
route_name: mon_module.more
base_route : mon_module.conf
Le thèming
Nouvelle conception
Preprocessing
Entity_API
Côté code PHP :
Changement de fonctionnement
La gestion des configurations
Dans la théorie :
Dans la pratique :
« Ceci est une Révolution »
« J'comprends rien à c'truc, j'peux pas l'faire à l'arrache ? »
« Il n'y aura qu'une seule voie, celle de la vertu »
S. Jobs
M. Drupespierre
Dev PHP du dimanche