j'ai lu dans le book qu'il est possible de créer un setter qui permet de modifier un champ dans l'entity :

  protected function _setTitle($title)
    {
        $this->set('slug', Inflector::slug($title));
        return $title;
    }

auteur : Rousseau
livre : Les confessions
mais par exemple si j'ai 2 champs (auteur + livre), comment puis je créer un setter pour obtenir dans mon champ name :

ce que je veux => name : Rousseau - Les confessions

16 réponses


Havok
Réponse acceptée

Ah, j'ai voulu faire éditer, mais j'ai fait "Supprimer".
J'ai creusé un peu et l'erreur apparaît pr une raison simple.
Lorsque l'Entity est créée, les propriétés sont parcourus dans l'ordre dans lequel elles sont données dans le tableau qui crée l'Entity.
Du coup, vu que tu crées ton Entity à partir de $this->request->data, les propriétés sont set dans l'ordre dans lequel tes champs sont créés dans ton formulaire (j'imagine que dans ton formulaire, name est avant prenom).
Du coup, tu devrais changer pour ça :

protected function _setPrenom($prenom)
{
    $fullname = trim($prenom . ' - ' . $this->_properties['name']);
    $this->set('fullname', $fullname);

    return $prenom;
}

Hello,

/**
 * Set the name of the user with his book.
 *
 * @return string
 */
protected function _setName($name)
{
    $name = trim($this->auteur . ' - ' . $this->livre);

    return $name;
}
alexyon
Auteur

et pourtant la sauvegarde en BDD ne prend pas en compte le champ name :

    protected function _setName($name)
    {
        $this->set('name', trim($this->auteur . ' - ' . $this->livre););
        return $name;
    }

Bonjour.

et pourtant la sauvegarde en BDD ne prend pas en compte le champ name

Tu n'as pas compris le principe et tu as mal reproduis le code, de plus que tu as des erreurs de ;.
L'exemple que tu nous montres de la doc, c'est pour effectuer un slug à partir du champ title.
Si tu veux que le name soit sauvegardé en base de donné avec la concaténation avec le livre, reproduis correctement le code que t'a proposé Xeta.
Par contre, ne confonds pas les setters et les getters.

alexyon
Auteur

slt à tous les 2,
même en recopiant exactement son code, la sauvegarde de ce champ ne se fait pas.
si je debug l'entity juste avant la sauvegarde, il devrait me l'afficher ?
voila comment je lai adapté :

protected function _setFullname($fullname)
{
    $fullname = trim($this->name . ' - ' . $this->prenom);

    return $fullname;
}

même en recopiant exactement son code, la sauvegarde de ce champ ne se fait pas.

Est-ce que tu transmets bien les données des deux champs au moment de la sauvegarde ?
Car si tu ne transmets pas par exemple le livre il ne pourra pas faire la sauvegarde du champ via le setter.
Et puis vérifies si ce n'est pas un problème de la taille du champ name.

alexyon
Auteur

jai mis le champ fullname en varchar 255
voila ce que me sort l'entity apres sauvegarde :

object(App\Model\Entity\Identite) {

    '_csrfToken' => '53aea4530bc326e26adb02a559d7931bf5551ca0',
    'name' => 'dupond',
    'prenom' => 'michel',
    'id' => (int) 40,
    '[new]' => false,
    '[accessible]' => [
        '*' => true
    ],
    '[dirty]' => [],
    '[original]' => [],
    '[virtual]' => [],
    '[errors]' => [],
    '[repository]' => 'Identites'

}

Si tu as les 2 champs "auteur" et "livre" sauvegardés en base, tu possèdes également une autre solution qui t'évite de sauvegarder un troisième champ qui concatène simplement les deux. Tu peux créer une "propriété virtuelle" :

// Va créer une propriété virtuelle "name" pour l'Entity
protected function _getName()
{
        return $this->_properties['auteur'] . ' - ' . $this->_properties['livre'];
}

Et y accéder comme s'il s'agissait d'une propriété classique de ton Entity :

echo $entity->name;

L'avantage c'est que si tu mets à jour l'un ou l'autre champ, ta propriété "name" sera mise à jour automatiquement.

Plus de détails sur le Cookbook : http://book.cakephp.org/3.0/fr/orm/entities.html#creer-des-proprietes-virtuelles

alexyon
Auteur

merci Havok, mais je voudrais surtout savoir pkoi je n'arrive pas sauvegarder ce champ.
ps : vraiment dommage qu'on ne puisse pas se servir de ces virtual dans les find...

Avec ton exemple "setFullName" (ici http://www.grafikart.fr/forum/topics/19255#forum-post-76414), tu ne fais pas de

$this->set('fullname', $fullname);

dans ta méthode. Du coup ton champ n'est pas ajouté à l'entity.

alexyon
Auteur

voila ma méthode mais le champ fullname ne se remplit pas

protected function _setFullname($fullname)
{
    $fullname = trim($this->name . ' - ' . $this->prenom);
    $this->set('fullname', $fullname);

    return $fullname;
}

Peux-tu essayer de vider le cache de l'ORM ?

Via le Shell :

bin/cake orm_cache clear

(http://book.cakephp.org/3.0/fr/console-and-shells/orm-cache.html)

On dirait que l'ORM n'est pas au courant que ton champ fullname existe d'après ce que l'Entity retourne.

alexyon
Auteur

mon entity est construite à partir du ($this->request->data), donc comme je ne mets pas dedans le champ fullname, il me parait normal qu'il n'apparaisse pas.
car si je fais un get($id), le champ fullname apparait :

object(App\Model\Entity\Identite) {

    'id' => (int) 51,
    'name' => 'dupont',
    'prenom' => 'michel',
    'fullname' => '',
    '[new]' => false,
    '[accessible]' => [
        '*' => true
    ],
    '[dirty]' => [],
    '[original]' => [],
    '[virtual]' => [],
    '[errors]' => [],
    '[repository]' => 'Identites'

}

Ah, c'est pour ça.
Ta méthode _setFullname n'est jamais appelée car à aucun moment tu ne fournis fullname à l'entity.
Tu devrais faire ton set('fullname', ...) sur _setName ou _setPrenom

Cependant pour ce cas là, je reste sur mon premier conseil : une propriété virtuelle reste la meilleure solution.

alexyon
Auteur

Oui, je comprends, mais c'est juste pour comprendre comment fonctionne un setter.
j'ai essayé ca :

protected function _setName($fullname)
{
    $fullname = trim($this->name . ' - ' . $this->prenom);
    $this->set('fullname', $fullname);

    return $fullname;
}

et dans la base il remplit les champs name et fullname avec un tiret; donc 2 prob :
1 - il écrase le name
2 - il ne trouve pas $this->name et $this->prenom

alexyon
Auteur

on y est presque ; mais il ne connait pas $this->_properties['prenom']

Notice (8): Undefined index: prenom [APP/Model/Entity/Identite.php, line 26]