Tabla de Contenidos

SmartMaker - Back (PHP)

La partie backoffice de SmartMaker s'intègre dans un module Dolibarr standard.

Structure des dossiers

Lorsque vous déployez SmartMaker dans votre module Dolibarr, les dossiers suivants sont créés :

Dossier Description
mobile/ Code source React de l'application mobile
pwa/ Application compilée + point d'entrée api.php
smartmaker-api/ Contrôleurs et mappeurs PHP

Et un fichier smartmaker-api-prepend.php pour factoriser les includes.

Le routeur PHP

Syntaxe

Route::action(path, Controller::class, method, protected);
Paramètre Description
action get, post, put, delete
path Chemin de l'API (ex: items, items/{id})
Controller::class Classe PHP à appeler
method Méthode de la classe
protected true = route authentifiée, false = publique

Exemple complet (api.php)

<?php
require_once '../smartmaker-api-prepend.php';

use SmartAuth\Api\AuthController;
use SmartAuth\Api\RouteController as Route;
use MyModule\Api\ItemController;

// Routes publiques (authentification)
Route::get('login',     AuthController::class, 'index');
Route::post('login',    AuthController::class, 'login');
Route::get('refresh',   AuthController::class, 'refresh');

// Routes protégées (nécessitent un token JWT)
Route::post('logout',   AuthController::class, 'logout', true);
Route::post('device',   AuthController::class, 'device', true);

// CRUD sur les items
Route::get('items',         ItemController::class, 'index', true);
Route::get('items/{id}',    ItemController::class, 'show', true);
Route::post('items',        ItemController::class, 'create', true);
Route::put('items/{id}',    ItemController::class, 'update', true);
Route::delete('items/{id}', ItemController::class, 'delete', true);

// Routes avec filtres
Route::post('items/{filter}', ItemController::class, 'search', true);

// Fichiers
Route::get('file/{element}/{parentid}/{ref}', FileController::class, 'download', true);

// Fallback
json_reply('Access denied', 403);

Paramètres dynamiques

Les paramètres entre accolades sont passés dans le payload :

// Route: GET /items/123
Route::get('items/{id}', ItemController::class, 'show', true);

// Dans le controller:
public function show($payload)
{
    $id = $payload['id']; // 123
}

Créer un Controller

Structure de base

<?php
namespace MyModule\Api;

class ItemController
{
    public function __construct() {}

    /**
     * Liste des items
     * @param array|null $payload Données de la requête
     * @return array [data, httpCode]
     */
    public function index($payload = null)
    {
        global $db, $user;

        // Votre logique ici
        $items = [];

        return [$items, 200];
    }

    /**
     * Récupérer un item
     */
    public function show($payload = null)
    {
        global $db;

        $id = $payload['id'] ?? null;

        if ($id === null) {
            return ['Not Found', 404];
        }

        // Fetch l'objet
        $item = new \MyObject($db);
        $res = $item->fetch($id);

        if ($res <= 0) {
            return ['Not Found', 404];
        }

        // Mapper pour le front
        $mapping = new dmMyObject();
        $data = $mapping->exportMappedData($item);

        return [$data, 200];
    }

    /**
     * Créer un item
     */
    public function create($payload = null)
    {
        global $db, $user;

        $item = new \MyObject($db);
        $item->label = $payload['label'];
        $item->description = $payload['description'];

        $res = $item->create($user);

        if ($res < 0) {
            return ['Error creating item', 500];
        }

        return [['id' => $res], 201];
    }

    /**
     * Mettre à jour un item
     */
    public function update($payload = null)
    {
        global $db, $user;

        $id = $payload['id'] ?? null;

        $item = new \MyObject($db);
        $res = $item->fetch($id);

        if ($res <= 0) {
            return ['Not Found', 404];
        }

        // Mettre à jour les champs
        if (isset($payload['label'])) {
            $item->label = $payload['label'];
        }

        $res = $item->update($user);

        if ($res < 0) {
            return ['Error updating item', 500];
        }

        return ['Updated', 200];
    }

    /**
     * Supprimer un item
     */
    public function delete($payload = null)
    {
        global $db, $user;

        $id = $payload['id'] ?? null;

        $item = new \MyObject($db);
        $res = $item->fetch($id);

        if ($res <= 0) {
            return ['Not Found', 404];
        }

        $res = $item->delete($user);

        if ($res < 0) {
            return ['Error deleting item', 500];
        }

        return ['Deleted', 200];
    }

    /**
     * Recherche avec filtres
     */
    public function search($payload = null)
    {
        global $db;

        $filter = $payload['filter'] ?? 'all';
        $limit = $payload['limit'] ?? 10;

        // Construire la requête SQL
        $sql = "SELECT rowid FROM " . MAIN_DB_PREFIX . "myobject";
        $sql .= " WHERE 1=1";

        if ($filter === 'active') {
            $sql .= " AND status = 1";
        }

        $sql .= " LIMIT " . (int) $limit;

        $resql = $db->query($sql);
        $items = [];

        while ($obj = $db->fetch_object($resql)) {
            $item = new \MyObject($db);
            $item->fetch($obj->rowid);

            $mapping = new dmMyObject();
            $items[] = $mapping->exportMappedData($item);
        }

        return [$items, 200];
    }
}

Accès à l'utilisateur connecté

L'utilisateur JWT est disponible dans le payload :

public function update($payload = null)
{
    $user = $payload['user']; // Objet User Dolibarr

    dol_syslog("Action par: " . $user->login);
}

Voir aussi