Bonsoir à tous,

Je suis en train de tester rapidement cakePHP 3, et je me retrouve confronté à un problème de slash que je n'arrive pas à résoudre.

// Model/Entity/Post.php
public function _getUrl() {
    $title = Inflector::slug($this->title);
    return ['action' => 'view', ($this->id.'/'.$title)];
}

//Template/Posts/index.ctp
$this->Html->link(h($post->title), $post->url);

Pour une raison que j'ignore lorsque je debug $post->url aucun problème l'url est comme je souhaite. Mais dès que je la passe dans le link le slash se transforme en %2F.

Une idée ?
Merci de votre aide

11 réponses


Daniel68
Auteur
Réponse acceptée

Je viens de comprendre mon problème.
Dans ma fonction _getUrl j'ai passé les params dans le premier tableau, alors que dans mes routes j'en ai spécifié 2.
Il faut donc mettre dans routes.php:

$routes->connect('/:id/:title', ['controller' => 'Posts', 'action' => 'view', 'id' => '\d+', 'title' => '[a-z\-]+'], [ 'pass' => ['id', 'title']]);
});

A présent tout est ok.
En tout cas merci Lartak pour tout le temps que tu as passé à m'aider.

Bonjour.
Il faut utiliser le routing pour faire la ré-écriture d'url.
De la manière que tu fais, le slash est utilisé comme un caractère lambda et non comme un séparateur dans l'url.

Daniel68
Auteur

Merci pour ta réponse si rapide.
J'utilise le routing pour réécrire mes URL.
Mais la je souhaite pouvoir créer une fonction qui me renvoi l'url en tant qu'entité.
Le problème me semble plutôt venir du link, parce que si dans ma vue je place directement mon array j'ai le même problème.
Il doit y'avoir une option dans le link pour spécifier que je ne souhaite pas la convertion html, mais je ne trouve pas.
A moins que tu veuilles dire que directement dans ma fonction _getURL j'utilise Routter:: ?

Le helper Link, tout comme le helper Url, utilisent le routing, donc, dans ta fonction _getUrl, il faut que tu mettes ceci par exemple :

return ['action' => 'view', 'id' => $this->id, 'slug' => $title];

Puis dans ton routing :

$routes->connect('/post/:id/:slug', ['controller' => 'Posts', 'action' => 'view'], [
    'pass' => ['id', 'slug'], 
    'id' => '[0-9]+', 'slug' => '[a-z\-]+'
]);

Si tu ne fais pas ça, les helpers concernés ne pourront pas interpréter tes url.
Par contre, vu que tu ne mets pas le nom du controller, tu ne pourras pas utiliser en dehors de tes vues du controller Posts.

Daniel68
Auteur

Merci pour ton aide.
Même en fesant cela ça ne marche pas.
Dans routes.php j'ai créé un scope pour repasser les posts en /blog.
Puis dedans j'ai donc connecté ma route comme tu me l'as dit (je l'avais déjà fait avant).
J'ai donc juste modifié ma fonction _getUrl().
Le problème c'est qu'il ne réécrit pas mes urls lorsque je lance la fonction dans ma vue index.ctp
Il retourne : /posts/view?id=1?title=test
Au lieu de : /blog/1/title
Pourtant l'index est bien accessible depuis /blog/

Montres le code du routing correspondant au blog s'il te plaît.

Le problème c'est qu'il ne réécrit pas mes urls lorsque je lance la fonction dans ma vue index.ctp

Ce n'est pas ta fonction _getUrl qui va faire la ré-écriture d'url, mais la méthode Link du Helper Html ou le Helper Url.

Daniel68
Auteur

Merci infiniment pour toute ton aide.
Voici le code de mon fichier routes.php (uniquement pour le blog)

Router::scope('/blog', function($routes) {
   $routes->connect('/category/:category', ['controller' => 'Posts', 'action' => 'index', 'category' => '[a-z\-]+']);
   $routes->connect('/', ['controller' => 'Posts', 'action' => 'index']);
   $routes->connect('/:id/:title', ['controller' => 'Posts', 'action' => 'view'], ['id' => '\d+', 'title' => '[a-z\-]+', 'pass' => ['id', 'title']]);
});

Et si tu remplaces :

'id' => '\d+'

Par :

'id' => '[0-9]+'

?

Daniel68
Auteur

Non ça ne change rien (y'a pas de raison...)

Donc, la sortie de ta fonction _getUrl, c'est bien :

return ['action' => 'view', 'id' => $this->id, 'title' => $title];

?

Daniel68
Auteur

C'est:

public function _getUrl() {
      $title = Inflector::slug($this->title);
      return ['controller' => 'Posts', 'action' => 'view', 'id' => $this->id, 'title' => $title];
}