Après quelques jours sans nouvelle, me revoilà avec un nouveau tutoriel.
Dans le cours précédent, nous avons mis en place l'accès aux données.
Nous allons voir aujourd'hui comment mettre en place un contrôler et une vues.
Nous sommes enfin prêt à travailler sur les différents scénarios que nous avons présenté lors du jour 2:
- En tant qu'utilisateur, j'accède à la page d'accueil du site
- En tant qu'utilisateur, j'accède à la page d'une catégorie
- En tant qu'utilisateur, je clique sur un emploi pour voir sa fiche détaillée
Au programme du jour (pas forcément dans cet ordre):
- L'architecture MVC
- Mise en place du Layout de l'application
- Création de la page d'accueil du site Jobeet
- Suppression du module Application
L'architecture MVC
Avant l’émergence des frameworks PHP, nous avions l'habitude de créer un fichier PHP par page: configurations diverses, récupération des données, traitements eventuelles de celles-ci puis affichage du code HTML. On se retrouvait donc avec du HTML mélangé avec du PHP, et plusieurs fichiers plus ou moins bien organisés
Puis les moteurs de template sont apparus: séparation de la logique et de la présentation. mais avec un effet pervers: beaucoup de code à maintenir, un "langage" de template à apprendre.
Aujourd'hui la plupart des solutions que nous utilisons sont basées sur l'architecture MVC (Modèle-Vue-Contrôleur). Pour résumer, l'architecture MVC permet de mettre en place une organisation de notre code via une séparation en 3 couches.
La couche Modèle
C'est elle qui contient la logique de nos données (les accès à la base de données se trouvent dans cette couche). Dans Zend Framework 2, les modèles se trouvent dans module/[nom-du-module]/src/[namespace]/Model
La couche Vue
C'est la partie présentation (ce que l'on voit sur le site). Dans ZF2, les vues sont situées dans module/[nom-du-module]/View
La couche Contrôleur
C'est cette couche qui récupère les données et les passe à la Vue pour le rendu.
Le Layout de l'application
Qu'est-ce que le layout ?
Il s'agit d'une vue particulière, qui englobe les autres vues de contenu de l'application.
La version 1.x du framework séparait la notion de layout et de vue. Ce n'est plus le cas avec la version 2. Zend Framework 2 propose une hiérarchie de vue, afin de déterminer la vue qui servira de layout. De plus, il est maintenant possible d'imbriquer une vue dans une vue.
Notre layout contiendra:
- un entête (titre du site + logo)
- un corps (qui contiendra les vues associées a nos controlleurs/actions)
- un pied de page (avec différents liens)
Voici le code de notre layout:
// module/Front/view/layout/layout.phtml <?php echo $this->doctype(); ?> <html lang="en"> <head> <meta charset="utf-8"> <?php echo $this->headLink(array('rel' => 'shortcut icon', 'type' => 'image/vnd.microsoft.icon', 'href' => $this->basePath() . '/favicon.ico')) ->prependStylesheet($this->basePath() . '/css/main.css'); ?> <title>ZF2 - Jobeet</title> </head> <body> <div id="container"> <div id="header"> <div class="content"> <h1> <a href="#"> <img src="/images/logo.jpg" alt="Jobeet Job Board" /> </a> </h1> <div id="sub_header"> <div class="post"> <h2>Ask for people</h2> <div> <a href="#">Post a Job</a> </div> </div> <div class="search"> <h2>Ask for a job</h2> <form action="#" method="get"> <input type="text" name="keywords" id="search_keywords" /> <input type="submit" value="search" /> <div class="help">Enter some keywords (city, country, position, ...)</div> </form> </div> </div> </div> </div> <div id="content"> <div class="content"> <?php echo $this->content; ?> </div> </div> <div id="footer"> <div class="content"> <span class="symfony"> <img src="/images/jobeet-mini.png" alt="logo jobeet" /> powered by <a href=""><img src="/images/zf2-logo.png" alt="Zend Framework 2" /></a> </span> <ul> <li><a href="">About Jobeet</a></li> <li class="feed"><a href="">Full feed</a></li> <li><a href="">Jobeet API</a></li> <li class="last"><a href="">Affiliates</a></li> </ul> </div> </div> </div> </body> </html>
En regardant le code de plus près, vous aurez remarqué un peu de code PHP, que je vais vous expliqué brièvement ici:
echo $this->doctype();
Il s'agit d'une aide de vue: il s'agit d'une classe d'aide permettant d'effectuer des actions répétitives (formatter une date, générer des liens, ...) ou complexe. L'aide de vue Doctype affiche automatiquement le doctype.
echo $this->headLink(...)->prependStylesheet($this->basePath() . '/css/main.css');
Cette aide de vue permet ajouter une feuille de style.
Zend Framework 2 (comme le 1) possède un grand nombre d'aide de vue, que je vous invite à consulter ici. Nous seront amener à en utiliser d'autre ultérieurement.
Les feuilles de style et les images
Ce tutoriel concernant Zend Framework 2, et non le web design, nous utiliserons les feuilles de style et les images du tutoriel Jobeet de Symfony pour donner un look à notre site. Décompresser cette archive dans le répertoire public de notre application (vous aurez donc un répertoire css, un répertoire images et un favicon dans ce répertoire public)
Création de la page d'accueil
Le layout et le design étant en place, nous allons enfin attaquer notre première page: la page d'accueil.
Créons maintenant un Contrôleur Index (dans module/Front/src/Front/Controller/):
namespace Front\Controller; use Zend\Mvc\Controller\AbstractActionController; use Zend\View\Model\ViewModel; use Front\Model\JobTable; class IndexController extends AbstractActionController { protected $jobTable; protected $categoryTable; public function getJobTable() { if (!$this->jobTable) { $sm = $this->getServiceLocator(); $this->jobTable = $sm->get('Front\Model\JobTable'); } return $this->jobTable; } public function getCategoryTable() { if (!$this->categoryTable) { $sm = $this->getServiceLocator(); $this->categoryTable = $sm->get('Front\Model\CategoryTable'); } return $this->categoryTable; } // Action index qui sera appelé par défaut public function indexAction() { $categories = $this->getCategoryTable()->fetchAll(); $results = array(); foreach ($categories as $category) { $jobs = $this->getJobTable()->fetchAllByIdCategory($category->idCategory); $results[$category->name] = $jobs; } return new ViewModel( array( 'categories' => $results, ) ); } }
Quelques explications sont nécessaires pour bien comprendre ce que vous venez de voir.
Dans Zend Framework 2, le contrôleur est une classe nommé par convention {Nom}Controler et doit commencer par une majuscule (IndexControler, CategoryControler, ...).
Notre contrôleur contient une action IndexAction (toutes les méthode doivent respecter la même convention de nommage {Nom}Action , doivent commencer par une majuscule et sont obligatoirement publique).
Les contrôleurs doivent implémenter l'interface Zend\Stdlib\Dispatchable. Pour cela, Zend Framework met à notre disposition deux classe abstraites:
- Zend\Mvc\Controller\AbstractActionController: il s'agit du contrôleur standard
- Zend\Mvc\Controller\AbstractRestfulController: pourra être utilisé pour écrire un WebService RESTful
Ce nouveau contrôleur doit être déclaré dans config/module.config.php de notre module Front.
return array( [...] 'controllers' => array( 'invokables' => array( 'Front\Controller\Index' => 'Front\Controller\IndexController', 'Front\Controller\Category' => 'Front\Controller\CategoryController', 'Front\Controller\Job' => 'Front\Controller\JobController', ), ), [...] );
Créons ensuite la vue index.phtml associée à l'action index de notre contrôleur Index dans (module/Front/view/front/index):
<?php $this->headLink()->appendStylesheet('/css/jobs.css'); ?> <div id="job_history">Recent viewed jobs:</div> <?php foreach ($this->categories as $category => $jobs): ?> <h1><?php echo $category; ?></h1> <table class="jobs"> <tbody> <?php foreach($jobs as $job): ?> <tr class="<?php echo $this->cycle(array("even", "odd"))->next();?>"> <td><?php echo $this->escapeHtml($job->location); ?></td> <td> <a href=""> <?php echo $this->escapeHtml($job->position); ?> </a> </td> <td><?php echo $this->escapeHtml($job->company); ?></td> </tr> <?php endforeach;?> </tbody> </table> <?php endforeach;?>
Cette vue sera insérée dans notre layout. Vous pouvez voir l'utilisation de 2 aides de vue: appendStyleSheet() pour ajouter une nouvelle feuille de style et cycle() pour alterner une série de valeur (utilisé ici pour gérer deux classes CSS différentes, pour gérer l'alternance de couleur des lignes du tableau).
Suppression du module Application
Nous avons créé le premier contrôler de notre module Front.
Le squelette que nous avons utilisé contenait un module Application qui ne nous est pas utile.
Nous allons donc récupérer quelques bouts de code en les copiant dans le répertoire de notre module Front.
Copiez d'abord le répertoire error (dans view) du module Application pour le coller dans notre module Front (dans le répertoire view).
Nous allons aussi modifier notre fichier Module.php pour y ajouter ça:
use Zend\Mvc\MvcEvent; use Front\Model\CategoryTable; use Front\Model\JobTable; use Front\Model\UserTable; use Zend\ModuleManager\ModuleManager; // Ajoutez cette ligne use Zend\Mvc\ModuleRouteListener; // Et celle-là class Module { // Ajoutez cette méthode public function onBootstrap(MvcEvent $e) { $e->getApplication()->getServiceManager()->get('translator'); $eventManager = $e->getApplication()->getEventManager(); $moduleRouteListener = new ModuleRouteListener(); $moduleRouteListener->attach($eventManager); } [...] }
Cette méthode permettra de gérer les traductions de l'application (que nous aborderons plus tard). Nous l'ajoutons maintenant car les vues error que nous venons de copier en ont besoin (si vous ouvrez une des vues error, vous verrez $this->translate(...) qui permet de traduire une chaine de caractères.
Nous devons aussi ajouter une route pour que notre module soit chargé par défaut. Nous verrons les route dans le jour 5. Modifiez juste le fichier /config/module.config.php de notre module:
return array( // La route dont nous avons besoin 'router' => array( 'routes' => array( 'home' => array( 'type' => 'Zend\Mvc\Router\Http\Literal', 'options' => array( 'route' => '/', 'defaults' => array( '__NAMESPACE__' => 'Front\Controller', 'controller' => 'Index', 'action' => 'index', ), ), ), ), ), // Translator, qui permettra plus tard de gérer les traduction de notre application (plus tard) 'service_manager' => array( 'factories' => array( 'translator' => 'Zend\I18n\Translator\TranslatorServiceFactory', ), ), 'translator' => array( 'locale' => 'en_US', 'translation_file_patterns' => array( array( 'type' => 'gettext', 'base_dir' => __DIR__ . '/../language', 'pattern' => '%s.mo', ), ), ), // Nos contrôleurs 'controllers' => array( 'invokables' => array( 'Front\Controller\Index' => 'Front\Controller\IndexController', 'Front\Controller\Category' => 'Front\Controller\CategoryController', 'Front\Controller\Job' => 'Front\Controller\JobController', ), ), // Quelques paramètres pour notre application 'view_manager' => array( 'display_not_found_reason' => true, 'display_exceptions' => true, 'doctype' => 'HTML5', // On défini notre doctype 'not_found_template' => 'error/404', // On indique la page 404 'exception_template' => 'error/index', // On indique la page en cas d'exception 'template_map' => array( 'layout/layout' => __DIR__ . '/../view/layout/layout.phtml', ), 'template_path_stack' => array( __DIR__ . '/../view', ), ), );
Vous pouvez maintenant effacer le répertoire du module Application.
Si tout va bien, et que je n'ai rien oublié (ce qui serait possible, car j'écrit ces cours presque en même temps que j'avance le code de Jobeet et que je découvre Zend), vous devriez pouvoir accéder à votre page d'accueil (allez insérer quelques données, telles que 2 ou 3 catégories et 2-3 emplois, dans la base MySQL) :
Si cela ne fonctionne pas chez vous, téléchargez le code source du jour 4 sur mon compte Github et comparez avec ce que vous avez (ou remplacez).
C'est fini pour ce jour 4.
N'hésitez pas à me laissez des commentaires si vous avez des questions ou si vous avez des remarques !
Les recommandations de ZF ont changées entre ZF1 et ZF2 ? Car je vois de variables en protected ne commençant pas par _.
RépondreSupprimerAttention, le schéma pour énoncé le MVC est faux, attention aux liaisons.
L'imbrication des vues existait dans ZF1.
Tu n'as pas rencontré de problème pour le moment avec la traduction ? Tu optes pour du gettext ? Car tu vas voir au niveau de la détection par le navigateur c'est bien moins intuitif.
L'utilisation du underscore dans des attributs protected ou private n'est pas obligatoire: "For variables that are declared with private or protected visibility, the first character of the variable name MAY be a single underscore." => le MAY est important
RépondreSupprimerTu peux aller voir les codings standards pour ZF2 ici: http://framework.zend.com/wiki/display/ZFDEV2/Coding+Standards
Pour les traductions, je ne passerais pas par la détection du navigateur, mais par un choix de l'utilisateur (flag, selectbox).
La raison pour ne pas mettre de underscore: "This is the only acceptable application of an underscore in a variable name, and is discouraged (as it makes refactoring to public visibility more difficult)."
SupprimerMerci pour le lien (c'est justement pour ça que je posais la question). Je continuerai donc d'utiliser le _ car j'aime bien savoir si telle ou telle variable est public directement.
RépondreSupprimerPour la traduction tu fais bien, car la détection du navigateur ne semble pas tout à fait au point encore.
Sinon tu as essayé de créer ta propre librairie ? (attention je parle pas de module) car j'ai pas trouvé ça très intuitif.
Pour la création d'une librairie (pour l'instant, je n'en ai pas fait pour Jobeet), mais créer une lib est presque identique à la création d'un module (la structure est très proche) => l'essentiel étant de bien comprendre le fichier Module.php (et du fichier autoload_classmap.php)
SupprimerLoïc tu es obsolète pour le coup ;) les underscore c'était utile en php4 quand il n'y avait pas les private et protected sur les attributs de classe. Maintenant ce n'est plus du tout utilisé et absolument pas considéré comme une bonne pratique.
RépondreSupprimerCyprien tu fais erreur, cela est frequemment utilisé en PHP5. Cela n'est plus obligatoire dans ZF mais cela ne le rend pas pour autant deprecated. Quand tu bosses dans une classe contenant pas mal de méthodes, tu sais rapidement si ta variable est public ou non. Prouve moi que cela n'est pas une mauvaise pratique et en suite nous verrons ;).
RépondreSupprimerRomain, c'est justement pour ça que j'ai bien précisé "pas comme les modules", car il est possible de créer une librairie permettant la surcharge de méthode ZF, tout à fait différent de la notion de module.
Cyprien, tu devrais regarder comment sont utilisés les annotations sur SF, j'espère qu'il est possible de les désactiver ;).
De manière générale je suis contre ces pratiques qui consistent à contourner les "limitations" d'un langage avec des conventions de code ou de commentaire. Et les underscore sont exactement ça à la base : un moyen visuel de s'empêcher d'utiliser des propriétés que l'on considère comme internes à la classe (puisque php4 ne permettait pas de protéger ces propriétés au niveau du code). Maintenant si tu l'utilises et trouves ça pratique libre à toi, moi je dis juste que ce n'est pas une bonne pratique, d'après moi, et d'après les codings standards de nombreuses librairies php un tant soit peu modernes (donc pas ZF1 :p). D'ailleurs comme le fait remarquer Romain (et ZF2) si tu veux changer la visibilité d'une propriété, ça impose d'en modifier le nom partout où tu l'as utilisée.
RépondreSupprimerEt si tu veux troller sur Symfony, tu peux choisir ton format de configuration en annotation, yml, xml, ...(waaa un framework flexible et découplé !)
;)
Pour info: La norme PSR-2 indique (point 4.2) que l'underscore ne devrait pas être utilisé comme préfixe du nom de la propriété pour indiquer sa visibilité private ou protected :-)
RépondreSupprimerProperty names SHOULD NOT be prefixed with a single underscore to indicate protected or private visibility.
Evidemment, ce standard suivi par ZF2
Supprimer@Cyprien: D'un coté, il y a les "préconisations" et de l'autre les préférences personnelles :-)
RépondreSupprimer@Loïc: Avec un bon IDE, si tu commente bien tes classes, tes propriétés, etc, avec des commentaire style PHPDoc, tu peux voir rapidement la visibilité :-)
Après c'est une question de goût et d'habitude. Il y a bien des personnes qui developpent en PHP en suivant la notation hongroise...C'est aussi un choix personnel :-)
@Romain, oui tout à fait d'accord pour l'IDE mais je parlais de façon générale.
RépondreSupprimer@Cyprien, si nous t'coutons, les conventions de nommages serait totalement obsolète.
Je rappelle quand même quelque chose qui va outre les convetions de tel ou tel framework, ce qui est important comme le signale Romain au niveau de certaines conventions, c'es de garder les même convetions et quelles soient connus.
(Il ne faut pas être borné, sinon le jour où tu arrives dans une nouvelle boite tu vas pas dire les convetions ce n'est pas bon, ce qui compte c'est que tous les développeurs de la boite utilisent les même convetions et que celles ci soient explicite.
La plupart des frameworks de nos jours sont flexible et heureusement (SF1 n'était pas flexible tout l'opposé de ZF ^^). Je sais bien qu'il est possible de faire en yaml ou xml. D'ailleurs c'est exactement ce qui est fait sous ZF2 mais pas les même formats.
Ce que je veux dire, c'est que c'est bien de prévoir des annotations dans les fichiers PHP mais quand tu vois comment c'est géré, ça fait peur tout de même.
Il ne faut pas vouloir faire ce que Java fait obligatoirement, car les annotations en Java sont traitées lors de la compilation.
Du coup je réitère ma question, est il possible de désactivés le système d'annotations de SF2, car ne pas utiliser les annotations n'empêche pas le mécanisme d'être présent et de vérifier si des annotations sont présentes ou non.
Et je ne suis pas la pour critiquer SF2, bien au contraire, je vais faire des deux conjointement car ils sont tout de même des références, même si je trouve que ZF2 n'est pas complètement fini pour le moment.
Bonjour Romain,
RépondreSupprimerEst ce que le projet Jobeet sur ZF2 est toujours d'actualité. Si je ne me trompe pas je n'ai pas vu de nouvelles publications depuis cet article. Attention, ce n'est absolument pas un reproche ni une critique. Je souhaiterai juste savoir si les autres articles sont prévus dans ton planning.
Merci de tes retours.
Cordialement,
Fred
Bonjour Frédéric,
SupprimerEffectivement, il y a eu un petit temps d'arrêt. Depuis un mois, je n'ai pas eu beaucoup de temps libre pour moi.
Je pense reprendre la suite de ce tuto prochainement:certainement un nouvel article en début (ou milieu) de semaine prochaine.
En tout cas, ça fait plaisir de voir que des personnes sont intéressés pour lire la suite :-)
Cordialement,
Romain
Avec impatience je dirai même :)
SupprimerCourage !!
Bon, encore pas mal occupé cette semaine...
SupprimerJe vais essayer de finir ce weekend (j'ai un petit soucis avec les tests unitaires et l'injection de dépendance dans les controleurs).
Merci pour le soutien :-)
Dans la méthode de 'IndexController::indexAction', tu utilises 'JobTable::fetchAllByIdCategory' qui n'existe pas. Il faut donc ajouter dans module/Front/src/Front/Model/Jobtable:
RépondreSupprimerpublic function fetchAllByIdCategory($id_category) {
$resultSet = $this->select(array('id_category'=>$id_category));
return $resultSet;
}
Coucou Romain !
RépondreSupprimerJ'ai un problème avec ce jour 4, et voici le message d'erreur :
Additional information:
Zend\ServiceManager\Exception\ServiceNotFoundException
File:
D:\eclipse-php\workspace\jobeet\vendor\zendframework\zendframework\library\Zend\ServiceManager\ServiceManager.php:456
Message:
Zend\ServiceManager\ServiceManager::get was unable to fetch or create an instance for Zend\Db\Adapter\Adapter
Même en comparant avec l'ariche que tu a mis à disposition, je ne trouve pas d'où vient le problème. Saurais-tu d'où cela vient ?
Merci d'avance
l'ariche = l'archive :/
SupprimerSalut Biloute,
SupprimerTu n'as pas eu de soucis avec les tutos précédents ?
A priori, ton message d'erreur indiquerait un pb de création de l'adapter pour la base de données.
Regarde dans le fichier /config/autoload/database.local.php (il te faudra certainement changer le nom de la base, login ou password en fonction de ce que tu as reellement dans MySQL).
une question qui me revient souvent depuis la version 1 de Zend.
RépondreSupprimerj'ai souvent ces erreurs dans view
"NetworkError: 404 Not Found - http://localhost/images/logo.jpg"
"NetworkError: 404 Not Found - http://localhost/images/zf2-logo.png"
"NetworkError: 404 Not Found - http://localhost/images/jobeet-mini.png"
"NetworkError: 404 Not Found - http://localhost/public/images/jobeet-mini.png"
Est t'il nécessaire de faire un $this->baseUrl() (ou $this->basePath() dans Zend 2) dans tous les liens des view? ou bien il y'a une configuration à faire, et c'est pour cette raison que tu l'as pas ajouté dans l'application jobeet que tu as partagé?!
Zend\ServiceManager\ServiceManager::get was unable to fetch or create an instance for Zend\Db\Adapter\Adapter
RépondreSupprimercomment je fais avec ce type d'erreur
Bonjour
RépondreSupprimeril faut ajouter le fichier /config/autoload/database.local.php
$dbParams = array(
'database' => 'jobeet',
'username' => 'jobeet',
'password' => 'jobeet',
'hostname' => 'localhost'
);
return array(
'service_manager' => array(
'factories' => array(
'Zend\Db\Adapter\Adapter' => function ($sm) use ($dbParams) {
$adapter = new BjyProfiler\Db\Adapter\ProfilingAdapter(
array(
'driver' => 'pdo',
'dsn' => 'mysql:dbname='.$dbParams['database'].';host='.$dbParams['hostname'],
'database' => $dbParams['database'],
'username' => $dbParams['username'],
'password' => $dbParams['password'],
'hostname' => $dbParams['hostname'],
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
)
);
$adapter->setProfiler(new BjyProfiler\Db\Profiler\Profiler);
$adapter->injectProfilingStatementPrototype();
return $adapter;
},
),
),
);
Merci Fadel pour la réponse pour Thity14 :-)
SupprimerIl me semblait que le fichier était dispo dans l'archive
;)
Supprimeret ce qu'on peux créer une communauté pour faire avancer les tutos ? mm creer des articles sur ZF2 ?
Fatal error: Uncaught exception 'RuntimeException' with message 'Unable to load ZF2. Run `php composer.phar install` or define a ZF2_PATH environment variable.' in C:\wamp\www\zendJobeet\init_autoloader.php on line 48
RépondreSupprimeret pourtan j'ai suivie le tuto des album et ca marché bien??
An error occurred during execution; please try again later.
RépondreSupprimerAdditional information:
Zend\ServiceManager\Exception\ServiceNotFoundException
File:
C:\wamp\www\zendJobeet\vendor\ZF2\library\Zend\ServiceManager\ServiceManager.php:495
Message:
Zend\ServiceManager\ServiceManager::get was unable to fetch or create an instance for Zend\Db\Adapter\Adapter
Stack trace:
#0 C:\wamp\www\zendJobeet\module\Front\Module.php(46): Zend\ServiceManager\ServiceManager->get('Zend\Db\Adapter...')
#1 [internal function]: Front\{closure}(Object(Zend\ServiceManager\ServiceManager), 'frontmodelcateg...', 'Front\Model\Cat...')
#2 C:\wamp\www\zendJobeet\vendor\ZF2\library\Zend\ServiceManager\ServiceManager.php(852): call_user_func(Object(Closure), Object(Zend\ServiceManager\ServiceManager), 'frontmodelcateg...', 'Front\Model\Cat...')
#3 C:\wamp\www\zendJobeet\vendor\ZF2\library\Zend\ServiceManager\ServiceManager.php(984): Zend\ServiceManager\ServiceManager->createServiceViaCallback(Object(Closure), 'frontmodelcateg...', 'Front\Model\Cat...')
#4 C:\wamp\www\zendJobeet\vendor\ZF2\library\Zend\ServiceManager\ServiceManager.php(597): Zend\ServiceManager\ServiceManager->createFromFactory('frontmodelcateg...', 'Front\Model\Cat...')
#5 C:\wamp\www\zendJobeet\vendor\ZF2\library\Zend\ServiceManager\ServiceManager.php(556): Zend\ServiceManager\ServiceManager->doCreate('Front\Model\Cat...', 'frontmodelcateg...')
#6 C:\wamp\www\zendJobeet\vendor\ZF2\library\Zend\ServiceManager\ServiceManager.php(480): Zend\ServiceManager\ServiceManager->create(Array)
#7 C:\wamp\www\zendJobeet\module\Front\src\Front\Controller\IndexController.php(26): Zend\ServiceManager\ServiceManager->get('Front\Model\Cat...')
#8 C:\wamp\www\zendJobeet\module\Front\src\Front\Controller\IndexController.php(33): Front\Controller\IndexController->getCategoryTable()
#9 C:\wamp\www\zendJobeet\vendor\ZF2\library\Zend\Mvc\Controller\AbstractActionController.php(83): Front\Controller\IndexController->indexAction()
#10 [internal function]: Zend\Mvc\Controller\AbstractActionController->onDispatch(Object(Zend\Mvc\MvcEvent))
#11 C:\wamp\www\zendJobeet\vendor\ZF2\library\Zend\EventManager\EventManager.php(468): call_user_func(Array, Object(Zend\Mvc\MvcEvent))
#12 C:\wamp\www\zendJobeet\vendor\ZF2\library\Zend\EventManager\EventManager.php(207): Zend\EventManager\EventManager->triggerListeners('dispatch', Object(Zend\Mvc\MvcEvent), Object(Closure))
#13 C:\wamp\www\zendJobeet\vendor\ZF2\library\Zend\Mvc\Controller\AbstractController.php(117): Zend\EventManager\EventManager->trigger('dispatch', Object(Zend\Mvc\MvcEvent), Object(Closure))
#14 C:\wamp\www\zendJobeet\vendor\ZF2\library\Zend\Mvc\DispatchListener.php(114): Zend\Mvc\Controller\AbstractController->dispatch(Object(Zend\Http\PhpEnvironment\Request), Object(Zend\Http\PhpEnvironment\Response))
#15 [internal function]: Zend\Mvc\DispatchListener->onDispatch(Object(Zend\Mvc\MvcEvent))
#16 C:\wamp\www\zendJobeet\vendor\ZF2\library\Zend\EventManager\EventManager.php(468): call_user_func(Array, Object(Zend\Mvc\MvcEvent))
#17 C:\wamp\www\zendJobeet\vendor\ZF2\library\Zend\EventManager\EventManager.php(207): Zend\EventManager\EventManager->triggerListeners('dispatch', Object(Zend\Mvc\MvcEvent), Object(Closure))
#18 C:\wamp\www\zendJobeet\vendor\ZF2\library\Zend\Mvc\Application.php(309): Zend\EventManager\EventManager->trigger('dispatch', Object(Zend\Mvc\MvcEvent), Object(Closure))
#19 C:\wamp\www\zendJobeet\public\index.php(17): Zend\Mvc\Application->run()
#20 {main}
Message:
SupprimerZend\ServiceManager\ServiceManager::get was unable to fetch or create an instance for Zend\Db\Adapter\Adapter
=> La réponse est juste dans le message du dessus :-)
Bonjour, j'ai suivis ton tuto jusqu'a ce jour(Jour 4) et j'obtiens l'erreur suivante : " Fatal error: Uncaught exception 'Zend\ModuleManager\Exception\RuntimeException' with message 'Module (Application) could not be initialized.' in C:\wamp\www\Zend_test\vendor\zendframework\zendframework\library\Zend\ModuleManager\ModuleManager.php on line 175" après avoir recu une erreur qui disais que le module Application avais un problème et que j'ai résolu en supprimant application de la liste des module dans config/applicatio.config.php
RépondreSupprimerJe suis vraiment bloqué svp
Bonjour,
SupprimerC'est avec le code trouvé dans l'archive ?
oui, j'ai telechargé ton archive et il me génèrz toujours ces erreurs
SupprimerOk, je regarderais aujourd'hui. Là, je n'ai pas le temps du tout :-)
SupprimerBonjour Romain,
RépondreSupprimerJe confirme il ya une erreur de connexion et de création d'instance, c'est vraiment dommage de suivre 4 pages et de tomber sur une erreurs insoluble pour les débutants ... :(
Bonjour,
RépondreSupprimerLe bug en question viens d'un problème du module bjyProfiler qui n'était pas à jour avec la version Zend Framework2.
Il a été fixé sur le repo Git : https://github.com/bjyoungblood/BjyProfiler
Grosse prise de tête pour trouver mais j'ai trouvé !
et je fais comment pour le resoudre?
RépondreSupprimerArnaud, tu télécharges la version sur le repository Git du projet BjyProfiler et tu le remplaces avec celui existant dans le dossier vendor
RépondreSupprimerMerci Sèb pour ton aide
SupprimerSalut, qui a pu traiter l'erreur du BjyProfiler ? je l'ai telecharger et mis dans le dossier vendor mais ça ne marche pas :( help !
RépondreSupprimerBONJOUR ,
RépondreSupprimerj'ai une erreur de type " Uncaught exception 'RuntimeException' with message 'Unable to load ZF2. Run `php composer.phar install` or define a ZF2_PATH environment variable.' in C:\wamp\www\ZF2\init_autoloader.php"
salut,
RépondreSupprimerj ai une erreur de ce type " Informations complémentaires:
Zend\View\Exception\RuntimeException
Fichier:
/var/www/reseausocial1/vendor/zendframework/zendframework/library/Zend/View/Renderer/PhpRenderer.php:499
Message:
Zend\View\Renderer\PhpRenderer::render: Unable to render template"
A quoi sa sert de faire ce tuto si tu le fais pas intégralement?
RépondreSupprimerPourtant ce tuto était génial, tu expliques bien mais c'est carrément incomplet.
Bonjour,
SupprimerComme tout le monde, j'ai des priorités, et le tuto n'en était pas une depuis quelques mois :-)
Le tuto est là pour donner les bases du framework. Rien ne t’empêche de suivre le début et de te débrouiller pour la suite.
Je t'invite cependant à revenir voir régulièrement. Je devrais pouvoir poster de nouveaux tutos prochainement.
Bonjour,
RépondreSupprimerJe suis débutant sur ZF2 :
J'aimerais faire une requête : comme ceci :
"SELECT `item_quantity` FROM `vw_my_asn_unit_sum` WHERE `message_id` = '000098b0-5896-44db-834f-c504937f513e';"
l'affichage :
++++++++++++++
+ item_quantity +
++++++++++++++
+ 54 +
++++++++++++++
ma view est :
++++++++++++++++++++++++++++++++++++++++++++++
+ message_id + item_quantity +
++++++++++++++++++++++++++++++++++++++++++++++
+000098b0-5896-44db-834f-c504937f513e + 54 +
+00009d98-b130-4343-b8ad-b1dcdbeff8de + 720 +
+0001919e-e902-48a4-8d8e-3d769d752e07 + 144 +
+0005baa5-1ba4-4da3-9e7c-a9005390ca08 + 435 +
+00086b6d-f359-43ab-a0b4-cb055de8a466 + 0 +
+000bb737-c8f5-4152-865f-c990dbc90b9b + 15609 +
+000dff41-baf3-4feb-bdcf-c31c35a8060f + 1 +
+00101b13-4a19-4360-be96-a556d29b7ca7 + 31 +
+001bdcd1-99fd-4bf4-804f-02ddf968f927 + 166 +
+001dbfa3-9b99-4004-82ec-aba951c0186d + 0 +
+001e9ee2-eb93-4541-b731-3a9fcbe3142d + 77 +
++++++++++++++++++++++++++++++++++++++++++++++
J'ai fait une fonction suivante :
public function getSumUnit($message_id)
{
$message_id = (string)$message_id ;
$select = $this->tableGateway->getSql()->select();
$select->where->equalTo('message_id', $message_id);
$resultSet = $this->tableGateway->selectWith($select);
return $resultSet;
}
mais cela me retourne une erreur :
Object of class Zend\Db\ResultSet\ResultSet could not be converted to string
Or je souhaite juste l'item_quantity et non le message_id et l'item_quantity.
Mes question sont les suivantes :
- 1) comment faire un select avec juste item_quantity en retour
- 2) comment tu l'affiche sur la page xxxx.phtml sachant que j'ai un retour sur le Controller pour la page comme celui-ci :
return array(
'asn_header' => $asn_header,
'recap' => $array_recap,
'summaries' => $summaries,
'result' => $result,
'language' => $language,
'form' => $form,
'systematic_consumption' => $systematic_consumption,
);
Bonjour,
SupprimerPour repondre à tes questions:
1/ Tu dois pouvoir faire:
$select->columns(array('l'item_quantity'));
2/ Si tu passe 'result' à ta vue, ca correspond au resultat de ton select ?
Tu dois pouvoir faire ça dans ta vue:
foreach ($this->result as $result)
echo $result->'item_quantity
merci de ta réponse !
Supprimerça marche !
Bonjour,
Supprimerje sais pas si tu as déjà fait des requêtes avec PredicatSet :
je bloque sur une bêtise qu'en SQL ça prend 10 secondes à corriger mais sur Zend je sais pas faire, voilà le code PHP :
Et le SQL :
SupprimerSELECT * FROM `vw_my_asn_header` where `username` = 'toto' and ( `shipment_number` like '20151106052811' or `shipment_number` like '20151110053250' or `shipment_number` like '20151116054359') ORDER BY `message_id` ASC
Mon problème est de mettre les parenthèses au bon endroit.
La requête zend :
["queryString"] => string(181) "SELECT `vw_my_asn_header`.* FROM `vw_my_asn_header` WHERE (username = :where1 AND `shipment_number` LIKE :where2 OR `shipment_number` LIKE :where3 OR `shipment_number` LIKE :where4)"
Je met comment les parenthèses.
Cordialement,
public function searchSitesDeliveries($username, Search $search)
RépondreSupprimer{
$select = $this->tableGateway->getSql()->select();
$predicate_set = new Predicate\PredicateSet(
array(new Predicate\Expression('username = ?', $username)),
Predicate\PredicateSet::COMBINED_BY_AND
);
if (!empty($search->get_shipment_number()))
{
$valeur = $search->get_shipment_number();
if(is_array($valeur))
{
$valeur = array_unique($valeur);
\Zend\Debug\Debug::dump($valeur);
foreach ($valeur as $key => $value)
{
if($key == 0)
{
$predicate_set->andPredicate(new Predicate\Like('shipment_number', '%'.$value.'% ('));
}
else
{
if($key == end($key))
{
$predicate_set->orPredicate(new Predicate\Like('shipment_number', '%'.$value.'%)'));
}
else
{
$predicate_set->orPredicate(new Predicate\Like('shipment_number', '%'.$value.'%'));
}
}
}
}
else
{
$predicate_set->andPredicate(new Predicate\Like('shipment_number', '%'.$valeur.'%'));
}
}
$select->where($predicate_set);
\Zend\Debug\Debug::dump($this->tableGateway->selectWith($select));
$resultSet = $this->tableGateway->selectWith($select);
salut,
RépondreSupprimerj ai une erreur
Fatal error: Uncaught exception 'Zend\ModuleManager\Exception\RuntimeException' with message 'Module (projet1) could not be initialized.' in C:\wamp\www\projet1\vendor\zendframework\zend-modulemanager\src\ModuleManager.php:195 Stack trace: #0 C:\wamp\www\projet1\vendor\zendframework\zend-modulemanager\src\ModuleManager.php(169): Zend\ModuleManager\ModuleManager->loadModuleByName(Object(Zend\ModuleManager\ModuleEvent)) #1 C:\wamp\www\projet1\vendor\zendframework\zend-modulemanager\src\ModuleManager.php(96): Zend\ModuleManager\ModuleManager->loadModule('projet1') #2 [internal function]: Zend\ModuleManager\ModuleManager->onLoadModules(Object(Zend\ModuleManager\ModuleEvent)) #3 C:\wamp\www\projet1\vendor\zendframework\zend-eventmanager\src\EventManager.php(444): call_user_func(Array, Object(Zend\ModuleManager\ModuleEvent)) #4 C:\wamp\www\projet1\vendor\zendframework\zend-eventmanager\src\EventManager.php(205): Zend\EventManager\EventManager->triggerListeners('loadModules', Object(Zend\ModuleManager\ModuleEvent), NULL) #5 C:\w in C:\wamp\www\projet1\vendor\zendframework\zend-modulemanager\src\ModuleManager.php on line 195
Salut,
SupprimerTon module existe bien ?
Il est declaré dans application.config.php ?
Autre erreur possible => tu as bien un fichier Module.php dans ton module projet1, avec une classe appelé Module ?
ouiii voila mon fichier application.config.php
RépondreSupprimer'modules' => array(
'Application','projet1'
),
et voila le contenu de mon fichier module.php
array(__DIR__.'/autoload_classmap.php',),
'zendframework\zend-loader\src\ClassMapAutoloader' => array('namespaces' => array(__NAMESPACE__=>
__DIR__.'/src/'.__NAMESPACE__,),),);
}
public function getConfig (){
return include __DIR__ .'/config/module.config.php';
}
je pense que le probleme vient de composer.json !??
Composer could not find a composer.json file in C:\ProgramData\ComposerSetup\bin
RépondreSupprimerTo initialize a project, please create a composer.json file as described in the
https://getcomposer.org/ "Getting Started" section
Bonjour!Merci pour ce tutoriel!
RépondreSupprimerJ'essai de refaire les mêmes étapes pour mon propre projet.Mes deux tables sont service(id_service,nom_service) et personnel(id_prsonnel,id_service,matricule,nom_personnel,prenom_personnel,date_naissance).
en compilation,j'ai l'erreur suivante qui s'affiche en haut mais les information dans la base de données s'affiche correctement.
Array ( [id_service] => 1 [nom_service] => Moderateur ) Array ( [id_service] => 2 [nom_service] => Developpeur ) Array ( [id_service] => 3 [nom_service] => Secretaire ) Array ( [id_service] => 4 [nom_service] => Administrateur )
Bonsoir,
SupprimerQuelle erreur ?
Bonjour apres avoir suivie ce tuto et rajouté le fichier database.local.php j'ai cette erreur Fatal error: Class 'BjyProfiler\Db\Adapter\ProfilingAdapter' not found in /Users/Shared/MAMP/WWW/ZendComp/config/autoload/database.local.php on line 13 aurrez vous une idée svp ? merci bien
RépondreSupprimerBonjour apres avoir suivie ce tuto et rajouté le fichier database.local.php j'ai cette erreur Fatal error: Class 'BjyProfiler\Db\Adapter\ProfilingAdapter' not found in /Users/Shared/MAMP/WWW/ZendComp/config/autoload/database.local.php on line 13 aurrez vous une idée svp ? merci bien
RépondreSupprimer