# CHAPITRE 20 — Insérer des données Dolibarr (shortcodes)

<span style="white-space: pre-wrap;">Les slots stockent du contenu éditable. Les </span>**shortcodes**, eux, affichent des données Dolibarr lues en direct (produits, catégories, informations société, médias). Ils sont résolus au moment du rendu, à chaque consultation de page.

### <span style="color: rgb(35, 111, 161);">Distinction entre slot et shortcode</span>

<table id="bkmrk-slotshortcodestocke-" style="width: 100%; border-collapse: collapse; margin: 1rem 0px; font-size: 0.95em;"><colgroup><col></col><col></col></colgroup><tbody><tr style="background: rgb(25, 5, 45); color: rgb(254, 252, 232);"><th class="align-left" style="padding: 0.6rem 1rem; text-align: left; border: 1px solid rgb(25, 5, 45);">Slot

</th><th class="align-left" style="padding: 0.6rem 1rem; text-align: left; border: 1px solid rgb(25, 5, 45);">Shortcode

</th></tr><tr><td style="padding: 0.6rem 1rem; border: 1px solid rgb(229, 231, 235);"><span style="white-space: pre-wrap;">Stocke du </span>

**contenu éditable**

<span style="white-space: pre-wrap;"> par le client.</span>

</td><td style="padding: 0.6rem 1rem; border: 1px solid rgb(229, 231, 235);"><span style="white-space: pre-wrap;">Affiche des </span>

**données Dolibarr**

<span style="white-space: pre-wrap;"> lues en direct.</span>

</td></tr><tr style="background: rgb(250, 245, 255);"><td style="padding: 0.6rem 1rem; border: 1px solid rgb(229, 231, 235);"><span style="white-space: pre-wrap;">Persistance dans </span>

`<span class="editor-theme-code">llx_infrasstudio_slot</span>`

.

</td><td style="padding: 0.6rem 1rem; border: 1px solid rgb(229, 231, 235);">Aucune persistance — résolu à chaque requête.

</td></tr><tr><td style="padding: 0.6rem 1rem; border: 1px solid rgb(229, 231, 235);"><span style="white-space: pre-wrap;">Exemple : </span>

`<span class="editor-theme-code">{{slot:hero_title|type=text}}</span>`

</td><td style="padding: 0.6rem 1rem; border: 1px solid rgb(229, 231, 235);"><span style="white-space: pre-wrap;">Exemple : </span>

`<span class="editor-theme-code">{{product:ref=supplyflow.label}}</span>`

</td></tr></tbody></table>

### <span style="color: rgb(35, 111, 161);">Syntaxe générale</span>

```
{{<namespace>:<sélecteur>.<champ>}}
```

- **namespace**<span style="white-space: pre-wrap;"> : la source de données (</span>`<span class="editor-theme-code">product</span>`<span style="white-space: pre-wrap;">, </span>`<span class="editor-theme-code">category</span>`<span style="white-space: pre-wrap;">, </span>`<span class="editor-theme-code">dict</span>`<span style="white-space: pre-wrap;">, </span>`<span class="editor-theme-code">mysoc</span>`<span style="white-space: pre-wrap;">, </span>`<span class="editor-theme-code">extrafield</span>`<span style="white-space: pre-wrap;">, </span>`<span class="editor-theme-code">media</span>`).
- **sélecteur**<span style="white-space: pre-wrap;"> : la manière d'identifier l'élément (le plus souvent </span>`<span class="editor-theme-code">ref=xxx</span>`<span style="white-space: pre-wrap;"> ou </span>`<span class="editor-theme-code">id=N</span>`).
- **champ**<span style="white-space: pre-wrap;"> : la donnée à extraire de l'élément.</span>

### <span style="color: rgb(35, 111, 161);">Namespace product</span>

<span style="white-space: pre-wrap;">Lit un produit dans la table </span>`<span class="editor-theme-code">llx_product</span>`.

```
<h2>{{product:ref=supplyflow-pro.label}}</h2>
<p>{{product:ref=supplyflow-pro.description}}</p>
<span class="price">{{product:ref=supplyflow-pro.price}} €</span>
<span>{{product:ref=supplyflow-pro.ef_tagline}}</span>
<img src="{{product:ref=supplyflow-pro.ef_hero_image}}" alt="...">
```

##### **Champs disponibles**

<table id="bkmrk-champsourcelabel%2C-de" style="width: 100%; border-collapse: collapse; margin: 1rem 0px; font-size: 0.95em;"><colgroup><col></col><col></col></colgroup><tbody><tr style="background: rgb(25, 5, 45); color: rgb(254, 252, 232);"><th class="align-left" style="padding: 0.6rem 1rem; text-align: left; border: 1px solid rgb(25, 5, 45);">Champ

</th><th class="align-left" style="padding: 0.6rem 1rem; text-align: left; border: 1px solid rgb(25, 5, 45);">Source

</th></tr><tr><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">`<span class="editor-theme-code">label</span>`

<span style="white-space: pre-wrap;">, </span>

`<span class="editor-theme-code">description</span>`

<span style="white-space: pre-wrap;">, </span>

`<span class="editor-theme-code">note</span>`

</td><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);"><span style="white-space: pre-wrap;">Champs natifs (traduits selon la langue du visiteur via </span>

`<span class="editor-theme-code">llx_product_lang</span>`

)

</td></tr><tr style="background: rgb(250, 245, 255);"><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">`<span class="editor-theme-code">price</span>`

<span style="white-space: pre-wrap;">, </span>

`<span class="editor-theme-code">price_ttc</span>`

<span style="white-space: pre-wrap;">, </span>

`<span class="editor-theme-code">cost_price</span>`

</td><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">Prix HT, TTC, coût (formaté selon la langue)

</td></tr><tr><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">`<span class="editor-theme-code">ref</span>`

<span style="white-space: pre-wrap;">, </span>

`<span class="editor-theme-code">tosell</span>`

</td><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">Référence, statut commercialisable

</td></tr><tr style="background: rgb(250, 245, 255);"><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">`<span class="editor-theme-code">ef_<slug></span>`

</td><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">Tout champ personnalisé (

`<span class="editor-theme-code">ef_tagline</span>`

<span style="white-space: pre-wrap;">, </span>

`<span class="editor-theme-code">ef_hero_image</span>`

, etc.)

</td></tr></tbody></table>

##### **Le marqueur $current**

<span style="white-space: pre-wrap;">Pour un même gabarit utilisé par plusieurs produits (par exemple </span>`<span class="editor-theme-code">solution-detail</span>`<span style="white-space: pre-wrap;"> servi par les wrappers </span>`<span class="editor-theme-code">solution-<ref>.php</span>`<span style="white-space: pre-wrap;">), utilisez </span>`<span class="editor-theme-code">ref=$current</span>`<span style="white-space: pre-wrap;"> :</span>

```
<h1>{{product:ref=$current.label}}</h1>
<p>{{product:ref=$current.ef_tagline}}</p>
```

<span style="white-space: pre-wrap;">Le module résout </span>`<span class="editor-theme-code">$current</span>`<span style="white-space: pre-wrap;"> via la variable globale </span>`<span class="editor-theme-code">$infrasstudio_current_product_ref</span>`, posée par le wrapper.

### <span style="color: rgb(35, 111, 161);">Namespace category</span>

<span style="white-space: pre-wrap;">Lit une catégorie dans la table </span>`<span class="editor-theme-code">llx_categorie</span>`.

```
<h3>{{category:id=5.label}}</h3>
<p>{{category:id=5.description}}</p>
```

### <span style="color: rgb(35, 111, 161);">Namespace dict</span>

Lit une entrée d'un dictionnaire Dolibarr (`<span class="editor-theme-code">c_country</span>`<span style="white-space: pre-wrap;">, </span>`<span class="editor-theme-code">c_currencies</span>`, etc.).

```
<span>{{dict:c_country.code=FR.label}}</span>
<span>{{dict:c_currencies.code_iso=EUR.label}}</span>
```

### <span style="color: rgb(35, 111, 161);">Namespace mysoc</span>

Lit les informations de la société courante (`<span class="editor-theme-code">$mysoc</span>`).

```
<footer>
    © {{mysoc.name}} — {{mysoc.address}}, {{mysoc.zip}} {{mysoc.town}}
    Tél : {{mysoc.phone}} — Courriel : {{mysoc.email}}
    SIRET {{mysoc.idprof2}} — TVA {{mysoc.tva_intra}}
</footer>
```

##### **Champs disponibles**

`<span class="editor-theme-code">name</span>`<span style="white-space: pre-wrap;">, </span>`<span class="editor-theme-code">address</span>`<span style="white-space: pre-wrap;">, </span>`<span class="editor-theme-code">zip</span>`<span style="white-space: pre-wrap;">, </span>`<span class="editor-theme-code">town</span>`<span style="white-space: pre-wrap;">, </span>`<span class="editor-theme-code">country_code</span>`<span style="white-space: pre-wrap;">, </span>`<span class="editor-theme-code">phone</span>`<span style="white-space: pre-wrap;">, </span>`<span class="editor-theme-code">fax</span>`<span style="white-space: pre-wrap;">, </span>`<span class="editor-theme-code">email</span>`<span style="white-space: pre-wrap;">, </span>`<span class="editor-theme-code">url</span>`<span style="white-space: pre-wrap;">, </span>`<span class="editor-theme-code">capital</span>`<span style="white-space: pre-wrap;">, </span>`<span class="editor-theme-code">tva_intra</span>`<span style="white-space: pre-wrap;">, </span>`<span class="editor-theme-code">idprof1</span>`<span style="white-space: pre-wrap;"> à </span>`<span class="editor-theme-code">idprof6</span>`<span style="white-space: pre-wrap;">, </span>`<span class="editor-theme-code">logo</span>`<span style="white-space: pre-wrap;">, </span>`<span class="editor-theme-code">logo_small</span>`<span style="white-space: pre-wrap;">, </span>`<span class="editor-theme-code">logo_squarred</span>`.

### <span style="color: rgb(35, 111, 161);">Namespace extrafield</span>

Lit un champ personnalisé d'un objet Dolibarr quelconque.

```
{{extrafield:table=product|ref=supplyflow.field=tagline}}
{{extrafield:table=societe|id=42|field=segment}}
{{extrafield:table=product|ref=$current|field=tagline}}
```

<span style="white-space: pre-wrap;">Plus générique que </span>`<span class="editor-theme-code">{{product:ref=X.ef_tagline}}</span>`<span style="white-space: pre-wrap;"> mais plus verbeux. À utiliser lorsque le namespace dédié n'existe pas (par exemple pour </span>`<span class="editor-theme-code">societe</span>`<span style="white-space: pre-wrap;"> ou </span>`<span class="editor-theme-code">contact</span>`).

### <span style="color: rgb(35, 111, 161);">Namespace media</span>

Lit un média de la bibliothèque du module (`<span class="editor-theme-code">llx_infrasstudio_media</span>`).

```
<img src="{{media:ref=hero-1.url}}" alt="{{media:ref=hero-1.alt}}">
<img src="{{media:ref=hero-1.thumb}}">
<img src="{{media:ref=hero-1.card}}">
<img src="{{media:ref=hero-1.wide}}">
```

##### **Champs disponibles**

<table id="bkmrk-champdescriptionurlu" style="width: 100%; border-collapse: collapse; margin: 1rem 0px; font-size: 0.95em;"><colgroup><col></col><col></col></colgroup><tbody><tr style="background: rgb(25, 5, 45); color: rgb(254, 252, 232);"><th class="align-left" style="padding: 0.6rem 1rem; text-align: left; border: 1px solid rgb(25, 5, 45);">Champ

</th><th class="align-left" style="padding: 0.6rem 1rem; text-align: left; border: 1px solid rgb(25, 5, 45);">Description

</th></tr><tr><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">`<span class="editor-theme-code">url</span>`

</td><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">URL du fichier original

</td></tr><tr style="background: rgb(250, 245, 255);"><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">`<span class="editor-theme-code">thumb</span>`

</td><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">Variante 200 × 200

</td></tr><tr><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">`<span class="editor-theme-code">card</span>`

</td><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">Variante 640 × 480

</td></tr><tr style="background: rgb(250, 245, 255);"><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">`<span class="editor-theme-code">wide</span>`

</td><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">Variante 1600 × 1200

</td></tr><tr><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">`<span class="editor-theme-code">alt</span>`

</td><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">Texte alternatif (résolu selon la langue)

</td></tr><tr style="background: rgb(250, 245, 255);"><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">`<span class="editor-theme-code">label</span>`

<span style="white-space: pre-wrap;">, </span>

`<span class="editor-theme-code">width</span>`

<span style="white-space: pre-wrap;">, </span>

`<span class="editor-theme-code">height</span>`

</td><td style="padding: 0.5rem 1rem; border: 1px solid rgb(229, 231, 235);">Métadonnées

</td></tr></tbody></table>

### <span style="color: rgb(35, 111, 161);">Combiner shortcodes et slots</span>

Vous pouvez intégrer un shortcode dans la valeur par défaut d'un slot, ou dans le contenu d'un slot de type texte riche :

```
<!-- Shortcode dans le default d'un slot -->
<p>{{slot:greeting|type=text|default=Bienvenue chez {{mysoc.name}}}}</p>

<!-- Shortcode dans un slot richtext (l'éditeur peut le saisir librement) -->
<div>{{slot:long_intro|type=richtext|default=Notre équipe à {{mysoc.town}} vous accompagne.}}</div>
```

<p class="callout info">**Cas d'usage —**<span style="white-space: pre-wrap;"> Une page de remerciements après commande qui dit « Merci, votre commande sera livrée à... ». Le HTML reste statique côté gabarit, mais le rendu est personnalisé pour chaque visiteur.</span></p>

### <span style="color: rgb(35, 111, 161);">Étendre avec un namespace personnalisé</span>

<span style="white-space: pre-wrap;">Pour ajouter un namespace propre à votre projet, déposez un fichier dans </span>`<span class="editor-theme-code">htdocs/custom/infrasstudio/shortcodes/</span>`<span style="white-space: pre-wrap;"> :</span>

```
// shortcodes/myorg.shortcode.php
function infrasstudio_shortcode_myorg_resolve($args, $context)
{
    global $db;
    $id    = isset($args['id']) ? (int) $args['id'] : 0;
    $field = isset($args['_field']) ? $args['_field'] : 'name';
    if ($id <= 0) { return ''; }

    $sql = "SELECT name, sector FROM ".MAIN_DB_PREFIX."myorg WHERE rowid = ".$id;
    $resql = $db->query($sql);
    if (!$resql) { return ''; }
    $obj = $db->fetch_object($resql);
    $db->free($resql);
    return isset($obj->$field) ? (string) $obj->$field : '';
}
```

Utilisable dans n'importe quel gabarit :

```
<h2>{{myorg:id=12.name}}</h2>
<p>Secteur : {{myorg:id=12.sector}}</p>
```

### <span style="color: rgb(35, 111, 161);">Pièges et performance</span>

**Shortcode dans une boucle —**<span style="white-space: pre-wrap;"> Si vous résolvez cent fois le même shortcode dans une page, vous effectuez cent requêtes SQL. Mettez vos données en cache dans une variable locale avant la boucle, ou utilisez les fonctions natives Dolibarr (</span>`<span class="editor-theme-code">Product::fetch</span>`) en PHP.

**Shortcode introuvable —**<span style="white-space: pre-wrap;"> Si </span>`<span class="editor-theme-code">{{product:ref=inexistant.label}}</span>`<span style="white-space: pre-wrap;"> ne résout rien, le module retourne une chaîne vide silencieusement. Aucune erreur n'est affichée. Testez en local avant la livraison.</span>

**Shortcodes dans les attributs —**<span style="white-space: pre-wrap;"> Les shortcodes fonctionnent dans tous les contextes HTML, attributs compris : </span>`<span class="editor-theme-code"><img src="{{media:ref=X.url}}"></span>`<span style="white-space: pre-wrap;">, </span>`<span class="editor-theme-code"><a href="{{slot:cta_url|...}}"></span>`, etc.

### <span style="color: rgb(35, 111, 161);">Récapitulatif</span>

**Vous savez désormais :**

- Distinguer slots (contenu éditable) et shortcodes (données Dolibarr).
- Utiliser les six namespaces livrés (product, category, dict, mysoc, extrafield, media).
- <span style="white-space: pre-wrap;">Utiliser </span>`<span class="editor-theme-code">$current</span>`<span style="white-space: pre-wrap;"> dans les gabarits partagés entre plusieurs produits.</span>
- Combiner shortcodes et slots.
- <span style="white-space: pre-wrap;">Ajouter votre propre namespace via un fichier dans </span>`<span class="editor-theme-code">shortcodes/</span>`.
- Anticiper les pièges (boucles, valeurs absentes).