Bonjour à tous, je viens soliciter votre aide sur un projet que je développe sur mes temps libre.

Pour résumé simplement J'ai une base de clients, une base d'unités de stockage et je dois créer des entrées en stockage, je choisi donc un client, je lui attribut une ou plusieurs unités de stockage avec une date d'entrée par unité et une date de sortie pour le jour ou il libère l'espace.

Je suis donc parti sur 3 modèles

Client :

class Client extends AppModel {
    public $name = 'Client';

    public $hasMany = array('ClientStockage');
}

Stockage :

class Stockage extends AppModel {
    public $name = 'Stockage';

    public $hasMany = array('ClientStockage');
}

ClientStockage :

class ClientStockage extends AppModel {
    public $name = 'ClientStockage';

    public $belongsTo = array(
        'Client' => array(
            'className' => 'Client', 
            'foreignKey' => 'client_id'
        ),
        'Stockage' => array(
            'className' => 'Stockage',
            'foreignKey' => 'stockage_id'
        )
    );
}

Ces modèles sont liés par une relation HasAndBelongsToMany car j'ai besoin de stocker des informations supplémentaires dans la table ClientStockage. Jusque la tout va bien, les données sont bien enregistrées.

Mon problème : j'ai un formulaire d'ajout pour ClientStockage qui propose des selects déja remplis avec les noms des clients, les id des stockages, puis des champs pour les infos supplémentaires, le soucis c'est que je voudrais qu'un stockage ne puisse être attibué qu'une fois à un client (un client peut avoir plusieurs stockage mais un stockage ne peut avoir qu'un client) et cela ne fonctionne pas, je n'arrive pas à remplir mes champs avec seulement les id des stockages encores disponibles.

La fonction dans mon controller ClientStockages :

public function in() {
        // On fait passer à la vue les infos pour remplir les input select
        $this->set('clients', $this->ClientStockage->Client->find('list', array('fields' => array('Client.nom'))));
        $this->set('stockages', $this->ClientStockage->Stockage->find('list', array('fields' => array('Stockage.id'))));

        if ($this->request->is('post')) {
            if ($this->ClientStockage->saveAssociated($this->request->data)) {
                return $this->redirect(array('action' => 'index'));
                debug($this->request->data);
            }
        }
    }

Mes relations ne sont pas bonnes mais dans ce cas quelle structure utiliser puisque je veux sauvergarder des infos supplémentaires dans l'association Client-Stockage, tel que date d'entrée, de sortie....

Sinon je pensais rajouter un champ location dans ma table Stockage qui serait sur 0 et qui passerait à 1 si la caisse est attribuée à un client, mais je n'arrive pas à gérer cet enregistrement depuis mon controller ClientStockages

J'espère que je suis clair et merci d'avance de l'aide que vous pourrez m'apporter.

5 réponses


Wa3aR
Réponse acceptée

Pour ton problème d'enregistrement, tu dois juste spécifier l'ID du stockage avant de faire la sauvegarde. Je pense que tu dois récupèrer l'ID depuis ta view tu y auras accès donc dans $this->request->data["Stockage"]["id"] il te suffit de rajouter avant le saveField :

$this->Stockage->id = $this->request->data["Stockage"]["id"]; 

De cette manière tu spécifies précisement quel stockage modifier.

Tu peux stocker autant d'informations que tu le souhaites dans ta table clients_stockages qui relient tes modèles en HABTM. Il te suffit juste de créer un modèle qui utilisera la table de liaison. Dans ton cas, tu auras une configuration comme ça :

// Model Client.php
class Client extends AppModel {
    public $hasMany = array("Occupation"); 
    public $hasAndBelongsToMany = array("Stockage"); 
}

// Model Stockage.php
class Stockage extends AppModel {
    public $hasMany = array("Occupation"); 
    public $hasAndBelongsToMany = array("Client"); 
}

// Model Occupation.php (ou n'importe quel autre nom) 
class Occupation extends AppModel {
    public $useTable = "clients_stockages"; 
    public $belongsTo = array("Client", "Stockage"); 
}

Ta table clients_stockages pourra contenir autant de colonnes que tu le souhaites et tu y auras accès depuis tes controllers ClientsController et StockagesController avec un $this->Client->Occupation par exemple. La méthode que je décris est précisée dans le book de Cake et Graf en parle dans sa formation (chapitre Association). Je te conseille de jeter un oeil la-dessus.

Pour ton second problème, personnellement, je rajouterai une colonne attribué à ta table stockages qui sera en boolean (donc tinyint de 1) et je fixerai à true dés que je ferai une sauvegarde sur la table Occupation. Ainsi pour récupérer les stockages qui sont disponibles, tu n'auras qu'à faire un find avec comme condition attribué a 0.

$stockages = $this->Occupation->Stockage->find("list", array("conditions" => array("attribue" => "0"))); 

Et normalement ça devrait marcher :)

kozzy34
Auteur

Merci pour ton aide.

Si je ne dis pas de bétise J'ai la même structure, sauf que je n'ai pas appelé mon model occupation, ce qui est d'ailleur une bonne idée ;) j'étais resté bloqué sur les conventions de nommage, alors que je vois qu'on peut déclarer un nom différent pour ce model grace à $usetable.

Sur les models tu rajoutes des relation HABTMs pour Client et Stockage, je vais voir ce que ça donne car pour l'instant je n'avais défini aucune relations entre ces deux modèles.

J'ai déja rajouté une colone "attribué" en boolean dans ma table stockage mais je n'arrive pas à gérer l'enregistrement depuis mon controller Occupation, il m'enregistre bien les données pour le model Occupation mais dans le modèle stockage il me rajoute un ligne avec juste le champ "attribué" à 1 au lieu de mettre la valeur 1 sur la ligne correspondant à l'id du stockage que je viens d'attribuer à un client.

Voici la fonction dans mon controller Occupations

public function in() {
        // On fait passer à la vue les infos pour remplir les input select
        $this->set('clients', $this->Occupation->Client->find('list', array('fields' => array('Client.nom'))));
        $this->set('stockages', $this->Occupation->Stockage->find('list', array('fields' => array('Stockage.id', array('conditions' => array('attribue' => '0'))))));

        if ($this->request->is('post')) {
            if ($this->Occupation->saveAssociated($this->request->data)) {
                $this->Stockage->saveField('attribue', '0');
                return $this->redirect(array('action' => 'index'));
            }
        }
    }
kozzy34
Auteur

Super, ça fonctionne parfaitement.

Voici ma fonction :

public function stockage_entry() {
        // On fait passer à la vue les infos pour remplir les input select
        $this->set('clients', $this->Occupation->Client->find('list', array('fields' => array('Client.nom'))));
        $this->set('stockages', $this->Occupation->Stockage->find('list', array(
            'fields' => array('Stockage.ref'),
            'conditions' => array('attribue' => '0')
        )));

        if ($this->request->is('post')) {
            if ($this->Occupation->saveAssociated($this->request->data)) {
                $this->Stockage->id = $this->request->data["Occupation"]["stockage_id"]; 
                $this->Stockage->saveField('attribue', '1');
                return $this->redirect(array('action' => 'index'));
            }
        }
    }

Merci beaucoup ton aide, je voyais bien que l'id n'était spécifié nul part mais je ne savais pas comment le récupérer !!

De rien ^^ ravi de voir que ça fonctionne !