Bug Cake PHP 3 ?

Par Muxabble, il y a 11 ans


Hello, j'ai voulu installé le Plugin d'Upload de Xeta, j'ai donc DL le plugin et l'est installer dans plugins, et j'ai une erreur absurde !

*Xety/Cake3Upload.UploadBehavior could not be found.aroundaroundMake sure your plugin Xety/Cake3Upload is in the /var/www/local.dev/jobcarer/plugins/ directory and was loaded.* *Error: Create the class UploadBehavior below in file: /var/www/local.dev/jobcarer/plugins/Xety/Cake3Upload/src/Model/Behavior/UploadBehavior.php*

47 réponses

Grafikart, il y a 11 ans

Et tu l'as bien load ?

Muxabble, il y a 11 ans

Ba j'ai utilisé

Plugin::loadAll();

pour être sur et j'ai même essayé

Plugin::load('Xety\Cake3Upload);

rien à faire

Muxabble, il y a 11 ans

Alors je viens de l'installer avec composer sauf que je n'ai rien dans mon fichier plugins .. bon je vais essayer de le mettre dans le model du coup ! le soucis c'est est-ce adaptable pour upload des images à la une par exemple ?!

JC_Pires, il y a 11 ans

Mets le dans tes dépendences de composer et puis composer Update , il va te l'installer dans le dossier Vendor et tu n'auras qu'a le load après dans ton bootstrap.php

Exemple de mon composer.json

{ "name": "cakephp/app", "description": "CakePHP skeleton app", "homepage": "http://cakephp.org", "type": "project", "license": "MIT", "require": { "php": ">=5.4.16", "cakephp/cakephp": "~3.0", "mobiledetect/mobiledetectlib": "2.*", "cakephp/migrations": "@stable", "ezyang/htmlpurifier": "dev-master", "cakephp/plugin-installer": "*", "xety/cake3-sluggable": "1.*", "xety/cake3-upload": "1.*", "xety/cake3-cookieauth": "1.*" }, "require-dev": { "psy/psysh": "@stable", "cakephp/debug_kit": "~3.0", "cakephp/bake": "~1.0" }, "suggest": { "phpunit/phpunit": "Allows automated tests to be run without system-wide install.", "cakephp/cakephp-codesniffer": "Allows to check the code against the coding standards used in CakePHP." }, "autoload": { "psr-4": { "App\\": "src" } }, "autoload-dev": { "psr-4": { "App\\Test\\": "tests", "Cake\\Test\\": "./vendor/cakephp/cakephp/tests" } }, "scripts": { "post-install-cmd": "App\\Console\\Installer::postInstall", "post-autoload-dump": "Cake\\Composer\\Installer\\PluginInstaller::postAutoloadDump" }, "minimum-stability": "dev", "prefer-stable": true }
Muxabble, il y a 11 ans

Ah oui non je ne peux pas utiliser composer, il trouve toujours des erreurs du coup ba je ne l'utilise pas !

JC_Pires, il y a 11 ans

Ah dommage. Il faut vraiment que tu vois à ça car c'est incontournable de nos jours.

Est-ce que le plugin est bien dans le dossier plugin sous cette forme Tondossier/plugins/xety/cake3-upload

Où a tu pris la version que tu as installée 'github j'imagine' et comment?

Si tu l'as pris en .zip par exemple, le dossier ressemble à ceci cake3-upload-master si tu as copié/collé ce dossier tel quel dans ton dossier plugins ça n'ira pas il te faut bien le mettre dans un dossier xety et renommer ton dossier cake3-upload-master en cake3-upload à l'intérieur du dossier plugins/xety. En tout cas c'est comme ça qu'il est dans le dossier vendor. C'est tellement plus simple avec composer qu'il faut que tu corriges ton problème.

En espérant t'aider.

Muxabble, il y a 11 ans

Oui j'ai bien renomé le dossier et j'ai enfin pris le temps de voir ce foutu soucis de Composer ! En fait vu que j'avais tester Symfony ba j'avais instalelr NFS, et apparement il y aurais des bugs avec ce module du coup j'ai refais une VM sans NFS x)

JC_Pires, il y a 11 ans

Bon du coup tu devrais pas avoir trop de problème pour l'installer maintenant. Sinon ce n'est qu'une simple classe "Behavior". Tu pourrais juste déplacer le fichier dans le bon dossier dans ton dossier src/Model/Behavior, changer le namespace et hop ça fonctionnera tout aussi bien.

Dossier: src/Model/Behavior
Namespace: App\Model\Behavior

Après t'adaptes juste pour l'attacher à tes models, par exemple

$this->addBehavior('Upload', [ 'fields' => [ 'avatar' => [ 'path' => 'upload/avatar/:id/:md5' ] ] ] );
JC_Pires, il y a 11 ans

Lors d'une installation avec Composer toutes tes dépendences s'installeront dans ton dossier vendor, je fais toujours apres un: composer dumpautoload pour être sûr que toutes les classes soient prise en compte dans l'autoloader.

Pour l'avoir testé et l'utiliser dans mon projet de CMS Blog/Forum, ce behavior te permet de sauter tout la partie enregistrement des fichiers envoyé dans tes formulaires juste en spécifiant le nom de l'input d'une certaine manière, manière que tu peut redéfinir lors de l'attachement du Behavior à ton Model.

Dans un formulaire d'une vue, exemple la vue se trouvant dans src/Templates/Topics/add.ctp:

<?= $this->Form->input('thumbnails_file', ['type' => 'file']) ?>

Dansl le Model, exemple le model se trouvant dans src/Model/Table/TopicsTable.php:

<?php namespace App\Model\Table; use Cake\ORM\Table; use Cake\ORM\Query; use Cake\Validation\Validator; class TopicsTable extends Table { public function initialize(array $config) { $this->table('topics'); $this->displayField('id'); $this->primaryKey('id'); $this->addBehavior('Xety/Cake3Upload.Upload', [ 'fields' => [ 'thumbnails' => [ 'path' => '/img/articles/:y/:m/:md5', 'overwrite' => true, ] ] ] ); } }

Tu as la possibilité de redéfinir le champ où tu veut que soit stocké l'url du fichier téléchargé, dans mon exemple c'est "thumbnails" dans ma Table Topics, par la suite il te suffit d'ajouter "_file" à ton input comme ci-haut pour déclencher le behavior : "nomdechamp_file". Tu peut également redéfinir le path ou il sera enregistré, également la récurrence si "overwrite => true ", il supprimera le fichier lors de la suppression de l'enregistrement en BDD également.

Je tiens à préciser que ce behavior fonctionne parfaitement, comme les autres d'ailleurs. Merci encore à Xeta.

Muxabble, il y a 11 ans

Je te crois, j'en suis même sur, le soucis c'est qu'il ne m'enregistre rien en BDD ! ni rien le path en ajoutant thumbnail_file ...

JC_Pires, il y a 11 ans

Est-ce que le fichier s'enregistre quand meme dans ton dossier webroot?

Muxabble, il y a 11 ans

Non même pas ...

JC_Pires, il y a 11 ans

Donne nous les champs de ta table où tu veut que ça soit enregistré stp.

Muxabble, il y a 11 ans

Ba thumbnail => varchar 255

JC_Pires, il y a 11 ans

Fais un composer dumpautoload, j'ai l'impression que la Classe n'est pas chargée.

Sinon donne nous le formulaire, ainsi que ton model stp

Muxabble, il y a 11 ans

Alors j'ai passé thumbnail en Null Yes dans ma bdd, et j'ai tester avec et sans la validation, il n'update pas dans la bdd, et il n'upload toujours pas !
J'ai testé à l'ajout, il considère thumbnail_file comme vide !

JC_Pires, il y a 11 ans

Envoi tout ton formulaire stp

Muxabble, il y a 11 ans

Je n'avais pas fais le composer dumpautoload ! Mais toujours rien ...

Je prend la vue edit.ctp

<?= $this->Form->input('thumbnail_file', ['type' => 'file']) ?> <?php namespace App\Model\Table; use App\Model\Entity\Post; use Cake\ORM\Query; use Cake\ORM\RulesChecker; use Cake\ORM\Table; use Cake\Validation\Validator; /** * Posts Model */ class PostsTable extends Table { /** * Initialize method * * @param array $config The configuration for the Table. * @return void */ public function initialize(array $config) { $this->table('posts'); $this->displayField('name'); $this->primaryKey('id'); $this->addBehavior('Timestamp'); $this->addBehavior('Sluggable'); $this->addBehavior('Xety/Cake3Upload.Upload', [ 'fields' => [ 'thumbnail' => [ 'path' => '/img/articles/:y/:m/:md5', 'overwrite' => true, ] ] ] ); $this->addBehavior('CounterCache', ['Categories' => ['post_count']]); $this->belongsTo('Users', [ 'foreignKey' => 'user_id', 'joinType' => 'INNER' ]); $this->belongsTo('Categories', [ 'foreignKey' => 'category_id', 'joinType' => 'INNER' ]); } /** * Default validation rules. * * @param \Cake\Validation\Validator $validator Validator instance. * @return \Cake\Validation\Validator */ public function validationDefault(Validator $validator) { $validator ->add('id', 'valid', ['rule' => 'numeric']) ->allowEmpty('id', 'create') ->requirePresence('name', 'create') ->notEmpty('name') ->requirePresence('excerpt', 'create') ->notEmpty('excerpt') ->requirePresence('content', 'create') ->notEmpty('content') ->add('published', 'valid', ['rule' => 'boolean']) ->requirePresence('published', 'create') ->notEmpty('published'); return $validator; } /** * Returns a rules checker object that will be used for validating * application integrity. * * @param \Cake\ORM\RulesChecker $rules The rules object to be modified. * @return \Cake\ORM\RulesChecker */ public function buildRules(RulesChecker $rules) { $rules->add($rules->existsIn(['user_id'], 'Users')); $rules->add($rules->existsIn(['category_id'], 'Categories')); return $rules; } }
Assassins, il y a 11 ans

Si tu as créé une Entity pour ta table et que tu as un protected $_accessible il faut ajouter 'thumbnail_file'=>true sinon il ignore tous simplement le champ thumbnail_file du coup il enregistre ni le fichier et ni le chemin vers l'image dans la base de données.

Je viens d'avoir un problème équivalent au tiens quand j'ai installe le plugin et cela à régler le problème.

Muxabble, il y a 11 ans

@Assassins, pas bête après rélfexion voir même logique, mais le model du behavior devrait s'en occuper, mais même avec sa, il ne veut toujours pas ...

JC_Pires, il y a 11 ans

L'enregistrement de l'entité ce fais?

Muxabble, il y a 11 ans

Non rien dans la base de donnée, rien dans img/upload

// PostsController.php public function edit($id = null) { $post = $this->Posts->get($id, [ 'contain' => [] ]); if ($this->request->is(['patch', 'post', 'put'])) { $post = $this->Posts->patchEntity($post, $this->request->data); if ($this->Posts->save($post)) { $this->Flash->success("L'article à bien été sauvegardé."); return $this->redirect(['action' => 'index']); } else { $this->Flash->error("L'article n'as pas pu être sauvegardé. Merci d'essayer de nouveau."); } } $users = $this->Posts->Users->find('list', ['limit' => 200]); $categories = $this->Posts->Categories->find('list', ['limit' => 200]); $this->set(compact('post', 'users', 'categories')); $this->set('_serialize', ['post']); }
JC_Pires, il y a 11 ans

Donc le problème viens de là. Après avoir fais patchEntity, debug ta variable $post et regarde si tout les champ requis pour la validation sont bien présent dans l'objet, sinon redéfinis les $post->tonchamp = ...

Si thumbnail est pas autorisé à être null en bdd ça pourrais déclencher une erreur aussi. Mais je doute que ça soit le cas ?!

Tu as un problème au if($this->Posts->save($post)){} soit tu rentres pas dans la condition if ($this->request->is(['patch', 'post', 'put'])) ce qui m'étonnerais fortement, sinon c'est des champ qui ne sont pas définis après le patchEntity ou la requête get() qui ne trouve aucun enregistrement mais j'en doute encore plus.

Muxabble, il y a 11 ans

Okey ! J'ai réussi pour l'enregistrement en BDD mais il ne l'upload pas ...

$post->thumbnail = $post->thumbnail_file;

JC_Pires, il y a 11 ans

Ok bon premier pas, tu n'as pas a faire ça:

$post->thumbnail = $post->thumbnail_file;

C'est le behavior qui va s'en charger.

Dans ton create() tu lui a bien indiqué qu'il faut qu'il ajoute "enctype="multipart/form-data" en faisant:

Pour l'edition:

<?= $this->Form->create($topic, ['type' => 'file']);?>

Pour un ajout:

<?= $this->Form->create('Topics', ['type' => 'file']);?>
JC_Pires, il y a 11 ans

Ah je n'avais pas retesté avec ma version à jour de cake 3, et j'ai le même problème ... Je l'avais testé avec une dev preview 2 semaines avant la 3.0

JC_Pires, il y a 11 ans

Ok j'ai trouvé le problème, il ne viens pas de nous mais du behavior, je suis entrain d'effectuer les modifs, je te redis et j'en parle a Xeta

Muxabble, il y a 11 ans

Okey pas de soucis x) Je vais y jette un coup d'oeil !

Muxabble, il y a 11 ans

Arf, les formulaires d'upload ne sont pas comme d'hab c'est vrai, j'avais complétement zappé ! Donc du coup j'ai enlevé le $post->thumbnail = $post->thumbnail_file; mais ducoup plus d'enregistrement en bdd et pas d'upload non plus

JC_Pires, il y a 11 ans

Ca veut dire que ton champ n'autorise pas à être null dans ta base de données et ou que tu as un problème de validation des données. Commente la partie validation de ton model et test. Vérifie bien le null autorisé dans ta base de données pour le champ thumbnail au passage.

JC_Pires, il y a 11 ans

Okay c'est que depuis la 3.0 il faut mettre un _initialize dans les behaviors donc va dans ton dossier

vendor\xety\cake3-upload\src\Model\Behavior\UploadBehavior.php

Et avant la fonction beforeSave()

met ça:

public function initialize(array $config) { $this->_config = array_merge ($this->_defaultConfig , $config); }

Après dans ton formulaire:

<?= $this->Form->create('Topics', ['type' => 'file']);?> ... <?= $this->Form->input('thumbnails_file', ['type' => 'file','class' => 'form-control']) ?> <?= $this->Form->button('Creer', ['type' => 'submit', 'class' => 'btn btn-primary']);?> <?= $this->Form->end();?>

dans ton controller juste avant ton save:

$topic->thumbnails_file = $this->request->data['thumbnails_file'];

Chez moi ça marche niquel, il manquais la fonction d'initialize au behavior, en espérant que ça marche chez toi, je soumettrais ma modif a Xeta sur github

JC_Pires, il y a 11 ans

Dans ton model

$this->addBehavior('Xety/Cake3Upload.Upload', [ 'fields' => [ 'thumbnails' => [ 'path' => '/img/articles/:y/:m/:md5', 'overwrite' => true, ] ] ] );
Muxabble, il y a 11 ans

Merci pour cette contribution, en effet c'était le behavior, maintenant tout rentre dans l'ordre, un p'tit bémol en bdd il enregistre /img/:file/:y/:y/:md5, le truc c'est que pour récuperer l'image avec le Helper Html, le helper génère

<img ... /img/img/articles/2015/04/ghji8.jpg>
Xeta, il y a 11 ans

Chez moi le behavior fontionne très bien sans modification, et ce même avec la version 3.0.1.

Muxabble, il y a 11 ans

C'est ce que j'ai fais, mais du coup il me l'enregistre dans le dossier webroot et non plus dans img ...

JC_Pires, il y a 11 ans

essai ça "Pas testé"

$this->addBehavior('Xety/Cake3Upload.Upload', [ 'fields' => [ 'thumbnails' => [ 'path' => 'articles/:y/:m/:md5', 'overwrite' => true, ] ], 'root' => IMAGES // le root de base sera plus webroot mais le dossier image ] );
JC_Pires, il y a 11 ans

Oui Xeta à raison, désolé mais effectivement même sans la function initialize() le Behavior fonctionne. Je trouvais bizarre justement que ça vienne du Behavior, mais il ne restais plus beaucoup de solution, et depuis que je l'avais testé des choses avais changée dans le framework.

La seule chose que je dois faire c'est dans mon controller avant mon save c'est:

$topic->thumbnails_file = $this->request->data['thumbnails_file'];

Chose que je n'étais pas obligé de faire avant.

Désolé d'avoir douté @Xeta.

En ce qui concerne ton problème @dubleYu concernant le chemin enregistré en base de données, tu as juste a changer le chemin dans ton addBehavior, tout simplement:

$this->addBehavior('Xety/Cake3Upload.Upload', [ 'fields' => [ 'thumbnails' => [ 'path' => 'articles/:y/:m/:md5', // enleve le /img 'overwrite' => true, ] ] ] );
Muxabble, il y a 11 ans

J'ai trouvé une alternative

'path' => 'img/upload/articles/:y/:m/:md5',
JC_Pires, il y a 11 ans

Voilà dsl la constante IMAGES n'existe plus dans cake3

$this->addBehavior('Xety/Cake3Upload.Upload', [ 'fields' => [ 'thumbnails' => [ 'path' => 'articles/:y/:m/:md5', 'overwrite' => true, ] ], 'root' => WWW_ROOT. DS . 'img'.DS ] );
Muxabble, il y a 11 ans

Merci pour l'info x)

JC_Pires, il y a 11 ans

Ca veut pas. Il ne passe pas dans le tableau $data dans le behavior, il coupe l'évènement ici :

if (!isset($data[$virtualField]) || !is_array($data[$virtualField])) {

Muxabble, il y a 11 ans

Je vais check tout sa merci x)

JC_Pires, il y a 11 ans

J'ai essayé avec les modifications des validations, sans validation. Avec accessible/sans mais le seul moyen pour que ça fonctionne c'est:

$topic->thumbnails_file = $this->request->data['thumbnails_file'];

Alors j'aimerais vraiment comprendre pq ça ne veut pas, et je précise qu'avant la 3.0.0 ou la 3.0.1 je n'avais pas ce problème tout fonctionnais normalement.

//Mon controller TopicsController public function add() { $topic = $this->Topics->newEntity($this->request->data); if ($this->request->is('post')) { $topic->accessible('thumbnails_file', true); $article->user_id = $this->Auth->user('id'); $topic->thumbnails_file = $this->request->data['thumbnails']; if ($this->Topics->save($topic)) { ... } } //Ma vue: <?= $this->Form->create($topic, ['type' => 'file']);?> <?= $this->Form->input('thumbnails', ['type' => 'file','class' => 'form-control']) ?> <?= $this->Form->button('Creer', ['type' => 'submit', 'class' => 'btn btn-primary']);?> <?= $this->Form->end();?> // Mon model <?php namespace App\Model\Table; use App\Model\Entity\Topic; use Cake\ORM\Query; use Cake\ORM\RulesChecker; use Cake\ORM\Table; use Cake\Validation\Validator; /** * Topics Model */ class TopicsTable extends Table { /** * Initialize method * * @param array $config The configuration for the Table. * @return void */ public function initialize(array $config) { $this->table('topics'); $this->displayField('title'); $this->primaryKey('id'); $this->addBehavior('Timestamp'); $this->addBehavior('CounterCache', ['Forums' => ['topic_count'], 'Users'=> ['topic_count']]); $this->addBehavior('Xety/Cake3Sluggable.Sluggable'); $this->addBehavior('Xety/Cake3Upload.Upload', [ 'fields' => [ 'thumbnails' => [ 'path' => 'articles/:y/:m/:md5', 'overwrite' => true, ] ], 'root' => WWW_ROOT. DS . 'img'.DS ] ); $this->belongsTo('ParentForums', [ 'className' => 'Forums', 'foreignKey' => 'forum_id' ]); $this->belongsTo('Forums', [ 'foreignKey' => 'forum_id' ]); $this->belongsTo('Users', [ 'foreignKey' => 'user_id' ]); $this->belongsTo('LastUser', [ 'className' => 'Users', 'foreignKey' => 'lastuser' ]); $this->belongsTo('Groups', [ 'foreignKey' => 'group_id' ]); $this->hasMany('Posts', [ 'foreignKey' => 'topic_id' ]); $this->hasMany('TopicsUsersTrackers', [ 'foreignKey' => 'topic_id' ]); $this->hasMany('RatingsUsers', [ 'className' => 'RatingsUsers', 'foreignKey' => 'refid', 'conditions' => ['ref' => 'topic'] ]); } public function findShort(Query $query) { return $query ->select([ 'id', 'title', 'slug', 'ParentForums.slug' ]) ->contain( [ 'ParentForums' => function ($q){ return $q ->find('short'); } ] ); } public function findListe(Query $query, $options) { return $query ->contain( [ 'Users' => function ($q){ return $q ->find('short'); }, 'LastUser' => function ($q){ return $q ->find('short'); }, 'TopicsUsersTrackers' ] ) ->order(['Topics.modified' => 'DESC']); } /** * Default validation rules. * * @param \Cake\Validation\Validator $validator Validator instance. * @return \Cake\Validation\Validator */ public function validationDefault(Validator $validator) { $validator ->add('id', 'valid', ['rule' => 'numeric']) ->allowEmpty('id', 'create') ->add('is_article', 'valid', ['rule' => 'boolean']) ->requirePresence('is_article', 'create') ->notEmpty('is_article') ->add('is_pinned', 'valid', ['rule' => 'boolean']) ->requirePresence('is_pinned', 'create') ->notEmpty('is_pinned') ->add('is_private', 'valid', ['rule' => 'boolean']) ->requirePresence('is_private', 'create') ->notEmpty('is_private') ->requirePresence('title', 'create') ->notEmpty('title') ->requirePresence('content', 'create') ->notEmpty('content') ->add('commentable', 'valid', ['rule' => 'boolean']) ->requirePresence('commentable', 'create') ->notEmpty('commentable') // Ajout de tes règles ->allowEmpty('thumbnails_file') ->add('thumbnails_file', [ 'mimeType' => [ 'rule' => ['mimeType', ['image/jpeg', 'image/png']], 'message' => __("The mimeType is not allowed."), 'on' => function ($context) { return !empty($context['data']['thumbnails_file']['name']); } ], 'fileExtension' => [ 'rule' => ['extension', ['jpg', 'jpeg', 'png']], 'message' => __("The extensions allowed are {0}.", '.jpg, .jpeg and .png'), 'on' => function ($context) { return !empty($context['data']['thumbnails_file']['name']); } ], 'fileSize' => [ 'rule' => ['fileSize', '<', '500KB'], 'message' => __("The file exceeded the max allowed size of {0}", '500KB'), 'on' => function ($context) { return !empty($context['data']['thumbnails_file']['name']); } ], ]); return $validator; } /** * Returns a rules checker object that will be used for validating * application integrity. * * @param \Cake\ORM\RulesChecker $rules The rules object to be modified. * @return \Cake\ORM\RulesChecker */ public function buildRules(RulesChecker $rules) { $rules->add($rules->existsIn(['forum_id'], 'Forums')); $rules->add($rules->existsIn(['user_id'], 'Users')); $rules->add($rules->existsIn(['group_id'], 'Groups')); return $rules; } }

Si tu vois quelque chose Xeta, car là je pêche ...

Xeta, il y a 11 ans

Remplace :

<?= $this->Form->input('thumbnails', ['type' => 'file','class' => 'form-control']) ?>

par

<?= $this->Form->input('thumbnails_file', ['type' => 'file','class' => 'form-control']) ?>

C'est marqué dans la doc du plugin : https://github.com/Xety/Cake3-Upload#identifiers

JC_Pires, il y a 11 ans

Oui oui excuse moi, j'ai juste changé avant pour un test mais c'est bien:

<?= $this->Form->input('thumbnails_file', ['type' => 'file']) ?>