Utiliser les fonctions de date SQL avec doctrine2 et symfony2

Merci à Florent Viel pour m’avoir refilé le tips (c’est un tueur) !

Grâce à SQL, il est possible de manipuler des dates en utilisant les fonction MONTH(), MINUTE(), etc… plus d’info sur les manipulations de dates en SQL.

Cependant, il est parfois utile de pouvoir les utiliser dans doctrine (par exemple comme dans mon cas en travaillant sur Symfony2 (v2.3 à l’heure où j’écris ce billet)). Avant de pouvoir les utiliser facilement comme dans cet exemple :

$qb = $this->createQueryBuilder('p')
            ->select('count(p) as activity, hour(p.created_at) as hour, dayofweek(p.created_at) as journey')
            ->groupBy('hour, journey');

Il est nécessaire de faire un petit prérequis qui indiquera à doctrine comment utiliser ces fonctions jusqu’à lors inconnues pour lui.

Dans un dossier DQL dans mon bundle (par exemple), créer un fichier Month.php qui renseigne comment parser un format date

<?php

namespace YourApp\YourBundle\DQL;

use Doctrine\ORM\Query\AST\Functions\FunctionNode;
use Doctrine\ORM\Query\Lexer;
use Doctrine\ORM\Query\Parser;
use Doctrine\ORM\Query\SqlWalker;

/**
 * DateFunction ::= "HOUR" "(" ArithmeticPrimary ")"
 */
class Month extends FunctionNode
{
    public $dateExpression;

    public function parse(Parser $parser)
    {
        $parser->match(Lexer::T_IDENTIFIER);
        $parser->match(Lexer::T_OPEN_PARENTHESIS);
        $this->dateExpression = $parser->ArithmeticPrimary();
        $parser->match(Lexer::T_CLOSE_PARENTHESIS);
    }

    public function getSql(SqlWalker $sqlWalker)
    {
        return 'MONTH(' .
            $this->dateExpression->dispatch($sqlWalker) .
        ')';
    }
}

Ensuite, dans le fichier de config config.yml de votre application, rajoutez les différentes fonctions que vous souhaitez utiliser :

doctrine:
    orm:
        entity_managers:
                dql:
                    datetime_functions:
                        date: YourApp\YourBundle\DQL\Date
                        hour: YourApp\YourBundle\DQL\Hour
                        month: YourApp\YourBundle\DQL\Month

A partir de là, vous pourrez utiliser vos fonctions de manipulation de dates comme en SQL.

Associer une photo à un résultat de recherche Google

J’ai essayé il y a peu  l’expérience, par curiosité, d’associer une de mes photos à mon blog dans l’affichage des résultats de Google. Voici la méthode à suivre pour arriver facilement à un résultat de ce type :

Tout d’abord, discutons des avantages que peuvent avoir une image présente sur le coté de votre blog dans les recherches.

Premièrement, c’est l’effet visuel, celui qui attire le regard. Au même titre qu’un référenceur rechercherait à viser les requêtes clés dans ses métas (title, description, url) afin de mettre en gras (entre autres) ces mots clés dans les SERP (pour l’anglais « search engine results page »), l’idée d’avoir avoir photo présente comme dans l’exemple est, selon moi un point fort pour consolider cet effet flash.

Ensuite, Google se dirige de plus en plus vers une gratification des sites transparents. Les sites dits propres, qui respectent ses consignes, se verront de plus en plus bénéficier d’un bon ranking. Afficher clairement à qui appartient un blog / site est pour Google un gage légitime de transparence et de sincérité. Nul doute qu’avec les démarches effectuées pour afficher une photo dans le résultat de recherche google, le placement d’un site/blog sera favorablement ré-évalué. Aussi, cette démarche de transparence est valable pour instaurer une confiance entre l’internaute et le site visé.

Les démarches

Pour obtenir un résultat associé à une photo, vous devez absolument (ou en tout cas au moment où j’écris ce billet) vous munir d’un compte google+. Google+, outil qui risque, selon moi, de devoir être utilisé bien plus souvent à l’avenir dans les démarches SEO. La firme américaine aurait tout intérêt à promouvoir l’activité sur son site dans les moteurs de recherche.

Dans votre profil, il existe un champ « également auteur de :« . C’est ici qu’existe la première entrée, primordiale, pour indiquer à Google un lien entre vous, et votre site/blog.

L’étape suivante consiste à faire le chemin inverse ! Comme pour valider le fait que c’est bien vous qui avez réaliser le site ajouté dans le champ « également auteur de :« , vous devez insérer sur votre site un lien vers votre page Google+.

Dans mon cas :

<a href="https://plus.google.com/115876301207724849311?rel=author">Google+</a>

Pensez à changer l’id du lien par le votre ! L’attribut rel=author en fin d’url de destination indique que vous êtes donc bien l’auteur et que vous souhaitez être identifié comme tel.

Une chose marrante, curieuse, meme si…

C’est un confrère de l’agence axe-net qui indique sur son très chouette blog que Google ne publie pas n’importe quoi comme photo ! Il indique dans un article sur le même sujet, mais en détaillant plus que moi, que Google arrive à détecter s’il s’agit bien d’un visage. En effet, google souhaite une photo de l’auteur, et rien d’autre !

Les résultats

Environ 3 jours après avoir effectué les requêtes, j’ai constaté que j’avais ma photo de publiée aux cotés des résultats liés à ce blog. La réponse de Google est donc très rapide ! Cependant, la photo ne s’affiche pas (encore?) sur tous les résultats sortant dans les résultats.

Et si…

Et si nous pouvions duper Google ? Si j’avais mis dans mon profil Google +, dans le champs « également auteur de :« , l’adresse d’un site hypothétique concurrent d’une part. Et d’autre part pris soin de poster sur sa home (via un message forum, ou un quelconque moyen d’avoir un backlink), un lien vers mon google+ avec le rel=author ? Aurait-il affiché quand même ma photo aux cotés des résultats de hypothétique concurrent ? Nous entrons ici dans le domaine du négativ SEO (même si c’est light, on en conviendra ;)), cependant, je me pose la question…

Et vous ? Ca marche ? En combien de temps ? Des effets notables ?

erreur Neither property « path » nor method « getPath() » nor method « isPath() » exists in … lors de l’installation de Symfony 2.1 RC1

Dès les premières minutes de l’installation, il y a une erreur sur la RC1 de la version Symfony 2.1.

Vous obtenez l’erreur :

Neither property « path » nor method « getPath() » nor method « isPath() » exists in class « Sensio\Bundle\DistributionBundle\Configurator\Step\DoctrineStep »

Il suffit d’aller dans :

Symfony/vendor/sensio/distribution-bundle/Sensio/Bundle/DistributionBundle/Configurator/Form/DoctrineStepType.php

et de commenter la ligne :

->add('path', 'text', array('required' => false))

Et tout revient (étrangement) dans l’ordre.

Résoudre ‘Fatal error: Call to undefined method UserBundle\ Controller\ProfileController::getDoctrine()’ [Symfony2]

Pour résoudre l’erreur :

Il suffit d’ajouter dans le controller en question la fonction suivante :

/**
* Shortcut to return the Doctrine Registry service.
*
* @return Registry
*
* @throws \LogicException If DoctrineBundle is not available
*/
 public function getDoctrine()
 {
    if (!$this->container->has('doctrine')) {
            throw new \LogicException('The DoctrineBundle is not registered in your application.');
 }

    return $this->container->get('doctrine');
 }

ainsi que les Use en haut du controller adéquats.

 

Régler l’erreur ‘Unknown Entity namespace alias […]. 500 Internal Server Error – ORMException’ [Symfony2]

J’ai passé pas mal de temps sur cette erreur. Je me trouvais dans le controller profileController surcharge du FOSUserBundle. Je souhaitais pouvoir récupérer un utilisateur autre que celui qui est connecté grâce à un paramètre d’id.

Par défaut j’ai utilisé :

//dans mon action
$repositoryUser = $this->getDoctrine()
            ->getEntityManager()
            ->getRepository('MonsiteUserBundle:User');

$user = $repositoryUser->findOneById($id);

Et finalement, j’avais l’erreur Unknown Entity namespace alias […]. 500 Internal Server Error – ORMException’ .

La solution était de ne pas indiquer le namespace global du projet, comme ci-dessous.

//dans mon action
$repositoryUser = $this->getDoctrine()
            ->getEntityManager()
            ->getRepository('UserBundle:User');

$user = $repositoryUser->findOneById($id);

Je ne sais pas pourquoi tout agit comme ça, mais en cas ça a résolu mon problème, si quelqu’un à l’explication du pourquoi du comment, je suis preneur.

note : pour utiliser GetDoctrine dans un controller de FOSUserBundle