wiki/HowtoDrupal.md

509 lines
17 KiB
Markdown
Raw Permalink Normal View History

2018-03-29 12:14:49 +02:00
---
categories: web CMS
title: Howto Drupal
---
2018-10-11 00:17:27 +02:00
* Documentation : <https://www.drupal.org/documentation>
2018-03-29 12:14:49 +02:00
2018-10-11 00:17:27 +02:00
[Drupal](https://www.drupal.org/) est un CMS libre écrit en PHP.
2018-03-29 12:38:40 +02:00
## Pré-requis
* Un serveur web (Apache/Nginx/...)
2022-08-26 12:31:21 +02:00
* Une base de données MySQL/Mariadb ou PostgreSQL
2022-10-18 11:35:52 +02:00
* PHP 8.1 (Drupal 10), PHP 7.4/8.0/8.1 (Drupal 9), PHP 7.3/7.4 (Drupal 7 et 8)
* Pour Drush : /home en `exec` et `mariadb-client` installé
2019-03-22 21:47:38 +01:00
Pour plus de détails, voir [la documentation de Drupal](https://www.drupal.org/docs/user_guide/en/install-requirements.html) notamment :
* [pré-requis pour Drupal 7](https://www.drupal.org/docs/7/system-requirements/)
2022-08-26 11:32:28 +02:00
* [pré-requis pour Drupal 8 et versions suivantes](https://www.drupal.org/docs/system-requirements/)
2019-03-22 21:47:38 +01:00
### Apache
2019-01-11 15:15:07 +01:00
Drupal est livré avec des fichiers `.htaccess` qui utilisent un nombre varié de directives.
La configuration Apache doit donc contenir au minimum :
~~~{.apache}
AllowOverride AuthConfig Limit FileInfo Indexes Options=Indexes,MultiViews,ExecCGI,Includes
~~~
2019-01-11 15:25:17 +01:00
Le `DocumentRoot` d'Apache doit correspondre au dossier `web` qui se trouve à la racine du dossier du projet
2019-06-28 15:07:44 +02:00
### Nginx
Un exemple complet de vhost Nginx pour Drupal est accessible sur [dans la documentation de Nginx](https://www.nginx.com/resources/wiki/start/topics/recipes/drupal/)
### PHP
Certains ajustements sont nécessaires
#### Web ( FPM / libapache2-mod-php )
*TODO?*
#### CLI
C'est surtout pour `composer` et `drush` qui nécessitent :
* (composer) Le non blocage de la fonction `putenv()`
2024-01-16 22:50:04 +01:00
* (composer) Autoriser l'ouverture d'url (allow_url_fopen)
* (drush) Aucune fonction désactivée (ie: disable_functions vide) sinon drush refuse de fonctionner....
## Installation
2024-01-16 23:09:07 +01:00
Il existe [plusieurs méthodes pour installer Drupal](https://www.drupal.org/docs/getting-started/installing-drupal/get-the-code).
La méthode conseillée est d'utiliser [composer](HowtoPHP#composer)
Ainsi, une installation par défaut va se faire avec la commande suivante va créer une nouvelle installation et récupérer toutes les dépendances avec composer.
~~~
2022-08-26 12:31:21 +02:00
$ mkdir www/
2024-01-16 22:50:04 +01:00
$ composer create-project drupal/recommended-project www
2024-01-16 23:09:07 +01:00
$ cd www/
2022-08-26 12:31:21 +02:00
$ composer show | grep ^drupal
2024-01-16 23:09:07 +01:00
drupal/core 10.2.1 Drupal is an open source content management platform powering millions of websites and applications.
drupal/core-composer-scaffold 10.2.1 A flexible Composer project scaffold builder.
drupal/core-project-message 10.2.1 Adds a message after Composer installation.
drupal/core-recommended 10.2.1 Core and its dependencies with known-compatible minor versions. Require this project INSTEAD OF drupal/core.
~~~
2018-10-11 00:17:27 +02:00
On peut en suite, aller directement à l'addresse du site (DocumentRoot qui pointe vers `/home/foo/www/web/`) pour obtenir l'interface de finalisation du site.
2022-08-29 08:37:49 +02:00
On aura notamment besoin d'avoir des identifiants pour accéder à une base de données.
2019-01-11 15:25:17 +01:00
On peut également finaliser l'installation avec Drush (cf plus bas) :
~~~
2024-02-08 22:42:40 +01:00
$ cd www
$ drush site:install standard
Database name [drupal]:
> foo
Database driver [mysql]:
>
Database username [drupal]:
> foo
Database password [drupal]:
> PASSWORD
Database host [127.0.0.1]:
>
Database port [3306]:
>
You are about to:
* DROP all tables in your 'foo' database.
Do you want to continue? (yes/no) [yes]:
>
[notice] Starting Drupal installation. This takes a while.
[notice] Performed install task: install_select_language
[notice] Performed install task: install_select_profile
[notice] Performed install task: install_load_profile
[notice] Performed install task: install_verify_requirements
[notice] Performed install task: install_settings_form
[notice] Performed install task: install_verify_database_ready
[notice] Performed install task: install_base_system
[notice] Performed install task: install_bootstrap_full
[notice] Performed install task: install_profile_modules
[notice] Performed install task: install_profile_themes
[notice] Performed install task: install_install_profile
[notice] Performed install task: install_configure_form
[notice] Performed install task: install_finished
[success] Installation complete. User name: admin User password: PASSWORD
2024-02-08 22:42:40 +01:00
$ cd web/sites/default/
$ drush sql-connect
mysql --user=foo --password='PASSWORD' --database=foo --host=127.0.0.1 --port=3306 -A
$ drush status
Drupal version : 10.2.1
Site URI : http://default
DB driver : mysql
DB hostname : 127.0.0.1
[…]
~~~
2024-02-08 22:42:40 +01:00
La configuration de Drupal qse trouve dans le fichier `web/sites/default/settings.php` :
~~~
<?php
$settings['hash_salt'] = 'l3Jh1oSBq6mKfsvZ6D0zD4sx23Gv2_XgExPj5Eqq3QlAwgxEt54O0jbXG-_Ai9L8tMH65zWFjQ';
$settings['update_free_access'] = FALSE;
$settings['container_yamls'][] = $app_root . '/' . $site_path . '/services.yml';
$settings['file_scan_ignore_directories'] = [
'node_modules',
'bower_components',
];
$settings['entity_update_batch_size'] = 50;
$settings['entity_update_backup'] = TRUE;
$settings['migrate_node_migrate_type_classic'] = FALSE;
$databases['default']['default'] = array (
'database' => 'drupal',
'username' => 'drupal',
'password' => 'PASSWORD',
'prefix' => '',
'host' => '127.0.0.1',
'port' => '3306',
'isolation_level' => 'READ COMMITTED',
'driver' => 'mysql',
'namespace' => 'Drupal\\mysql\\Driver\\Database\\mysql',
'autoload' => 'core/modules/mysql/src/Driver/Database/mysql/',
);
$settings['config_sync_directory'] = 'sites/default/files/config_DVQYtOdt2FEtnXLrOuHYfICqXRN0mJKX7lnAe1Nyjq5kPOWwPtpgjCwmtE8XOs8soZgUbh_wjw/sync';
~~~
2019-01-11 15:25:17 +01:00
### Cron
~~~
$ crontab -l
42 * * * * php /home/foo/www/vendor/bin/drush cron --root /home/foo/www/ 2&>1 >/dev/null
~~~
2018-10-11 00:17:27 +02:00
2022-08-26 12:31:21 +02:00
## drush
2022-10-04 14:42:50 +02:00
[Drush](https://www.drush.org/) est un outil en ligne de commande pour installer/gérer des sites Drupal.
2022-08-29 08:37:49 +02:00
Liste des commandes disponibles par défaut : <https://www.drush.org/12.x/commands/all/>
2022-08-26 12:31:21 +02:00
### Installation
2022-09-16 12:20:29 +02:00
Pour installer la dernière version :
2022-08-26 12:31:21 +02:00
~~~
2024-02-08 22:42:40 +01:00
$ cd www/
2022-08-26 12:31:21 +02:00
$ composer require drush/drush
2022-08-29 08:37:49 +02:00
$ composer require symfony/http-kernel
2022-08-26 12:31:21 +02:00
$ composer show drush/drush | grep ^version
2024-01-16 23:09:07 +01:00
versions : * 12.4.3
2022-08-29 08:37:49 +02:00
2024-01-16 23:15:42 +01:00
$ php ./vendor/bin/drush version
2024-01-16 23:09:07 +01:00
Drush version : 12.4.3.0
2022-08-26 12:31:21 +02:00
~~~
2022-09-16 12:20:29 +02:00
Pour installer une ancienne version :
~~~
$ composer global require drush/drush:8.4.8
2024-01-16 23:15:42 +01:00
$ php ./.composer/vendor/bin/drush version
2022-09-16 12:20:29 +02:00
Drush Version : 8.4.8
~~~
2023-04-18 17:11:39 +02:00
ou
~~~
$ composer require drush/drush:8.4.8
2024-01-16 23:15:42 +01:00
$ php ./vendor/bin/drush version
2023-04-18 17:11:39 +02:00
Drush Version : 8.4.8
~~~
2022-10-04 14:42:50 +02:00
### Utilisation
Au sein d'un site Drupal, on peut vérifier/collecter différentes informations :
~~~
2024-02-08 22:42:40 +01:00
$ cd www/
2024-01-16 23:15:42 +01:00
2022-10-04 14:42:50 +02:00
$ drush sql-connect
2024-02-08 22:42:40 +01:00
mysql --user=drupal --password='PASSWORD' --database=drupal --host=127.0.0.1 --port=3306 -A
2024-01-16 23:15:42 +01:00
2022-10-04 14:42:50 +02:00
$ drush status
2024-01-16 23:15:42 +01:00
Drupal version : 10.2.1
Site URI : http://default
PHP binary : /usr/bin/php8.2
PHP config : /etc/php/8.2/cli/php.ini
PHP OS : Linux
PHP version : 8.2.7
Drush script : /home/foo/www/vendor/bin/drush
Drush version : 12.4.3.0
Drush temp : /tmp
Drush configs : /home/foo/www/vendor/drush/drush/drush.yml
Drupal root : /home/foo/www/web
Site path : sites/default
2022-10-04 14:42:50 +02:00
~~~
### Alias
Fichiers dans le répertoire `~/.drush/` :
* `local.drushrc.php` : configuration générale
* `FOO.alias.drushrc.php` : contexte spécifique pour la commande `drush @FOO`
* `BAR.alias.drushrc.php` : contexte spécifique pour la commande `drush @BAR`
~~~
$ cat ~/.drush/FOO.alias.drushrc.php
$aliases['FOO'] = array (
'uri' => 'foo.example.com',
'root' => '/home/foo/www/web',
...
~~~
## Configuration
2022-10-27 17:32:48 +02:00
### Configuration derrière un reverse-proxy
2024-01-16 23:15:42 +01:00
Dans la configuration de Drupal, des directives sont à activer pour la prise en compte des headers HTTP X-Forwarded-For).
2022-10-27 17:32:48 +02:00
~~~php
$settings['reverse_proxy'] = TRUE;
$settings['reverse_proxy_addresses'] = ['192.0.2.1'];
~~~
Pour le HTTPS (signalé via X-Forwarded-Proto), il y a déjà des directives de configuration pour prendre ce réglage en compte.
Elles ressemblent à :
~~~php
/**
* If external request was HTTPS but internal request is HTTP, set $_SERVER['HTTPS'] so Drupal detects the right scheme.
*/
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && isset($_SERVER['REQUEST_SCHEME'])) {
if ($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' && $_SERVER["REQUEST_SCHEME"] == 'http') {
$_SERVER['HTTPS'] = 'on';
}
}
~~~
## Multisite
<https://www.drupal.org/docs/getting-started/multisite-drupal/>
Il est possible de créer différents sites Drupal à partir d'une même installation.
Cela permet d'avoir une seule fois le code source de Drupal et donc une gestion simplifiée.
Cela peut avoir des inconvénients si besoin de gérer finement des ensembles de personnalisations différentes par site.
On suppose qu'une installation de base de Drupal a été faite, et Drush également installé.
> *Note* : il est nécessaire d'avoir la commande `mysql` installée, donc `mariadb-client` doit être installé là où tourne PHP
Pour l'installation d'un premier site distinct du `default` créé à l'installation de Drupal :
~~~
2024-02-08 22:42:40 +01:00
$ cd www/
$ drush site:install standard --sites-subdir=test1
Database name [drupal]:
> foo_test1
2024-02-08 22:42:40 +01:00
www
Database driver [mysql]:
>
Database username [drupal]:
> foo
Database password [drupal]:
> PASSWORD
Database host [127.0.0.1]:
>
Database port [3306]:
>
You are about to:
* Create a sites/test1/settings.php file
* Create a sites/sites.php file
* DROP all tables in your 'foo_test1' database.
Do you want to continue? (yes/no) [yes]:
>
[notice] Starting Drupal installation. This takes a while.
[notice] Performed install task: install_select_language
[notice] Performed install task: install_select_profile
[notice] Performed install task: install_load_profile
[notice] Performed install task: install_verify_requirements
[notice] Performed install task: install_settings_form
[notice] Performed install task: install_verify_database_ready
[notice] Performed install task: install_base_system
[notice] Performed install task: install_bootstrap_full
[notice] Performed install task: install_profile_modules
[notice] Performed install task: install_profile_themes
[notice] Performed install task: install_install_profile
[notice] Performed install task: install_configure_form
[notice] Performed install task: install_finished
[success] Installation complete. User name: admin User password: PASSWORD
~~~
Cela crée donc un fichier `web/sites/sites.php` pour gérer plusieurs sites.
Et les sites sont « crées » dans des répertoires `web/sites/SITE/`
contenant principalement un fichier `settings.php` contenant notamment les paramètres de base de données du site.
~~~
$ cd web/sites/test1/
$ drush sql-connect
mysql --user=foo --password='PASSWORD' --database=foo_test1 --host=127.0.0.1 --port=3306 -A
$ drush status
Drupal version : 10.2.1
Site URI : http://test1
DB driver : mysql
DB hostname : 127.0.0.1
[…]
~~~
Il suffit ensuite de créer la configuration Apache ou Nginx pour les FQDN souhaités avec un DocumentRoot dans `web/`
et de bien configurer le fichier `web/sites/sites.php` par exemple :
~~~
$sites['test1.example.com'] = 'test1';
$sites['test2.example.com'] = 'test2';
~~~
On peut utiliser la commande Drush sur un site en particulier via l'argument `-l` :
~~~
$ drush -l test1 status
$ drush -l test1 updatedb
~~~
2022-10-27 17:32:48 +02:00
2018-10-11 00:17:27 +02:00
## Optimisation
* Drupal 7 : <https://www.drupal.org/docs/7/managing-site-performance-and-scalability/optimizing-drupal-to-load-faster-server-mysql>
* Drupal 8 : <https://www.valuebound.com/resources/blog/a-beginners-guide-to-performance-optimization-drupal-8>
### watchdog
Désactiver le logging non nécessaire en prod... surtout dans la base de données : <https://www.karelbemelmans.com/2015/05/drupal-watchdog-logging-dblog-vs-syslog/>
<https://www.drush.org/12.x/commands/watchdog_show/>
<https://www.drush.org/12.x/commands/watchdog_delete/>
2024-01-21 23:30:45 +01:00
À noter que l'on peut lire, supprimer, etc. avec Drush :
https://www.drush.org/12.x/commands/watchdog_delete/
https://www.drush.org/12.x/commands/watchdog_list/
https://www.drush.org/12.x/commands/watchdog_show/
### cache
Dans les versions récentes, Drupal génère du cache, notamment via Twig.
Cela peut générer des entrées dans les tables MySQL cache_page, cache_date, etc.
On peut lire la configuration courant de Twig via :
~~~
$ drush php:eval "var_export(\Drupal::getContainer()->getParameter('twig.config'));"
array (
'debug' => true,
'auto_load' => true,
'cache' => true,
)
~~~
#### désactiver le cache Twig
<https://www.drupal.org/docs/develop/development-tools/disable-caching>
Dans `sites/default/` (ou le répertoire du site ciblé) on crée un fichier `service.yml` contenant notamment :
~~~
parameters:
twig.config:
cache: false
~~~
On crée également un fichier `settings.local.php` contenant notamment :
~~~
$settings['cache']['bins']['render'] = 'cache.backend.null';
$settings['cache']['bins']['page'] = 'cache.backend.null';
$settings['cache']['bins']['dynamic_page_cache'] = 'cache.backend.null';
~~~
Ce fichier `settings.local.php` doit être inclus dans `settings.php` :
~~~
if (file_exists($app_root . '/' . $site_path . '/settings.local.php')) {
include $app_root . '/' . $site_path . '/settings.local.php';
}
~~~
Enfin, n'oubliez pas de vider le cache via Drush après tout changement de configuration :
~~~
$ drush cache:rebuild
$ drush php:eval "var_export(\Drupal::getContainer()->getParameter('twig.config'));"
~~~
À noter que dans les versions les plus récentes, on peut forcer via des variables :
~~~
$ drush state:set twig_cache_disable 1 --input-format=integer
$ drush state:set disable_rendered_output_cache_bins 1 --input-format=integer
$ drush cache:rebuild
~~~
2018-10-11 00:17:27 +02:00
## Sécurité
2019-01-11 15:15:07 +01:00
### Annonces de sécurité
2024-02-20 13:16:37 +01:00
Nous recommandons aux développeurs de garder un œil sur [les annonces de sécurité](https://www.drupal.org/security) faites par l'équipe Drupal.
2019-01-11 15:15:07 +01:00
2018-10-11 00:17:27 +02:00
### CVE-2018-7600 // SA-CORE-2018-002
2018-03-29 12:38:40 +02:00
Règle mod_security de protection (théorique)
~~~
SecRule ARGS_GET_NAMES|ARGS_POST_NAMES|REQUEST_COOKIES_NAMES "^#" "t:none,log,deny,msg:'CVE-2018-7600/Drupal-SA-CORE-2018-002 -- Deny # in (cookie|query|post) names',id:300000001"
~~~
2019-01-11 15:15:07 +01:00
## Plomberie
### An automated attempt to create the directory ../config/sync failed, possibly due to a permissions problem.
Ça arrive quand on a initialisé un projet Drupal depuis composer. Il semble que ce soit [un vieux bug non corrigé](https://github.com/drupal-composer/drupal-project/issues/274)
2019-03-22 21:47:38 +01:00
La solution est de créer un dossier `config/sync` a la racine du projet, avec des droits d'écritures pour le serveur web.
2024-02-20 13:16:37 +01:00
2024-02-27 10:12:43 +01:00
### Gestion des utilisateurs
~~~
MariaDB> select * from users,users_field_data where users.uid=users_field_data.uid;
+-----+--------------------------------------+----------+-----+----------+--------------------+--------------------------+--------+---------+-------------------+----------+--------+------------+------------+------------+------------+------------------+------------------+
| uid | uuid | langcode | uid | langcode | preferred_langcode | preferred_admin_langcode | name | pass | mail | timezone | status | created | changed | access | login | init | default_langcode |
+-----+--------------------------------------+----------+-----+----------+--------------------+--------------------------+--------+---------+-------------------+----------+--------+------------+------------+------------+------------+------------------+------------------+
| 0 | 0b713940-204b-41c3-93aa-2380aa773d70 | en | 0 | en | en | NULL | | NULL | NULL | | 0 | 1708703180 | 1708703180 | 0 | 0 | NULL | 1 |
| 1 | b2f79d0b-638c-4d45-927c-f196e33417e2 | en | 1 | en | en | NULL | admin | $2y$... | admin@example.com | UTC | 1 | 1708955952 | 1708956585 | 1708956573 | 1708956573 | init@example.com | 1 |
+-----+--------------------------------------+----------+-----+----------+--------------------+--------------------------+--------+---------+-------------------+----------+--------+------------+------------+------------+------------+------------------+------------------+
~~~
2024-02-20 13:16:37 +01:00
## FAQ
### The website encountered an unexpected error. Please try again later
Si vous obtenez cette erreur, c'est qu'il y a une erreur quelque part avec le code PHP.
Deux suggestions pour accéder à l'erreur PHP :
* Si vous avez activé le watchdog, l'erreur devrait se trouver dans la table `watchdog` (que vous pouvez notamment lire avec drush)
* Dans le fichier `errors.inc` appliquez **temporairement** ce patch pour voir l'erreur PHP dans votre page :
~~~
< print theme('maintenance_page', array('content' => t('The website encountered an unexpected error. Please try again later.')));
---
> print theme('maintenance_page', array('content' => t('The website encountered an unexpected error. Please try again later.\n'.$fatal.' '.var_export($error,true))));
~~~