Bonjour tout le monde

Je suis en train de coder un site destiné à des écrivains, et il faut que je mette en place un système de chapitres. Chaque chapitre dans les histoires arrive avec un ordre précis.

J'ai décidé de créer un setter pour pourvoir remplir cet ordre automatiquement lors de la création du chapitre. C'est simple, je compte le nombre de chapitres appartenant à l'histoire et je fais + 1. Mon champ en base de données s'appelle order.

public function setOrderAttribute(){
            $Story_Chapter = DB::table('chapters')->where('book_id', '=', $this->book_id)->count();
            $value = intval($Story_Chapter) + 1;
            $this->attributes['order'] = $value;
    }

Sauf, que ça ne passe absolument pas et rien ne se crée lorsque je crée un nouveau chapitre :(

J'ai testé la requête ailleurs et j'obtiens bien le nombre de chapitres qu'il y a dans l'histoire...

Merci à vous pour votre aide

10 réponses


kndeye
Réponse acceptée

Hum, je crois que j'ai quelque chose:
les setters ne sont appelés que si on acceède à leur valeur, je m'explique quand tu sauvegarde le chapitre je suis sûr qu'il ya pas de champ order dans ton formulaire donc lors de l'enregistrement il n'utilise (n'accede pas) pas le order de ce fait ton setter qui s'atache sur ce order ne sera jamais appelé à la différence du setter de l'image qui lui a son champ dans le formulaire.
J'espère avoir été assez clair.
Tu peux juste ajouter un champ order de type hidden avec une valeur bidon pour tester ma théorie.

Tout con, mais ta colonne "order" est elle bien fillable ?

Heribert
Auteur

J'avais juste mis l'id dans public $guarded, la j'ai modifié et j'ai mis les autres champs dans public $fillable, ça ne change rien, j'ai même juste fait un $this->attributes['order'] = 1; pour voir et ça n'a rien changé, je reste perplexe. Surtout qu'un autre setter fonctionne.

Je pense que tu n'as pas compris ce que faisait un mutateur

Un mutateur est créé lorsque tu modifies la valeur => si tu fais $chapitre->order = X;

Ce dont tu as besoin pour moi est de check l'event creating et d'ajouter le chapitre à ce moment

Salut, Après avoir lu et relu j'ai vraiment pas vu de bug possible le code est normal pour moi, donc essaies de faire un dd() de quelque chose dans le setter pour voir s'il est vraiment appelé ou zappé.

Heribert
Auteur

Alex, je (re)testerai demain les events.

Kndeye : J'ai essayé de dd() et même d'echo du console.log() en js dans la console, ça ne passe pas du tout. J'avais aussi essayé de faire des event comme préconisé par AlexJM

Je suis nouveau sur Laravel (j'ai du dev une semaine dessus) , il y a quelques mécaniques que je ne connais pas encore, peut être qu'il y a quelques éléments qui m'échappent et que je devrais vous montrer.

Merci pour vos réponses, je vous tiendrais au courant :)

J'aimerai bien voir ton action qui enregistre les chapitres dans la base de données!

Heribert
Auteur

Le voici

public function store(ChaptersRequest $request, Guard $auth)
    {
        $data = $request->all();
        $data['user_id'] = $auth->user()->id;
        Chapter::create($data);
        return redirect(action('BooksController@index'))->with('success', 'Nouveau chapitre enregistré');
    }

et le ChaptersRequest

public function rules()
    {
        $rules = [
            'title'   =>  "required|min:2",
            'content' => "required|min:10",
            'user_id' => "integer|exists:users,id",
            'book_id' => "integer|mybook",
            'image'   => "image",
            'slug' => "min:2"
        ];

        if($this->method('POST')){
            $rules['slug'] .= '|unique:chapters';
        }

        return $rules;
    }

La fonction authorize retourne bien true. Avec ma classe Chapter j'ai un autre setter qui lui fonctionne

public function setImageAttribute($image){
        if(is_object($image) && $image->isValid()){
            self::saved(function($instance) use ($image){
                $dir = public_path() . "/img/covers_chapter/".ceil($instance->id / 1000);
                if(!file_exists($dir)){
                    mkdir($dir, '0777', true);
                }
                ImageManagerStatic::make($image)->save($dir."/{$instance->id}.jpg");
            });
            $this->attributes['image'] = true;
        }
    }
Heribert
Auteur

Merci beaucoup kndeye,

C'était bien ça.

Cependant j'ai préféré dans la fonction @strore de faire un data['order'] plutot que de rajouter un champ dans le html, c'est plus sécu pour moi, comme ça un petit malin ne peut pas aller dans le inspecter l'élément :)

Merci à tous ceux qui m'ont aidé :)

Pas de quoi, pour le truc du champ html c'était juste pour tester.