Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine
This tutorial has a new version, check it out!

Generating URLs

Video not working?

It looks like your browser may not support the H264 codec. If you're using Linux, try a different browser or try installing the gstreamer0.10-ffmpeg gstreamer0.10-plugins-good packages.

Thanks! This saves us from needing to use Flash or encode videos in multiple formats. And that let's us get back to making more videos :). But as always, please feel free to message us.

We now have two pages: the HTML /genus/{genusName} page and the JSON endpoint. Ok ok, the JSON endpoint isn't really a page, at least not in the traditional sense. But pretend it is for a second. Pretend that we want to link from the HTML page to the JSON endpoint so the user can see it. Yes yes, we're going to do something fancier with JavaScript in a minute, but stay with me: this is important.

In show.html.twig, get rid of all this notes stuff because we're not passing in a notes variable anymore. Instead, near the top, add a new anchor tag. I want to put the URL to the getNotesAction page. Fill this in with /genus/{{ name }}/notes.

Perfect right! Wrong! Ok, only kind of wrong. This will work: you can click the link and go that URL. But this kinda sucks: if I decided that I needed to change the URL for this route, we would need to hunt down and update every link on the site. That's ridiculous.

Instead, routing has a second purpose: the ability to generate the URL to a specific route. But to do that, you need to give the route a unique name. After the URL, add comma and name="genus_show_notes":

... lines 1 - 10
class GenusController extends Controller
{
... lines 13 - 22
/**
* @Route("/genus/{genusName}/notes", name="genus_show_notes")
* @Method("GET")
*/
public function getNotesAction($genusName)
{
... lines 29 - 38
}
}

The name can be anything, but it's usually underscored and lowercased.

The Twig path() Function

To generate a URL in Twig, use the path() function. This has two arguments. The first is the name of the route - genus_show_notes. The second, which is optional, is an associative array. In Twig, an associative array is written using { }, just like JavaScript or JSON. Here, pass in the values for any wildcards that are in the route. This route has {genusName}, so pass it genusName set to the name variable:

... lines 1 - 4
{% block body %}
<h2 class="genus-name">{{ name }}</h2>
<a href="{{ path('genus_show_notes', {'genusName': name}) }}">Json Notes</a>
... lines 9 - 27
{% endblock %}

Ok, go back and refresh! This generates the same URL... so that might seem kind of boring. But if you ever need to change the URL for the route, all the links would automatically update. When you're moving fast to build something amazing, that's huge.

Linking to a JSON endpoint isn't realistic. Let's do what we originally planned: use JavaScript to give us a dynamic frontend.

Leave a comment!

10
Login or Register to join the conversation
Default user avatar
Default user avatar Chuying He | posted 4 years ago

I had a problem with this session too. Wenn I wrote the code(exactly like in video), the web keeping telling me "No route found for GET /../". I resolved it by a little change in show.html.twig:
Orginal: < a href="{{ path('genus_show_notes', {'genusName':name} ) }}">Json Notes

Change to: < a href="{{ path('genus_show_notes', {'genusName':'name'} ) }}">Json Notes

(Add ' ' an name, holp it will help)

Reply

Hey Chuying He

That worked because you passed a string (name) to the route, instead of the variable, I believe your template is missing the "name" variable

Cheers!

Reply
Default user avatar

[thumbs up]

1 Reply
Default user avatar
Default user avatar Oskaras Serelis | posted 4 years ago

Hello, I have problem. When i press link to Json, it shows

No route found for "GET /genussgs/notes" (from "http://localhost:8000/genus/sgs")

404 Not Found - NotFoundHttpException

1 linked Exception:

ResourceNotFoundException » . I am writing - "http://localhost:8000/genus/sgs" , and then I am having -"http://localhost:8000/genussgs/notes". If I not use link -"http://localhost:8000/genus/sgs/notes" it works perfectly.

Reply

Hey Oskaras Serelis!

Hmm... this seems very funny :/. Can you post your @Route code and also the code where you generate the link from your template? Something definitely isn't quite right.... but I'm not sure what yet.

Cheers!

Reply
Default user avatar
Default user avatar Oskaras Serelis | weaverryan | posted 4 years ago

GenusController.php:

namespace AppBundle\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\JsonResponse;

class GenusController extends Controller
{
/**
* @Route ("/genus/{genusName}")
*/

public function GenusController($genusName)
{
return $this->render('genus/show.html.twig',
['name'=>$genusName]);

}

/**
* @Route("/genus/{genusName}/notes", name="genus_show_notes")
* @Method("GET")
*/

public function getNotesAction()
{
$notes = [
['id' => 1, 'username' => 'AquaPelham', 'avatarUri' => '/images/leanna.jpeg', 'note' => 'Octopus asked me a riddle, outsmarted me', 'date' => 'Dec. 10, 2015'],
['id' => 2, 'username' => 'AquaWeaver', 'avatarUri' => '/images/ryan.jpeg', 'note' => 'I counted 8 legs... as they wrapped around me', 'date' => 'Dec. 1, 2015'],
['id' => 3, 'username' => 'AquaPelham', 'avatarUri' => '/images/leanna.jpeg', 'note' => 'Inked!', 'date' => 'Aug. 20, 2015'],
];

$data =[
'notes' => $notes
];

return new JsonResponse($data);
}
}

//*********************************************************************************

show.html.twig:

{% extends 'base.html.twig' %}

{% block title %}Genus {{ name }}{% endblock %}

{% block body %}
<h2 class="genus-name">{{path('genus_show_notes', {'genusName':name}) }}</h2>

JSON notes
<div class="sea-creature-container">
<div class="genus-photo"></div>
<div class="genus-details">
<dl class="genus-details-list">
<dt>Subfamily:</dt>
<dd>Octopodinae</dd>
<dt>Known Species:</dt>
<dd>289</dd>
<dt>Fun Fact:</dt>
<dd>Octopuses can change the color of their body in just three-tenths of a second!</dd>
</dl>
</div>
</div>
<div class="notes-container">
<h2 class="notes-header">Notes</h2>
<div></div>
</div>
<section id="cd-timeline">

</section>
{% endblock %}

Reply

Hey Oskaras Serelis

Look's like you are missing "genusName" parameter in your "getNoteAction" method, change it to this:


/**
* @Route("/genus/{genusName}/notes", name="genus_show_notes")
* @Method("GET")
*/
public function getNotesAction($genusName) {
Reply
Default user avatar
Default user avatar Oskaras Serelis | MolloKhan | posted 4 years ago

No route found for "GET /genusnotes/notes" (from "http://localhost:8000/genus/notes")and when I move my mouse to $genusName shows - "Unused parameter"

Reply
Default user avatar

I found it. Problem was in show.html.twig must be -"
"/genus/{{ name }}/notes">JSON notes".
My mistake was -"
"/genus{{ name }}/notes">JSON notes". Anyway thank you for help.

Reply

Hey Oskaras,

Great catch! Actually, path() Twig function solves such kind of problems very well, you would love to use it further instead of compound URLs manually:
{{ path('genus_show_notes', {'genusName': name}) }}

Cheers!

Reply
Cat in space

"Houston: no signs of life"
Start the conversation!

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": ">=5.5.9",
        "symfony/symfony": "3.1.*", // v3.1.4
        "doctrine/orm": "^2.5", // v2.7.2
        "doctrine/doctrine-bundle": "^1.6", // 1.6.4
        "doctrine/doctrine-cache-bundle": "^1.2", // 1.3.0
        "symfony/swiftmailer-bundle": "^2.3", // v2.3.11
        "symfony/monolog-bundle": "^2.8", // 2.11.1
        "symfony/polyfill-apcu": "^1.0", // v1.2.0
        "sensio/distribution-bundle": "^5.0", // v5.0.22
        "sensio/framework-extra-bundle": "^3.0.2", // v3.0.16
        "incenteev/composer-parameter-handler": "^2.0", // v2.1.2
        "composer/package-versions-deprecated": "^1.11" // 1.11.99
    },
    "require-dev": {
        "sensio/generator-bundle": "^3.0", // v3.0.7
        "symfony/phpunit-bridge": "^3.0" // v3.1.3
    }
}