Planète Kgaut

Par Kgaut
Adhérent
Kevin Gautreau

Drupal 8 & Search API - effectuer une requête dans le code

Avec Drupal et Drupal 8 encore plus la recherche passe la plupart du temps par Search API, une interface qui se branche devant plusieurs moteur de base de données (SolR, ElasticSearch, Database...)

Le plus souvent on va faire nos pages de résultats de recherche à l'aide de Views (et du module Search views pour Drupal 7). Mais dans certains cas on va vouloir avoir plus la main sur la recherche et donc aller interroger Search API directement dans le code.

Initialisation de la requête

Chargement de l'index (ici, le nom machine est « contenu »)

  1. // Chargement de l'index « contenu »
  2. $query = Index::load('contenu')->query();

Définition de la requête recherchée

Terme sur lesquels vont être effectués la requête.

  1. // On lancer la recherche sur « hello world »
  2. $query->keys("hello world");

Mode de la requête

  1. // Les différentes possibilités sont
  2. // - « direct » => Requête directe
  3. // - « terms » => Multiple words
  4. // - « phrase » => Single phrase
  5. $parse_mode = \Drupal::service('plugin.manager.search_api.parse_mode')->createInstance('direct');
  6.  
  7. // Optionnellement, on peut choisir un opérateur spécifique (OR ou AND)
  8. $parse_mode->setConjunction('OR');
  9.  
  10. // Affectation du mode de la requête
  11. $query->setParseMode($parse_mode);

Définitions des champs sur lesquels rechercher

Évidement c'est optionnel, par défaut la recherche se fera sur l'ensemble des champs « fulltext » contenus dans l'index.

  1. // Recherche uniquement sur le champ « body »
  2. $query->setFulltextFields(['body']);
  3.  
  4. // Recherche uniquement sur les champs « body » et « title »
  5. $query->setFulltextFields(['body', 'title']);

Ajout de conditions supplémentaires

L'objet retourné par Index::load('contenu')->query(); est une query classique drupal, sur laquelle on peut effectuer les traitement classique que l'on peut faire sur n'importe quelle Query drupal8.

À noter ici que le nom des champs doit être celui que l'on renseigne dans l'index, ils peuvent être différents des noms des champs définis dans nos types de contenu.

Quelques exemples en vrac :

Condition sur un champ boolean

  1. // le champ private doit être « TRUE »
  2. $query->addCondition('private', TRUE);

Condition sur un champ « varchar »

  1. // on veut que le contenu retourné soit un article ou un snippet
  2. $query->addCondition('type', ['article', 'snippet'], 'IN');

Condition sur un champ date

À noter le format de date à utiliser : "Y-m-d\TH:i:s\Z"

  1. $btf = \DateTime::createFromFormat('d/m/Y', '21/10/2015');
  2. $date_formatted = $btf->format("Y-m-d\TH:i:s\Z")
  3.  
  4. // Date de création de l'article > date définie
  5. $query->addCondition('created', $date_formatted, '>');
  6.  
  7. // Et l'inverse
  8. $query->addCondition('created', $date_to, ');

Pagination

Gestion de la pagination identique à une requête classique

  1. // Récupération des 20 premiers résultats.
  2. $query->range(0, 20);

Exécution de la requête et récupération des résultats

  1. $results_set = $query->execute();
  2.  
  3. //Nombre de résultats retournés
  4. $nb_results = $results_set->getResultCount()
  5.  
  6. // Récupération des entités
  7. foreach ($results_set->getResultItems() as $item) {
  8. $resultat = $item->getOriginalObject()->getValue();
  9. }

Sources

Pas trouvé grand chose sur le sujet à part cette page dans la documentation sur drupal.org : https://www.drupal.org/docs/8/modules/search-api/developer-documentatio…

Si vous avez d'autres liens pouvant aider, je suis preneur.

Par Kgaut
Adhérent
Kevin Gautreau

Drupal - Création d'une table dans une base secondaire

Voici comment créer une table dans une base de donnée autre que celle par défaut.

Code à mettre dans votre MODULE.install

Le principe : création d'un « HOOK_schema fake » et utilisation des HOOK_install et HOOK_uninstall pour créer / supprimer cette table en sélectionnant la bonne base.

Le code est pour drupal 8 mais il peut facilement être adapté pour drupal 7.

  1.  
  2. use \Drupal\Core\Database\Database;
  3.  
  4. function MODULE_schema_autre_db() {
  5. $schema['users'] = [
  6. 'description' => 'Members informations',
  7. 'fields' => [],
  8. 'primary key' => ['id'],
  9. ];
  10.  
  11. $schema['users']['fields']['id'] = [
  12. 'description' => 'ID',
  13. 'type' => 'serial',
  14. 'not null' => TRUE,
  15. 'unsigned' => TRUE,
  16. ];
  17.  
  18. $schema['users']['fields']['uid'] = [
  19. 'description' => 'Drupal ID',
  20. 'type' => 'int',
  21. 'not null' => TRUE,
  22. 'unsigned' => TRUE,
  23. ];
  24.  
  25. $schema['users']['fields']['mail'] = [
  26. 'type' => 'varchar',
  27. 'length' => 255,
  28. ];
  29. return $schema;
  30. }
  31.  
  32.  
  33. function MODULE_install() {
  34. Database::setActiveConnection('NOM_DB');
  35. $schema = MODULE_schema_autre_db();
  36. foreach ($schema as $name => $table) {
  37. Database::getConnection()->schema()->createTable($name, $table);
  38. }
  39. Database::setActiveConnection();
  40. }
  41.  
  42. function MODULE_uninstall() {
  43. Database::setActiveConnection('NOM_DB');
  44. $schema = MODULE_schema_autre_db();
  45. foreach ($schema as $name => $table) {
  46. Database::getConnection()->schema()->dropTable($name);
  47. }
  48. Database::setActiveConnection();
  49. }

 

 

Par Kgaut
Adhérent
Kevin Gautreau

Drupal 8 - Menu - Ajouter un élément de menu avec des paramètres GET

Voici comment créer un Menu item (élément de menu) avec des paramètres GET.

Pour cela on utilise le fichier MON_MODULE.links.menu.yml (à noter que cela marchera aussi dans les fichiers MON_MODULE.links.action.yml et MON_MODULE.links.task.yml)

  1. formations.element:
  2.   title: 'Mon titre de menu'
  3.   weight : 2
  4.   route_name: view.front_formations.page
  5.   menu_name: menu-formation
  6.   options:
  7.   query:
  8.   label: 'prise-de-vue'
  9.   cat: 2

Ici l'url aura comme « query string » : ?label=prise-de-vue&cat=2

Pour rappel la clé menu_name attend le nom du menu dans lequel on veut placer l'élément de menu que l'on vient de définir.

Par Kgaut
Adhérent
Kevin Gautreau

Drupal 8 - Entité - Champ de base « Nombre Décimal »

Le type nombre décimal peut-être pratique pour stocker tout nombre à virgule (un prix par exemple).

Voici comment attacher une propriété « nombre décimal » à un type d'entité personnalisé.

  1. $fields['prix'] = BaseFieldDefinition::create('decimal')
  2. ->setLabel(t('Prix'))
  3. ->setSetting('unsigned', TRUE)
  4. ->setSetting('scale', 2)
  5. ->setSetting('min', 0)
  6. ->setSetting('suffix', '€ TTC')
  7. ->setRequired(TRUE)
  8. ->setDisplayOptions('form', array(
  9. 'type' => 'number',
  10. 'weight' => 5,
  11. ))
  12. ->setDisplayConfigurable('form', TRUE)
  13. ->setDisplayConfigurable('view', TRUE);

 

Par Kgaut
Adhérent
Kevin Gautreau

Drupal 8 - Générer un lien de « flagging » dans le code

Voici comment générer un lien pour « flaguer » une entité avec drupal 8 et le module flag :

  1. $type_entite_a_flaguer = 'user';
  2. $id_entitee_a_flaguer = $user->id();
  3. $id_du_flag = 'follow_user';
  4.  
  5. $f = \Drupal::service('flag.link_builder');
  6. $link = $f->build($type_entite_a_flaguer, $id_entitee_a_flaguer, $id_du_flag);

vous pourrez alors utiliser le lien dans un template en faisant par exemple :

  1. {{- link -}}

 

Par Kgaut
Adhérent
Kevin Gautreau

Drupal 8 - Afficher un webform où l'on veut via le code

Pour récupérer et retourner un webform où l'on veut via le code (que ce soit dans un bloc, un controller...) on peut utiliser les lignes suivantes :

  1. // Ici, « contact » est le nom machine de mon webform
  2. $webform = \Drupal::entityTypeManager()->getStorage('webform')->load('contact');
  3. return $webform->getSubmissionForm();

 

Par Kgaut
Adhérent
Kevin Gautreau

Drupal 8 - Domain Access - récupérer le domaine courant

Voici comment récupérer le domaine actif quand on utilise le module Domain Access pour Drupal 8 :

  1. $current_domain = \Drupal::service('domain.negotiator')->getActiveDomain();

Pour récupérer le domaine par défaut :

  1. $default_domain = \Drupal::service('domain.negotiator')->loadDefaultDomain();

 

Par Kgaut
Adhérent
Kevin Gautreau

Drupal 8 - Entité - Champ de base « link » (lien / URL)

Pour créer un champ de base de type lien, dans la définition de votre entité :

  1. $fields['mon_lien'] = BaseFieldDefinition::create('link')
  2. ->setLabel(t('Path'))
  3. // valeurs possible : LinkItemInterface::LINK_EXTERNAL ou LinkItemInterface::LINK_GENERIC
  4. ->setSetting('link_type', LinkItemInterface::LINK_GENERIC)
  5. //Activer ou non le titre
  6. ->setSetting('title', DRUPAL_DISABLED)
  7. ->setDisplayOptions('form', [
  8. 'type' => 'link_default',
  9. 'weight' => 0,
  10. ])
  11. ->setDisplayConfigurable('form', TRUE);

 

Par Kgaut
Adhérent
Kevin Gautreau

Drupal 8 & Search API - effectuer une requête dans le code

Avec Drupal et Drupal 8 encore plus la recherche passe la plupart du temps par Search API, une interface qui se branche devant plusieurs moteur de base de données (SolR, ElasticSearch, Database...)

Le plus souvent on va faire nos pages de résultats de recherche à l'aide de Views (et du module Search views pour Drupal 7). Mais dans certains cas on va vouloir avoir plus la main sur la recherche et donc aller interroger Search API directement dans le code.

Initialisation de la requête

Chargement de l'index (ici, le nom machine est « contenu »)

  1. // Chargement de l'index « contenu »
  2. $query = Index::load('contenu')->query();

Définition de la requête recherchée

Terme sur lesquels vont être effectués la requête.

  1. // On lancer la recherche sur « hello world »
  2. $query->keys("hello world");

Mode de la requête

  1. // Les différentes possibilités sont
  2. // - « direct » => Requête directe
  3. // - « terms » => Multiple words
  4. // - « phrase » => Single phrase
  5. $parse_mode = \Drupal::service('plugin.manager.search_api.parse_mode')->createInstance('direct');
  6.  
  7. // Optionnellement, on peut choisir un opérateur spécifique (OR ou AND)
  8. $parse_mode->setConjunction('OR');
  9.  
  10. // Affectation du mode de la requête
  11. $query->setParseMode($parse_mode);

Définitions des champs sur lesquels rechercher

Évidement c'est optionnel, par défaut la recherche se fera sur l'ensemble des champs « fulltext » contenus dans l'index.

  1. // Recherche uniquement sur le champ « body »
  2. $query->setFulltextFields(['body']);
  3.  
  4. // Recherche uniquement sur les champs « body » et « title »
  5. $query->setFulltextFields(['body', 'title']);

Ajout de conditions supplémentaires

L'objet retourné par Index::load('contenu')->query(); est une query classique drupal, sur laquelle on peut effectuer les traitement classique que l'on peut faire sur n'importe quelle Query drupal8.

À noter ici que le nom des champs doit être celui que l'on renseigne dans l'index, ils peuvent être différents des noms des champs définis dans nos types de contenu.

Quelques exemples en vrac :

Condition sur un champ boolean

  1. // le champ private doit être « TRUE »
  2. $query->addCondition('private', TRUE);

Condition sur un champ « varchar »

  1. // on veut que le contenu retourné soit un article ou un snippet
  2. $query->addCondition('type', ['article', 'snippet'], 'IN');

Condition sur un champ date

À noter le format de date à utiliser : "Y-m-d\TH:i:s\Z"

  1. $btf = \DateTime::createFromFormat('d/m/Y', '21/10/2015');
  2. $date_formatted = $btf->format("Y-m-d\TH:i:s\Z")
  3.  
  4. // Date de création de l'article > date définie
  5. $query->addCondition('created', $date_formatted, '>');
  6.  
  7. // Et l'inverse
  8. $query->addCondition('created', $date_to, ');

Pagination

Gestion de la pagination identique à une requête classique

  1. // Récupération des 20 premiers résultats.
  2. $query->range(0, 20);

Exécution de la requête et récupération des résultats

  1. $results_set = $query->execute();
  2.  
  3. //Nombre de résultats retournés
  4. $nb_results = $results_set->getResultCount()
  5.  
  6. // Récupération des entités
  7. foreach ($results_set->getResultItems() as $item) {
  8. $resultat = $item->getOriginalObject()->getValue();
  9. }

Sources

Pas trouvé grand chose sur le sujet à part cette page dans la documentation sur drupal.org : https://www.drupal.org/docs/8/modules/search-api/developer-documentatio…

Si vous avez d'autres liens pouvant aider, je suis preneur.

Par Kgaut
Adhérent
Kevin Gautreau

Drupal - Création d'une table dans une base secondaire

Voici comment créer une table dans une base de donnée autre que celle par défaut.

Code à mettre dans votre MODULE.install

Le principe : création d'un « HOOK_schema fake » et utilisation des HOOK_install et HOOK_uninstall pour créer / supprimer cette table en sélectionnant la bonne base.

Le code est pour drupal 8 mais il peut facilement être adapté pour drupal 7.

  1.  
  2. use \Drupal\Core\Database\Database;
  3.  
  4. function MODULE_schema_autre_db() {
  5. $schema['users'] = [
  6. 'description' => 'Members informations',
  7. 'fields' => [],
  8. 'primary key' => ['id'],
  9. ];
  10.  
  11. $schema['users']['fields']['id'] = [
  12. 'description' => 'ID',
  13. 'type' => 'serial',
  14. 'not null' => TRUE,
  15. 'unsigned' => TRUE,
  16. ];
  17.  
  18. $schema['users']['fields']['uid'] = [
  19. 'description' => 'Drupal ID',
  20. 'type' => 'int',
  21. 'not null' => TRUE,
  22. 'unsigned' => TRUE,
  23. ];
  24.  
  25. $schema['users']['fields']['mail'] = [
  26. 'type' => 'varchar',
  27. 'length' => 255,
  28. ];
  29. return $schema;
  30. }
  31.  
  32.  
  33. function MODULE_install() {
  34. Database::setActiveConnection('NOM_DB');
  35. $schema = MODULE_schema_autre_db();
  36. foreach ($schema as $name => $table) {
  37. Database::getConnection()->schema()->createTable($name, $table);
  38. }
  39. Database::setActiveConnection();
  40. }
  41.  
  42. function MODULE_uninstall() {
  43. Database::setActiveConnection('NOM_DB');
  44. $schema = MODULE_schema_autre_db();
  45. foreach ($schema as $name => $table) {
  46. Database::getConnection()->schema()->dropTable($name);
  47. }
  48. Database::setActiveConnection();
  49. }

 

 

Pages