Partage
  • Partager sur Facebook
  • Partager sur Twitter

Cours Architecture PHP professionnelle / Questions

    29 décembre 2016 à 23:56:39

    Bonjour tout le monde,

    Ce bout de code me pose certaines interrogations:

    public function findAllByArticle($articleId) {
    
            // The associated article is retrieved only once
    
            $article = $this->articleDAO->find($articleId);
    
    
            // art_id is not selected by the SQL query
    
            // The article won't be retrieved during domain objet construction
    
            $sql = "select com_id, com_content, com_author from t_comment where art_id=? order by com_id";
    
            $result = $this->getDb()->fetchAll($sql, array($articleId));
    
    
            // Convert query result to an array of domain objects
    
            $comments = array();
    
            foreach ($result as $row) {
    
                $comId = $row['com_id'];
    
                $comment = $this->buildDomainObject($row);
    
                // The associated article is defined for the constructed comment
    
                $comment->setArticle($article);
    
                $comments[$comId] = $comment;
    
            }
    
            return $comments;
    
        }
    
    
        /**
    
         * Creates an Comment object based on a DB row.
    
         *
    
         * @param array $row The DB row containing Comment data.
    
         * @return \MicroCMS\Domain\Comment
    
         */
    
        protected function buildDomainObject(array $row) {
    
            $comment = new Comment();
    
            $comment->setId($row['com_id']);
    
            $comment->setContent($row['com_content']);
    
            $comment->setAuthor($row['com_author']);
    
    
            if (array_key_exists('art_id', $row)) {
    
                // Find and set the associated article
    
                $articleId = $row['art_id'];
    
                $article = $this->articleDAO->find($articleId);
    
                $comment->setArticle($article);
    
            }
    
            
    
            return $comment;
    
        }

    Premièrement dans $result, on ne sélectionne pas 'art_id' donc pk le if(array_key_exists('art_id', $row)) dans la fonction buildDomainObject?

    De plus cette fonction est appelée par findAllByArticle qui fait après son appel $comment->setArtcile($article); enfin vous voyez je pense...

    Donc je ne vois pas l'utilité de ce "if(array_key_exists('art_id', $row))...

    De plus pourquoi mettre private $articleDAO ça fonctionnerais très bien sans... on a en bdd de la table comment art_id on recherche donc les commentaires par art_id et voilà on affiche le tout ... je comprend bien le code et ça fonctionne mais certaines choses ne me semblent pas indispensables peut etre plus tard on verra que ça servira mais on n'en est pas là on on peut ajouter par la suite....

    -
    Edité par kid_jonath 30 décembre 2016 à 0:14:19

    • Partager sur Facebook
    • Partager sur Twitter
      30 décembre 2016 à 18:48:46

      Bonjour,

      Tout fonctionne jusqu'à l'itération 3. Lorsque j'ajoute silex j'obtiens ces messages d'erreur : 

      Warning: DateTime::createFromFormat(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thomasviennet/www/sites/cours/MicroCMS/vendor/symfony/http-foundation/Response.php on line 374
      
      Warning: Cannot modify header information - headers already sent by (output started at /Users/thomasviennet/www/sites/cours/MicroCMS/vendor/symfony/http-foundation/Response.php:374) in /Users/thomasviennet/www/sites/cours/MicroCMS/vendor/symfony/http-foundation/Response.php on line 380
      
      Warning: Cannot modify header information - headers already sent by (output started at /Users/thomasviennet/www/sites/cours/MicroCMS/vendor/symfony/http-foundation/Response.php:374) in /Users/thomasviennet/www/sites/cours/MicroCMS/vendor/symfony/http-foundation/Response.php on line 380
      
      Warning: Cannot modify header information - headers already sent by (output started at /Users/thomasviennet/www/sites/cours/MicroCMS/vendor/symfony/http-foundation/Response.php:374) in /Users/thomasviennet/www/sites/cours/MicroCMS/vendor/symfony/http-foundation/Response.php on line 380
      
      Warning: Cannot modify header information - headers already sent by (output started at /Users/thomasviennet/www/sites/cours/MicroCMS/vendor/symfony/http-foundation/Response.php:374) in /Users/thomasviennet/www/sites/cours/MicroCMS/vendor/symfony/http-foundation/Response.php on line 385

      Mais les articles apparaissent toujours correctement en dessous de ces messages.

      Puis lorsque je passe le format en UTC à la ligne 374 j'obtiens ce message d'erreur : 

      Catchable fatal error: Argument 1 passed to Symfony\Component\HttpFoundation\Response::setDate() must be an instance of DateTime, boolean given, called in /Users/thomasviennet/www/sites/cours/MicroCMS/vendor/symfony/http-foundation/Response.php on line 374 and defined in /Users/thomasviennet/www/sites/cours/MicroCMS/vendor/symfony/http-foundation/Response.php on line 674

      Et les articles n'apparaissent plus du tout.

      Pouvez-vous m'aider s'il vous plait ?

      -
      Edité par Wiki90 30 décembre 2016 à 18:49:39

      • Partager sur Facebook
      • Partager sur Twitter

      Consultant SEO : https://referencime.fr/

        5 janvier 2017 à 21:09:07

        Bonjour et une très bonne année a tous...

        Je suis à l'itération 8 et j'ai une petite question et je ne sais pas si quelqu'un pourra me répondre... Je comprend bien l'itération 8 mais quand je regarde la classe SecurityServiceProvider je ne comprend pas trop ou on va rechercher en bdd les informations users... :

        $app->get('/login', function(Request $request) use ($app) {
        
            return $app['twig']->render('login.html.twig', array(
        
                'error'         => $app['security.last_error']($request),
        
                'last_username' => $app['session']->get('_security.last_username'),
        
            ));
        
        })->bind('login');

        ici on appelle bien le service $app['twig'] ok et dans TwigServiceProvider on a ceci:

        $var = new AppVariable();
                            if (isset($app['security.token_storage'])) {
                                $var->setTokenStorage($app['security.token_storage']);
                            }
        

        Mais dans SecurityServiceProvider $app['security.token_storage'] est juste une instance d'une classe dans laquelle on a encore rien mis jusque là...

        $app['security.token_storage'] = function ($app) {
                    return new TokenStorage();
                };
        

        Enfin bref je comprend plus ou moins le fonctionnement de tout ça mais la dessus je cherche et ne trouve pas parce que on a pas mal de services mais tant qu'ils ne sont pas appelé ils sont juste là je pense... Enfin je ne sais pas si je me suis bien exprimé et si quelqu'un peut m'éclairer là dessus ce serait merveilleux parce que ça fais quelques jours que je lis et relis toutes ces classes pour comprendre le truc

        De plus dans SecurityServiceProvider on voit:

        $app['user'] = $app->factory(function ($app) {
                    if (null === $token = $app['security.token_storage']->getToken()) {
                        return;
                    }
        
                    if (!is_object($user = $token->getUser())) {
                        return;
                    }
        
                    return $user;
                });
        

        Ou est cette fonction getUser()?

        Enfin je nage un peu quand meme.... please help

        -
        Edité par kid_jonath 5 janvier 2017 à 22:49:12

        • Partager sur Facebook
        • Partager sur Twitter
          10 janvier 2017 à 14:02:11

          bpesquet a écrit:

          Bonjour,

          Je viens de finir la mise à jour du cours pour Silex 2. Les principaux changements sont :

          [...]

          • Suppression de la barre d'outils Symfony, instable dans la version actuelle.

          [...]

          Bonjour Baptiste et merci beaucoup pour ce cours qui m'a permis de bien démarrer avec les frameworks. 

          Concernant la barre d'outil Symfony, elle fonctionne bien avec Silex version 2. Il faut installer : "symfony/twig-bridge": "~3.2" et "silex/web-profiler": "^2.0". Avec ces versions-là et les autres composants en version identique à celles que tu donnes dans le cours, ça passe crème.

          • Partager sur Facebook
          • Partager sur Twitter
            21 janvier 2017 à 11:09:26

            Bonjour je n'arrive pas à tester mon site le navigateur me mes sa

            Pas trouvé

            L'URL /Users/mac/Documents/Programe/sitecubeipro.html demandée n'a pas été trouvée sur ce serveur.

            • Partager sur Facebook
            • Partager sur Twitter
              22 janvier 2017 à 20:57:42

              Erreur trouvée.....

              -
              Edité par Rêveurrr 26 janvier 2017 à 10:55:34

              • Partager sur Facebook
              • Partager sur Twitter
                30 janvier 2017 à 21:45:35

                Bonjour j'ai un bug lorsque j'appelle la méthod share itération 10

                <?php
                
                $app['twig'] = $app->share($app->extend('twig', function(Twig_Environment $twig, $app) {
                
                    $twig->addExtension(new Twig_Extensions_Extension_Text());
                
                    return $twig;
                
                }));
                
                $app->register(new Silex\Provider\ValidatorServiceProvider());

                apparemment la fonction share a été supprimé de symfony et l'appelle n'existe pas où je n'ai pas bien compris d'après les renseignements que j'ai pu avoir.

                • Partager sur Facebook
                • Partager sur Twitter
                  31 janvier 2017 à 23:07:23

                  Effectivement, avec Silex 2, un service n'a plus besoin d'être défini en tant que "partagé" (shared) pour l'être. Il sera partagé d'office. Par défaut, c'est donc la même instance du service qui sera retournée à chaque appel si on ne spécifie rien. Si on ne veut pas que ce soit le cas, il faut définir le service en tant que factory, ou protected.

                  Voir : http://silex.sensiolabs.org/doc/2.0/services.html#service-definitions

                  Concrètement, pour le cours, tu dois changer ton bout de code par ça :

                  $app['twig'] = $app->extend('twig', function(Twig_Environment $twig, $app) {
                  
                      $twig->addExtension(new Twig_Extensions_Extension_Text());
                  
                   return $twig;
                   
                  });



                  -
                  Edité par cdebix 31 janvier 2017 à 23:09:05

                  • Partager sur Facebook
                  • Partager sur Twitter
                    3 février 2017 à 22:04:31

                    Bonjour,

                    Je suis actuellement en fin de l’activité 2 (c’est-à-dire les corrections).

                    Ça serait bien de corriger l’insertion pour ne pas avoir les problèmes de compatibilité entre les cours (Silex 2) et l’activité (Silex 1).

                    Personnellement j’ai réglé le problème dans app.php :

                    // ...
                    'security.role_hierarchy' => array( 'ROLE_ADMIN' => array('ROLE_USER'),),
                    
                     'security.access_rules' => array(array('^/admin','ROLE_ADMIN'),array('^/link/submit','ROLE_USER')),
                    
                    'security.default_encoder' => function () use ($app){return $app['security.encoder.digest'];} ,
                    // ...

                    Le problème revient si on prend le code du cours pour la gestion des utilisateurs et que l’on créé un utilisateur, celui-là ne peut se connecter car dans AdminController.php fonction addUserAction() on peut remarquer :

                    $encoder = $app['security.encoder.bcrypt'];

                    J’ai donc changé ça par :

                    $encoder = $app['security.default_encoder'];

                    Ce qui permet d’avoir à changer l’encodage pour se connecter et insérer seulement dans app.php

                    On peut imaginer aussi (je n’ai pas testé mais il y a pas de raison.) :

                     $password = $app['security.default_encoder'] ->encodePassword($plainPassword, $user->getSalt());

                    J’ai donc téléchargé la correction et remarqué qu’il y avait des erreurs (chez moi en tout cas) pour la debug tool barre de symfony2/Silex qui ne marche pas.

                    En fait d’après ce que j’ai vu il manque HttpFragmentServiceProvider.

                    $app->register(new Silex\Provider\ServiceControllerServiceProvider());
                    
                    if (isset($app['debug']) && $app['debug']) {
                    
                        $app->register(new Silex\Provider\HttpFragmentServiceProvider());
                    
                        $app->register(new Silex\Provider\WebProfilerServiceProvider(), array(
                    
                            'profiler.cache_dir' => __DIR__.'/../var/cache/profiler'
                    
                        ));
                    
                    }

                    Après ça, la barre marche sur la correction chez moi.

                    Je l’ai mis en place pour Silex 2 aussi :

                    $app->register(new Silex\Provider\ServiceControllerServiceProvider());
                    
                    if(isset($app['debug']) && $app['debug'])
                    
                    {
                    
                        $app->register(new Silex\Provider\HttpFragmentServiceProvider());
                    
                        $app->register(new Silex\Provider\WebProfilerServiceProvider(), array(
                    
                        'profiler.cache_dir' => __DIR__.'/../var/cache/profiler',
                    
                        'profiler.mount_prefix' => '/_profiler', // this is the default
                    
                    ));
                    
                    }

                    Même principe il y a en fait que le composer.json qui change :

                        "require": {
                    
                                    ……
                    
                            "symfony/twig-bridge": "~2.8|3.2.*",
                    
                                    ……
                    
                        },
                    
                        "require-dev": {
                    
                                    ……
                    
                            "silex/web-profiler": "~2.0"
                    
                        },

                    Du coup l’activité n’utilise pas Assetic non plus il me semble, contrairement au cours.

                    Je trouve ça un peut dommage, ça serait bien d’avoir l’activité 2 et ses utilisateurs en base actualisé avec Silex 2.

                    Merci et un grand BRAVO pour ce cours qui  (à mon avis) est très bien fait.

                    Tout comme les autres dont vous êtes l’auteur et que j’ai eu le temps de faire.

                    Enfin je trouve que débuter avec Symfony 2 ou 3 est plus simple puisque moins de structure, dépendances à gérer et la console pour générer les bundles  etc.

                    C’est juste parfait pour débuter en framework objet (même plus que pour débuter d’ailleurs ^^)

                    • Partager sur Facebook
                    • Partager sur Twitter
                      5 février 2017 à 18:56:20

                      Bonjour,

                      dans la partie gestion de la sécurité, pourquoi limiter l'utilisateur à un seul rôle ?
                      Silex/symfony gere les roles multiples, autant en parler dans ce tutoriel .

                      du coup dans src/domain/user.php set et get role(s) peuvent etre facilement modifiés pour supporter cette fonction.
                      permettre par exemple d'ajouter un ROLE_MODERATOR

                      les rôles étant stockés dans la DB en étant séparés par une virgule

                       public function setRole($role) 
                      {
                          // un role ou plusieurs, un tableau est renvoyé quoi qu'il arrive
                          $roles = explode(',', $role);			
                          $this->role = $roles;		
                          return $this;
                      }
                      
                      public function getRoles()
                      {
                         // plus necessaire de créer un tableau avant renvoi
                         return $this->getRole();
                      }




                      il manque peut etre une assignation du ROLE_USER par defaut !

                      ca ne change rien au cours, mais ca permet d introduire des explications sur les roles multiples et l heritage.

                      sujet sur lequel j'ai passé du temps pour comprendre...

                      -
                      Edité par mooztik 5 février 2017 à 18:58:39

                      • Partager sur Facebook
                      • Partager sur Twitter
                        5 février 2017 à 23:58:05

                        Oui, sinon on peut aussi simplement utiliser la hiérarchisation des rôles, et n'assigner qu'un rôle à l'utilisateur.

                        Par exemple, tu peux avoir un rôle user simple qui n'a que le droit de lire les articles, un rôle commentateur, un rôle lecteur privé qui peut commenter et qui a aussi accès à la lecture d'articles spéciaux protégés, et un rôle admin qui peut tout faire.

                        Dans app.php :

                        $app['security.role_hierarchy'] = array(
                          'ROLE_ADMIN' => array(
                            'ROLE_PRIVATE_READER'
                          ),
                          'ROLE_PRIVATE_READER' => array(
                            'ROLE_COMMENTER'
                          ),
                          'ROLE_COMMENTER' => array(
                            'ROLE_USER'
                          )
                        );

                        Ici c'est un exemple très simple, chaque rôle hérite des privilèges du précédent. Mais on peut désigner par ailleurs toutes les combinaisons qu'on veut. Il suffit de créer arbitrairement un nom de rôle pour chaque type de privilège et choisir de quel rôle il peut hériter dans le tableau. Ca permet de ne garder qu'on rôle par utilisateur et de pouvoir changer en masse les privilèges si notre politique change, plutôt que de devoir révoquer tel ou tel rôle, utilisateur par utilisateur.



                        • Partager sur Facebook
                        • Partager sur Twitter
                          6 février 2017 à 21:06:51

                          cdebix c'est un des éléments dont je parle. entre autre la hiérarchisation(ou héritage) et les rôles multiples.

                          sujet non abordé dans ce tutoriel.
                          de plus, un seul privilège peu poser une limite dans certains cas.
                          par exemple :

                          admin > moderateur > user
                          admin > correcteur > user

                          admin doit hériter de tous les roles. pour autant moderateur n'est pas correcteur et inversement.

                          • Partager sur Facebook
                          • Partager sur Twitter
                            9 février 2017 à 11:59:48

                            Bonjour, 

                            Je suis toujours bloqué au même endroit donc je me permets de demander à nouveau un coup de main :)

                            Voici mon problème : 

                            Wiki90 a écrit:

                            Bonjour,

                            Tout fonctionne jusqu'à l'itération 3. Lorsque j'ajoute silex j'obtiens ces messages d'erreur : 

                            Warning: DateTime::createFromFormat(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /Users/thomasviennet/www/sites/cours/MicroCMS/vendor/symfony/http-foundation/Response.php on line 374
                            
                            Warning: Cannot modify header information - headers already sent by (output started at /Users/thomasviennet/www/sites/cours/MicroCMS/vendor/symfony/http-foundation/Response.php:374) in /Users/thomasviennet/www/sites/cours/MicroCMS/vendor/symfony/http-foundation/Response.php on line 380
                            
                            Warning: Cannot modify header information - headers already sent by (output started at /Users/thomasviennet/www/sites/cours/MicroCMS/vendor/symfony/http-foundation/Response.php:374) in /Users/thomasviennet/www/sites/cours/MicroCMS/vendor/symfony/http-foundation/Response.php on line 380
                            
                            Warning: Cannot modify header information - headers already sent by (output started at /Users/thomasviennet/www/sites/cours/MicroCMS/vendor/symfony/http-foundation/Response.php:374) in /Users/thomasviennet/www/sites/cours/MicroCMS/vendor/symfony/http-foundation/Response.php on line 380
                            
                            Warning: Cannot modify header information - headers already sent by (output started at /Users/thomasviennet/www/sites/cours/MicroCMS/vendor/symfony/http-foundation/Response.php:374) in /Users/thomasviennet/www/sites/cours/MicroCMS/vendor/symfony/http-foundation/Response.php on line 385

                            Mais les articles apparaissent toujours correctement en dessous de ces messages.

                            Puis lorsque je passe le format en UTC à la ligne 374 j'obtiens ce message d'erreur : 

                            Catchable fatal error: Argument 1 passed to Symfony\Component\HttpFoundation\Response::setDate() must be an instance of DateTime, boolean given, called in /Users/thomasviennet/www/sites/cours/MicroCMS/vendor/symfony/http-foundation/Response.php on line 374 and defined in /Users/thomasviennet/www/sites/cours/MicroCMS/vendor/symfony/http-foundation/Response.php on line 674

                            Et les articles n'apparaissent plus du tout.

                            Pouvez-vous m'aider s'il vous plait ?

                            -
                            Edité par Wiki90 30 décembre 2016 à 18:49:39



                            • Partager sur Facebook
                            • Partager sur Twitter

                            Consultant SEO : https://referencime.fr/

                              9 février 2017 à 18:48:31

                              Bonjour, personnellement je n'ai pas reçu ce message d'erreur. Il semble que ce soit une erreur sur la datetime je dirais que le date.timezone du php.ini n'est pas configuré (en tout cas c'est que je regarderais en premier).

                              Ce qui me fait dire ça, c'est cette partie surtout :


                              It is not safe to rely on the system's timezone settings.
                              
                              You are *required* to use the date.timezone setting or
                              
                              the date_default_timezone_set() function.

                              et aussi :

                              We selected the timezone 'UTC' for now,
                              
                              but please set date.timezone to select your timezone.


                              J'ai sur mon serveur dans le php.ini :

                              date.timezone = Europe/Paris

                              Si ce n'est pas ça, une capture du code que vous insérez en ligne 374 serait de probablement plus simple à comprendre.

                              Bon courage !

                              -
                              Edité par Osush 9 février 2017 à 18:57:32

                              • Partager sur Facebook
                              • Partager sur Twitter
                                14 février 2017 à 10:53:03

                                Bonjour,

                                est-il correct de générer les getter setter dynamiquement ?

                                <?php
                                
                                namespace MicroCMS\Domain;
                                
                                class Article 
                                {
                                   
                                    private $id;
                                    private $title;
                                    private $content;
                                    private $_VARS=array();
                                
                                    public function __construct()
                                	{
                                		foreach(array_keys(get_class_vars(__CLASS__)) as $key)
                                		{
                                			if($key != '_VARS') { // ignore _VARS
                                				$this->_VARS[] = $key;
                                			}
                                		}
                                	}	
                                	
                                	public function __get($var)
                                	{
                                		if(in_array($var, $this->_VARS))
                                		{
                                			$this->getVar($var);
                                		}
                                	}
                                	
                                	public function __set($var, $value)
                                	{
                                		if(in_array($var, $this->_VARS))
                                		{
                                			$this->setVar($var, $value);
                                		}
                                	}
                                
                                	private function getVar($var) {		
                                		return $this->$var;		
                                	}	
                                	
                                	private function setVar($var, $value) {		
                                		$this->$var = $value;
                                		return $this;
                                	}
                                }



                                -
                                Edité par mooztik 14 février 2017 à 10:59:43

                                • Partager sur Facebook
                                • Partager sur Twitter
                                  17 février 2017 à 16:00:19

                                  Bonjour, Personnellement je dirais que non.

                                  Déjà faire des moulinettes de tableaux là où, je pourrais atteindre simplement ce que je veux avec un $article->getId() ou $article->setId(‘id’)(par exemple.) me semble beaucoup plus lourd ! (même si effectivement c’est plus court à coder ^^)

                                  De plus je vous invite à regarder Twig et constater que dans une vue Twig je vais faire {{ article.id }}

                                  Qui regarde si il y a : $article[‘id’] , $article->getId() et article->isId() (il me semble que c’est tout.)

                                  Alors que vous votre fonction est (si j’ai bien lu) $article->getVar($id) ;

                                  De plus les __get() et __set() (si je me rappel bien) sont des fonctions qui s’exécute au moment d’un appel à une fonction get ou set et donc vous ‘forcez’ l’utilisation, alors que vos fonctions getVar() et setVar() sont private donc nom utilisables à l’extérieur de l’objet.

                                  D’une manière générale, il me semble que c’est plus de traitement pour éviter d’écrire le code.

                                  De plus si je ne dois pas pouvoir setId() car auto incrémenté en base, avec ce système je peux quand même faire setVar(‘id’,’toto’) ; qui au passage n’est pas un int donc double erreur du coup.

                                  Je ne peux même pas faire de contrôle sur le type avec ce genre de choses.

                                  Voilà ce n’est que mon avis, il me semble pour toutes ces raisons que je dirais : non ce n’est pas du tout une bonne pratique (ou même une pratique à faire tout court).

                                  Bon courage et bonne continuation.

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    18 février 2017 à 11:15:42

                                    Bonjour à tous,

                                    Je suis en train de réaliser le 2ème travail pratique, et il y a un décalage entre les notions vues dans les tutos et le TP, au niveau des versions des librairies.

                                    Cela ne parait pas trop grave, j'ai pu corriger à la volée 2/3 choses*, mais plus problématique, les identifiants/mots de passe/salt fournis pour le TP ne fonctionnent pas avec les librairies vues durant le cours. En utilisant les valeurs fournies pour le tuto MicroCMS, l'identification fonctionne.

                                    Question :

                                    • est-ce que l'on doit travailler avec les versions des librairies proposées dans l'exercice (et dans ce cas, on va tomber sur des syntaxes qui ne correspondent pas au cours), 
                                    • ou peut-on avoir une version à jour de l'énoncé de l'exercice,
                                    • ou est-il acceptable de modifier personnellement db/contents.sql et mettre des valeurs password/salt qui fonctionnent ?

                                    D'avance merci pour votre éclairage.

                                    * Les différences :

                                    MicroCMS/composer.json :

                                      "require": {
                                            "silex/silex": "~2.0",
                                            "doctrine/dbal": "~2.5",
                                            "twig/twig": "~1.28",
                                    ...

                                    Weblinks/composer.json

                                    "require": {
                                            "silex/silex": "~1.2",
                                            "doctrine/dbal": "~2.4",
                                            "twig/twig": "~1.16"
                                    ...

                                    J'ai ensuite du revoir quelques erreurs (app/app.php, ligne 17 : $app->share(...) : fonction non définie )

                                    -
                                    Edité par dblbass 19 février 2017 à 9:21:58

                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      18 février 2017 à 18:17:35

                                      Bonjour,

                                      En fait la réponse dépend de vous.

                                      L’activité doit marcher sans problème, donc soit vous choisissez Silex1 (l'Activité), soit Silex2 (le cours). Si vous avez choisi la deuxième option, vous devez changer ce qu'il faut dans le code pour éviter les erreurs.

                                      SANS toucher à la donnée, on doit pouvoir corriger avec la base de données fourni dans l'exercice.

                                      Pour régler vos problèmes d'encodage si vous faites du Silex 2, j'ai proposé une solution plus haut dans ce sujet.

                                      Bon courage.

                                      -
                                      Edité par Osush 18 février 2017 à 18:18:12

                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        19 février 2017 à 9:59:44

                                        Merci Osush pour votre réponse, j'avoue que je n'avais pas eu la patience de parcourir les 14 pages du sujet.

                                        Je vais suivre votre piste.

                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          19 février 2017 à 15:15:47

                                          Osush a écrit:

                                          De plus les __get() et __set() (si je me rappel bien) sont des fonctions qui s’exécute au moment d’un appel à une fonction get ou set et donc vous ‘forcez’ l’utilisation, alors que vos fonctions getVar() et setVar() sont private donc nom utilisables à l’extérieur de l’objet.

                                          Bonjour, Osush

                                          __get et __set sont de surchages magiques, donc 
                                          $article->id est traité comme  __get('id') (équivalent de $article->getId)
                                          et
                                          $article->id=5 est traité comme __set('id', 5) (équivalent de $article->setId(5);

                                          les getVar et setVar sont private justement pour ne pas pouvoir etre appelées de l exterieur, et seules les methodes __get et __set doivent pouvoir etre appelées.

                                          quand aux contrôles, ils sont sensés être faits en amont (dans le cas du tutoriel, via le FormBuilderInterface)

                                          seule point limitant est le fait qu'on ne peu pas faire de traitement de donnée au sain de la classe (on a à faire à la seule fonction de getter/setter) à moins de rajouter des getters/setters classiques, et dans ce cas je modifie le code en ce sens :

                                          <?php
                                           
                                          namespace MicroCMS\Domain;
                                           
                                          class Article
                                          {
                                              
                                              private $id;
                                              private $_VARS=array('title', 'content');
                                           
                                              
                                          	public function __get($var)
                                              {
                                                  if(in_array($var, $this->_VARS))
                                                  {
                                                      $this->getVar($var);
                                                  }
                                              }
                                               
                                              public function __set($var, $value)
                                              {
                                                  if(in_array($var, $this->_VARS))
                                                  {
                                                      $this->setVar($var, $value);
                                                  }
                                              }
                                           
                                              private function getVar($var) {    
                                                  return $this->$var;     
                                              }  
                                               
                                              private function setVar($var, $value) {    
                                                  $this->$var = $value;
                                                  return $this;
                                              }
                                          	
                                          	public function getId() {
                                                  return $this->id;
                                              }
                                          
                                              public function setId($id) {
                                                  $this->id = $id;
                                                  return $this;
                                              }
                                          }

                                          la raison principale est bien de réduire le code. car j'ai une table comportant 14 colonnes, et devoir faire 14*2 getters/setters est long et pas tres pratique pour s y retrouver.

                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            19 février 2017 à 21:04:45

                                            Bonjour,

                                            J'avance dans mon TP WebLinks, et je butte sur l'exigence suivante dans le cadre des tests effectués avec PHPUnit.

                                            • Tests fonctionnels automatisés des URL de consultation (6 URL à tester).
                                            • L’accès aux URL /link/submit et /admin doit être soumis à la possession par l’utilisateur du rôle adéquat.

                                            Cela fonctionne avec un navigateur, mais comment l'automatiser avec PHPUnit ? Pour pouvoir tester /link/submit/ , l'utilisateur doit être identifié, de même que pour /admin. 

                                            Le tuto fait l'impasse sur cette problématique en invalidant les règles de sécurité pour les tests (MicroCMS/tests/Tests/AppTest.php)

                                            // ligne 41
                                            // Enable anonymous access to admin zone
                                            $app['security.access_rules'] = array();
                                            

                                            Logiquement, il faudrait pouvoir faire 3 séries de tests (anonyme, USER, ADMIN) sur l'ensemble des urls et indiquer celles qui doivent fonctionner pour chacun des rôles, et celle qui ne doivent pas fonctionner. Il faudrait pouvoir faire un AssertTrue (page admin/role admin) et un AssertFalse (page admin / role anonyme ou user).

                                            Quelqu'un a une idée pour éclairer ma lanterne ? o_O

                                            D'avance merci

                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                              20 février 2017 à 16:51:49

                                              Bonjour.

                                              Dblbass, 

                                              Pour l’activé il me semble qu’avec la correction il faut juste que le test passe. Sans vous donner la réponse, l’idée n’est pas d’enregistrer un utilisateur dans le test mais de faire des vérifications dans le code pour permettre au test de ne pas générer d’erreur. Si je me rappelle bien de cette activité vous enregistrez en session un utilisateur et donc nous n’avons pas mis en place ni dans le cours ni dans l’activité de moyen de s’enregistrer via l’API. Je vous parle seulement de l’activité, dans l’absolu il y a de nombreuse façons de tester et de nombreux tests possible. Certains construise les tests avant même de développer, pour répondre à des USE Case (cas d’utilisation) par exemple. Je n’ai pas encore poussé PHPUnit bien qu’il y est un cours OC (je compte d’ailleurs le faire).Donc oui on pourrait imaginer beaucoup de test mais pour l’activité on nous demande seulement certains tests précis.

                                              Mooztik,

                                              J’ai dû mal m’exprimer. Je vais essayer de redonner mon point de vue d’une autre façon.

                                              J’ai vu que vos fonctions sont private, mais je pensais que vous aviez compris l’idée en fait j’aurai dû être plus précis, désolé.

                                              Donc je vous renvoie sur le guide.

                                              Par exemple il est dit :

                                              « Les méthodes magiques de surcharge sont appelées lors de l'interaction avec des propriétés ou des méthodes qui n'ont pas été déclarées ou ne sont pas visibles dans le contexte courant. »

                                              A mon sens, ces Surcharges magiques sont en fait plus mis en place pour gérer les erreurs  et problèmes du genre. Par exemple (j’ai fait le code sur traitement de texte donc vite fait c’est juste pour l’exemple) :

                                              class Personne
                                              {
                                              
                                                  private $_Nom ;
                                              
                                                  public function __get()
                                                  {
                                                      return null;
                                                  }
                                              
                                                  public function getNom()
                                                  {
                                                      return $this->_Nom; 
                                                  }
                                              
                                              }
                                              
                                              $toto = new Personne() ;
                                              
                                              $toto->getNom(); // tout va bien.
                                              
                                              $toto->getPrenom(); // retourne null.

                                              Si je n’avais pas mis en place le __get() ça monte en erreur et le reste ne se fait pas.

                                              Un truc tout bête :

                                              Si je veux des premières lettres de noms en majuscule mais sans modifier quoi que ce soit dans la donnée, je peux imaginer faire :

                                              public function getNom()
                                              {
                                                  return ucfirst($this->_Nom);
                                              }

                                              Au lieu de faire un ucfirst() dans toute mes vues.

                                              J’ai pris un exemple avec __get() qui pourtant serait plus permissif que pour __set() où là je pense l’idée complètement inadapté. Je pense qu’on peut quand même pour des getters massifs imaginer votre méthode même si il y a des outils pour générer des getters et setters notamment via UML ou même voir les outils Symfony2 pour générer les entities.

                                              Pour affiner votre méthodologie, si vous voulez quand même continuer dans ce cap voilà de quoi faire en moins risqué ici

                                              Je vous rappelle qu’avec twig (notamment) vous utiliserez {{ person.nom }}

                                              A voir si c’est bien compatible.


                                              "quand aux contrôles, ils sont sensés être faits en amont (dans le cas du tutoriel, via le FormBuilderInterface)."


                                              Les contrôles dont vous parlez sont des contrôles en php pour ce qu’on peut qualifier de la partie IHM. Si demain j’utilise vos objets avec un autre framework, sans framework, etc… je n’ai pas de contrôles de Type ce qui à mon sens n’est pas correct.

                                              Vous pouvez avoir plus d’un type de « contrôles ». Typiquement il a des contrôles qu’on utilise pour les utilisateurs (du site) des contrôles pour l’utilisateur mais avec objectif de performance (du site) et des contrôles qui sont plus pour les utilisateurs (développeurs) qui vont utiliser vos objets.

                                              Vos type dans un objet doit être Independent de l’interface d’utilisation.

                                              Si vous faites des contrôles pour un formulaire en Javascript par exemple ce n’est qu’un outil de performances/confort et doit être doublé avec des contrôles en php. Au même titre vous ne devais pas normalement pouvoir inscrire un type int dans un paramètre qui attend un bool par exemple. C’est vrai que certaines personnes pour aller plus vite vont mettre ça de côté et aussi beaucoup de développeurs en php ne ce soucis pas forcement du type (votre base de données s’en soucie elle ^^).

                                              Si vous faites un webservice en php objets par exemple, on fait des contrôleurs sur les interfaces qui utilisent le web service pour envoyer des types demandés. Le webservice a lui aussi ses contrôles pour ne pas essayer d’insérer des choses erronées.

                                              J’espère avoir était plus explicite sur mes points de vue,

                                              Bon courage et bonne continuation.



                                              -
                                              Edité par Osush 20 février 2017 à 16:55:00

                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                                20 février 2017 à 17:21:02

                                                Merci Osush pour cet éclairage.

                                                Je vais rendre mon TP avec les 6 tests demandés, en me basant sur ce qui a été décrit pendant le cours.

                                                (mais je pense que le travail n'est fait qu'à moitié, j'ai toujours soutenu que quand on planifie des tests, il faut prendre en compte 3 type d'utilisateurs, le gentil super intelligent qui ne fait jamais d'erreur, le grand distrait qui ne fait remplit pas correctement les champs, et qui correspond à la majorité des utilisateurs, et finalement le méchant qui fera tout pour casser notre site et s'en servir à ses fins personnelles. C'est pour les deux derniers que les batterie de tests sont utiles. Les 6 tests demandés correspondent selon moi au premier profil).

                                                Bonne suite à tout le monde.

                                                • Partager sur Facebook
                                                • Partager sur Twitter
                                                  20 février 2017 à 17:50:16

                                                  Il me semble que ce qui est proposé est plus une présentation des tests fonctionnels. L’idée est plus de mettre en place des tests que l'on pourrait faire nous-même, rapidement de façon automatisé. Ça permet de vérifier qu'après une modification dans l'application nous n'avons pas tout cassé, bien qu'effectivement on doive imaginer et mettre en place un jeu de test complexe. Personnellement je n'ai toujours pas creusé ce côté-là mais effectivement dans le jeu de test faire un test de connexion me semblerait un "must have". Si je touche à l'ajout d'utilisateurs (par exemple) avec le système d'encodage Silex1 ou 2 je peux avoir le risque  de problèmes de connexion alors même que mes tests fonctionnent en l'état.
                                                  Comme il est dit dans le cours : "Quelle que soit la stratégie choisie, l'écriture de tests est une activité chronophage et parfois délicate."

                                                  Votre vision des choses est je pense la bonne. C’est le principe des USE CASE si je ne me trompe. Je vous invite à voir le cours sur UML peut être que vous verrez la possibilité de créer une application autrement, j'irais même jusqu'à dire beaucoup plus proprement.

                                                  Bonne corrections ;)

                                                  -
                                                  Edité par Osush 20 février 2017 à 17:52:19

                                                  • Partager sur Facebook
                                                  • Partager sur Twitter
                                                    21 février 2017 à 11:40:27

                                                    Bonjour!

                                                    Je suis sur l'itération 7 et j'ai quelques questions.

                                                    • Pourquoi dans le diagramme UML de la classe Commentaire il n'y a pas de propriété article alors qu'il y a des méthodes associées (get/set)?
                                                    • Le setters renvoient-ils quelque chose? Alors que dans le diagramme c'est noté void?
                                                    • Qu'est-ce qui permet d'accéder aux propriétés et méthodes de la classe ArticleDAO dans la classe CommentDAO? La classe ArticleDAO n'est pas explicitement déclarée; est-ce grâce à l'autoload?
                                                    • D'où vient la méthode setArtice dans la classe CommentDAO et à quoi ça sert?

                                                    Merci d'avance

                                                    • Partager sur Facebook
                                                    • Partager sur Twitter
                                                      21 février 2017 à 14:35:24

                                                      Bonjour, 

                                                      Alors pour UML c'est vrai que si vous n'avez jamais fait d'UML ça peut ne pas être évidant au premier abord. Pourtant avec quelques notions ça devient vite très explicite.

                                                      Vous voyez le lien avec la classe Article, cela veut dire que un Comment appartient à 1 article seulement mais article peut avoir plusieurs Comment. En d'autre thermes c'est un objet Article dans l’objet Comment que vous avez, d'où le getter et setter dans Comment.

                                                      Dans certains framework ou pour certains besoins, un setter peu renvoyer quelque chose (dans ce cas la non). Quand vous lisez ce diagramme vous pouvez donc savoir que les setters ne vous renverront rien.

                                                      Dans Comment (je vous fais un exemple rapide) :

                                                      <?php
                                                      
                                                      namespace MicroCMS\Domain;
                                                      
                                                      class Comment 
                                                      {
                                                      
                                                          /**
                                                           * Associated article.
                                                           *
                                                           * @var \MicroCMS\Domain\Article
                                                           */
                                                          private $article;
                                                      
                                                      
                                                          public function getArticle() {
                                                              return $this->article;
                                                          }
                                                      
                                                          public function setArticle(Article $article) {
                                                              $this->article = $article;
                                                              return $this;
                                                          }
                                                      }

                                                      pour une classe Comment comme ça,

                                                      $com = new MicroCMS\Domain\Comment();
                                                      
                                                      $com->setArticle($monObjetArt);//Ici c'est bien un Objet Article et pas un tableau.
                                                      
                                                      $com->getArticle()->getId(); // l'id de l'article

                                                      Dans CommentDAO vous avez :

                                                          /**
                                                           * @var \MicroCMS\DAO\ArticleDAO
                                                           */
                                                          private $articleDAO;
                                                      
                                                          public function setArticleDAO(ArticleDAO $articleDAO) {
                                                              $this->articleDAO = $articleDAO;
                                                          }

                                                      Avec ça, vous devez passer un ArticleDAO instancié après vous pouvez faire des fonctions dans la classe CommentDAO avec votre

                                                      $this->articleDAO .


                                                      dans votre app/app.php vous avez :

                                                      // Register services
                                                      $app['dao.article'] = function ($app) {
                                                          return new MicroCMS\DAO\ArticleDAO($app['db']);
                                                      };
                                                      $app['dao.comment'] = function ($app) {
                                                          $commentDAO = new MicroCMS\DAO\CommentDAO($app['db']);
                                                          $commentDAO->setArticleDAO($app['dao.article']);
                                                          return $commentDAO;
                                                      };

                                                      Par rapport au loading, vous avez une façon d'enregistrer les services est un système/protocole/norme PSR4 c'est la norme utilisé dans beaucoup de projets/frameworks (considéré comme une bonne pratique.) qui entre autre permet de faire les chargements de classe avec un système de nommage.

                                                      Exemple : MicroCMS\Domain\Comment est dans le répertoire et s'appelle : /src/Domain/Comment.php

                                                      Donc MicroCMS votre projet dont dans src, Domain correspond à Domain et le non de la classe.

                                                      Je vous invite à voir aussi votre fichier composer :

                                                          "autoload": {
                                                              "psr-4": {"MicroCMS\\": "src"}
                                                          }


                                                      J'espère que je vous ai permis d'y voir un peu plus clair,

                                                      bonne continuation et bon courage.

                                                      -
                                                      Edité par Osush 21 février 2017 à 14:39:24

                                                      • Partager sur Facebook
                                                      • Partager sur Twitter
                                                        22 février 2017 à 11:58:56

                                                        Bonjour!

                                                        Merci d'avoir pris le temps de me répondre.

                                                        J'ai carrément repris cette itération du début à la fin et je crois avoir eu des éléments de réponses à mes préoccupations.

                                                        Je ne pense pas avoir assez de problème pour UML. J'ai quelques heures de ce cours pendant ma formation. A vrai dire il y un petit oubli de la part de l'enseignant pour la propriété article. On peut bien le constater en implémentant cette classe la propriété en question est là avvec les méthodes associées. Si jamais vous utilisez un générateur de code à partir d'un diagramme UML avec le diagramme tel que celui du cours vous n'aurez pas ladite propriété. Et ce propos renforce encore plus

                                                          L'association avec un article se traduit dans le code source par la présence d'une propriété$article. Il ne s'agit pas d'un simple            identifiant de type entier, mais bien d'un objet de la classe Article.

                                                        Pour ce qui est de setter bien que ça puisse dans certains cas comme tu l'as dit renvoyer quelque chose, dans le cas présent il n'y a rien d'important pour utiliser return avec. En plus en s’étalant au digramme qui montre clairement void, je ne vois pas pourquoi on peut utiliser return. Encore une fois si vous utilisez un générateur de code vous aurez un code légèrement différent de ce que nous avons car tout simplement le générateur ne mettra pas return sur le méthode déclarées void.

                                                        C'est bien l'autoload qui permet d'accéder aux classes non déclarée.

                                                        Mais il y a quand même certains points que je n'ai pas très bien compris ou partagé la même façon de faire avec l'enseignant. Je reviendrai à vous si besoin

                                                        • Partager sur Facebook
                                                        • Partager sur Twitter
                                                          26 février 2017 à 23:39:02

                                                          Bonjour tout le monde, j'ai une petite question technique et j'espère que qq pourra me répondre....

                                                          Dans la classe ControllerCollection de Silex, on a ceci:

                                                           public function match($pattern, $to = null)
                                                              {
                                                                  $route = clone $this->defaultRoute;
                                                                  $route->setPath($pattern);
                                                                  $this->controllers[] = $controller = new Controller($route);
                                                                  $route->setDefault('_controller', null === $to ? $this->defaultController : $to);
                                                          
                                                                  return $controller;
                                                              }
                                                          

                                                          $route étant une instance de Silex\\Route.
                                                          Et dans cette classe, on a ceci:

                                                           public function setDefaults(array $defaults)
                                                              {
                                                                  $this->defaults = array();
                                                          
                                                                  return $this->addDefaults($defaults);
                                                              }
                                                          public function addDefaults(array $defaults)
                                                              {
                                                                  foreach ($defaults as $name => $default) {
                                                                      $this->defaults[$name] = $default;
                                                                  }
                                                                  $this->compiled = null;
                                                          
                                                                  return $this;
                                                              }
                                                          


                                                          Donc .... $this->defaults[0] est égal à _controller et $this->defaults[1] est égal à $to non?

                                                          Mais ça m'embête parce que je me dis que ça devrait plutôt être $this->defaults['_controller'] == $to...

                                                          • Partager sur Facebook
                                                          • Partager sur Twitter
                                                            27 février 2017 à 19:14:03

                                                            Bonjour,

                                                            je peut faire erreur mais il me semble que c'est la classe route qui hérite de la classe route symfony2.

                                                            La fonction appelée est setDefault() et non pas setDefaults(). Si je ne me trompe pas par rapport à votre demande, vous avez deux fonctions différentes et donc $this->getDefault('__controller') n'est pas pareil que $this->getDefaults().

                                                            Regardez la fonction sans le "s" dans la classe route Symfony2.

                                                            Extrait :

                                                                public function setDefault($name, $default)
                                                                {
                                                                    $this->defaults[$name] = $default;
                                                                    $this->compiled = null;
                                                            
                                                                    return $this;
                                                                }

                                                            Bon courage.

                                                            -
                                                            Edité par Osush 27 février 2017 à 19:19:26

                                                            • Partager sur Facebook
                                                            • Partager sur Twitter
                                                              27 février 2017 à 19:33:56

                                                              Merci beaucoup, je savais que la classe Route héritait de la classe route symfony2. Et effectivement je n'avais pas fait attention à ce "s" et c'est beaucoup plus clair comme ça merci beaucoup ;-)

                                                              • Partager sur Facebook
                                                              • Partager sur Twitter

                                                              Cours Architecture PHP professionnelle / Questions

                                                              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                                              × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                                              • Editeur
                                                              • Markdown