Code goes in src/ and app/

You may have noticed that most of the committed files were in app/ and src/. That's on purpose: these are the only two directories you need to worry about. src/ will hold all the PHP classes you create and app/ will hold everything else: mostly configuration and template files. Ignore all the other directories for now and just focus on src/ and app/.

Building the First Page

Remember the functional homepage? It's coming from this DefaultController.php file. Delete that! Do it! Now we have an absolutely empty project. Refresh the homepage!

No route found for "GET /"

Perfect! That's Symfony's way of saying "Yo! There's no page here."

Now back to the main event: building a real page.

Our top secret project is called AquaNote: a research database for Aquanauts. These cool underwater explorers log their discoveries of different sea creatures to this nautical site. Our first page will show details about a specific genus, for example, the octopus genus.

Creating a page in Symfony - or any modern framework - is two steps: a route and a controller. The route is a bit of configuration that says what the URL is. The controller is a function that builds that page.

Namespaces

So, step 1: create a route! Actually, we're going to start with step 2: you'll see why. Create a new class in AppBundle/Controller called GenusController. But wait! The namespace box is empty. That's ok, but PhpStorm can help us out a bit more. Hit escape and then right-click on src and select "mark directory as sources root".

Now re-create GenusController. This time it fills in the namespace for me:

18 lines src/AppBundle/Controller/GenusController.php
<?php
namespace AppBundle\Controller;
... lines 4 - 7
class GenusController
{
... lines 10 - 16
}

Go Deeper!

If namespaces are new to you, welcome! Take a break and watch our PHP Namespaces Tutorial.

The most important thing is that the namespace must match the directory structure. If it doesn't, Symfony won't be able to find the class. By setting the sources root, PhpStorm is able to guess the namespace. And that saves us precious time.

Controller and Route

Inside, add a public function showAction():

18 lines src/AppBundle/Controller/GenusController.php
... lines 1 - 7
class GenusController
{
... lines 10 - 12
public function showAction()
{
... line 15
}
}

Hey, this is the controller - the function that will (eventually) build the page - and its name isn't important. To create the route, we'll use annotations: a comment that is parsed as configuration. Start with /** and add @Route. Be sure to let PhpStorm autocomplete that from the FrameworkExtraBundle by hitting tab. This is important: it added a use statement at the top of the class that we need. Finish this by adding "/genus":

18 lines src/AppBundle/Controller/GenusController.php
... lines 1 - 4
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
... lines 6 - 7
class GenusController
{
/**
* @Route("/genus")
*/
public function showAction()
... lines 14 - 16
}

Beautiful, that's the route and the URL for the page is /genus.

Returning a Response

As I already said: the controller is the function right below this, and its job is to build the page. The only rule for a controller is that it must return a Symfony Response object.

But hold on. Let's just all remember what our only job is as web developers: to understand the incoming request and send back a response, whether that's an HTML response, a JSON response of a PDF file. Symfony is modeled around this idea.

Keep things simple: return new Response. The Response class is the one from the HttpFoundation component. Hit tab to auto-complete it. This adds the use statement on top that we need. For the content, how about: 'Under the Sea!':

18 lines src/AppBundle/Controller/GenusController.php
... lines 1 - 5
use Symfony\Component\HttpFoundation\Response;
class GenusController
{
/**
* @Route("/genus")
*/
public function showAction()
{
return new Response('Under the sea!');
}
}

That's it!

We've only created one file with one function, but we already have a route, a controller and a lot of sea floor that needs discovering!

If you refresh the homepage, well... that's not going to work. Navigate instead to the URL: /genus. Woh! There's your first page in Symfony, done in about 10 lines of code. Simple enough for you?

Next, let's create a dynamic URL.

Leave a comment!

  • 2016-09-25 weaverryan

    Hey Mamun!

    I think I know the problem :). Whatever the URL is in your browser - add an app_dev.php to it. For example, if you setup XAMPP to have a URL like http://symfony.l, then go to http://symfony.l/app_dev.php. In fact, while developing, you'll always have that app_dev.php in your URL - e.g. http://symfony.l/app_dev.php/products (instead of just /products).

    Having the app_dev.php in the URL loads Symfony in the "dev" environment, where you see any errors and your cache is always rebuilt. The reason you don't see this in the video is that we're using the built-in PHP web server through Symfony, which does this (automatically & invisibly) for you. But, if you're using your own web server, that's great - you just need to add that app_dev.php to the URL yourself. When you do that, I think you won't see this error anymore. There's more info about this here: http://knpuniversity.com/scree...

    Let me know if that helps!

  • 2016-09-25 Mamun

    After deleting DefaultController.php, I got 500 Internal server error.

    Here is the message": Oops! An Error Occurred

    The server returned a "500 Internal Server Error".

    Something is broken. Please let us know what you were doing when this error occurred. We will fix it as soon as possible. Sorry for any inconvenience caused."

    I'm using widows 10, PHP version: 5.6.24, Symfony 3 . As PHP server I'm using XAMPP.

    What could be the reason for this error?

  • 2016-09-19 weaverryan

    Hey Leon!

    Hmmm. I'm sure we can figure this out! A few questions:

    1) Did you run the bin/console server:run to start the built-in web server? Or did you configure a web server to point to your project?
    2) What is the URL in your browser?
    3) Is the 404 error a "pretty" error that's coming from Symfony, or is it much more plain?

    Let me know and we'll find the problem :).

    Cheers!

  • 2016-09-16 Leon Hitzer

    I Symfony just install and so far everything runs. I followed your video but unfortunately get in the browser the message: The server returned a "404 Not Found".

  • 2016-09-07 Victor Bocharsky

    +1 It makes sense to clear the cache. Also ensure that the "Power Save Mode" is off: "File" -> uncheck "Power Save Mode".

  • 2016-09-07 PlayIt

    I had the same problem, I did two things, I believe the latter fixed it.
    Uninstalled plugin / restart /reinstalled plugin / restart..
    Still didn't work.
    File -> Invalidate Caches / Restart
    Wait for indices to finish building on restart ( takes a min )
    MAGIC.

  • 2016-08-25 Victor Bocharsky

    Hm, I think internal server error is not so bad here. I suppose your server configured properly, you just don't clear prod cache. Symfony recompile cache for changed files by itself in dev mode, but in prod mode you should clear it manually each time you make any changes. So try to clear cache for prod with the next Symfony console command:


    $ bin/console clear:cache --env prod

    Or just manually remove "/path-to-your-symfony-app-root-dir/var/prod" folder, it should help you. Let me know if you still has this error after clearing the prod cache.

    Cheers!

  • 2016-08-23 Kaiser

    Thanks for quick response. :)

    The root directory is now /web.
    When launching the app.php (which correctly is set as directory index i .htaccess) i get the "500 internal..." error. but app_dev.php works fine (though it has the debug bottom bar).

    If I'm running the application without MAMP, but just starting the server through terminal, i get another 500-error stating "An error occurred while loading the web debug toolbar (500: Internal Server Error)"
    This occurs both through app.php and app_dev.php?

    I am pretty new to all serber & system settings as well as managing bigger projects. I was used to just fire up MAMP, and build the directory structure myself without frameworks. So I am not sure at all how to follow the guide "Configuring a Web server" as in where those settings should be applied etc..

  • 2016-08-23 Victor Bocharsky

    Hey Kaiser,

    Yes, you should set the "/web" directory as a document root for Symfony projects.
    Also make the "web/app.php" as a directory index file. This actually set up in "/web/.htaccess" already, but your server could ignore it, depends on server configuration.

    BTW, the correct example of configuring a virtual host for Symfony project you could find here: Configuring a Web Server. There're few examples for both Apache and Nginx web servers.

    Cheers!

  • 2016-08-22 Kaiser

    Hi.
    First of all these tutorials are great! Thank you so much for making them!
    However. I can't seem to get this default routing working.

    I'm on mac El Capitan
    PHPstorm 2016.2
    Symfony 3.1.2

    I've set up MAMP to my projects directory as document root, but when typing localhost:8000 i just get a list of files in th edirectory.
    When typing localhost:8000/web
    or localhost:8000/web/app_dev.php
    it loads the "Welcome to symfony" page.

    Without the defaultController. i get the right result with localhost:8000/web/app_dev.php
    and with localhost:8000/web i get a basic "500 internal server error". ?

  • 2016-08-16 Vlad

    Thank you, Ryan!

  • 2016-08-15 weaverryan

    Yo Vlad!

    There is a proper way to do this - with $this->forward(). But - by design - this creates a sub-request in the system, so there is some performance impact for doing this (you can look in the Performance tab in the Profiler for this page - you'll see exactly what I mean and how much of an impact there is). Otherwise, yes, you could instantiate the controller directly (and call setContainer() on it) - it is just an object, of course. But, there's some risk in this, because certain normal pre-controller hooks won't fire, so you could rely on some functionality there that suddenly doesn't work. The longer, more proper answer is that if you need to call something, you should extract it to a service and call that service.

    But there you go - there's the long answer, because I know you'll find it interesting anyways!

    Cheers!

  • 2016-08-12 Vlad

    If I want to call a controller action inside of another controller, is there a proper way of doing it (via routes, etc.), or do I simply instantiate the target controller and call it's function directly?
    Thanks!

  • 2016-07-16 Luciano Marinho

    Sorry, the error was mine. I'm new in this symfony world. Learning well with this tutorial. Thanks a lot;

  • 2016-07-16 weaverryan

    Hey Luciano!

    Everything should still work just fine in 3.1.2 - what problems are you having? Do you have a "Route Not Found" error? What URL are you going to?

    Cheers!

  • 2016-07-15 Luciano Marinho

    I'm trying this with symfony 3.1.2 but this chapter does not work.....the router not work =(

  • 2016-05-25 weaverryan

    Awesome!

  • 2016-05-25 Mike

    I fixed my problem. I am using Sourcetree to push my changes but it is not updating my remote server. I had to us the CLI to pull my changes

  • 2016-05-24 Mike

    I deleted the DefaultController and it still loads the welcome to symfony page. Why is this? Also, when I create the genus route it says no route found. I'm using a remote server instead of my local pc. The symfony project is located in this directory /var/www/html/my_project

  • 2016-05-02 weaverryan

    Cheers! Yes, bin/console cache-clear --env=prod is your friend for the prod environment :)

  • 2016-05-02 Yoni L.

    Thank you for this great tutorial! just to share I had some trouble with an error 500 with /genus route. That was due to the cache in /app/cache/prod.

  • 2016-04-27 Konrad Zając

    Yes, thanks!

  • 2016-04-27 weaverryan

    Hi Konrad!

    I don't understand your question - can you ask it again? Which folder are you talking about? Are you talking about creating an empty project in PHPStorm? If so, I usually create my project with the Symfony installer. Then, in PHP storm, I go to "File -> Open Directory" and choose the directory that was just created. This "makes" a new project in PHPStorm, using that directory. I hope I answered your question :).

    Cheers!

  • 2016-04-26 Konrad Zając

    Create an empty project or a PHP empty project and load that folder created with the command line?

  • 2016-04-26 weaverryan

    Hi Josh!

    Yea, unfortunately we use "controller" interchangeably to refer to *both* the class, and the individual methods in the class (sometimes the individual methods are sometimes called "actions"). When I say "controller", I am typically referring to the single method that returns the Response object. When I'm talking about the class, I'll usually say "controller class". I can totally see how that can cross some wires :)

    Cheers!

  • 2016-04-26 weaverryan

    I do! Install the "PHP Annotations" plugin for PHPStorm - this gives PHPStorm intelligence about how annotations and use statements work. You'll also start to get awesome auto-complete when you use annotations.

    Cheers!

  • 2016-04-25 Emilien Ramos

    I'm sorry but I don't have the @Route completion ...

    I have the others (Response, ...) and the "use Sensio\Bundle\...\Route" message is highlighted with the note : "Usage of statement use was not found"

    Do you know why ?

  • 2016-04-25 Emilien Ramos

    Thanks ! :)

  • 2016-04-25 Josh Hardman

    Hey weaverryan,

    Thanks for your quick response! Your explanation does help. In my experience the controller has referred to the entire class, which has various methods that handles business logic, along with a display function that passes variables on to the template. In Symfony, is the controller simply the single method associated with the matched route which returns a response object? I'm sure this will all make better sense as I keep working through the videos!

  • 2016-04-24 weaverryan

    Hi Josh!

    It's actually the internal a of Symfony that call showAction. Here's what happens:

    1) the user loads the page - Symfony boots up

    2) Synfony reads the routing info (the @Route annotation) to determine which route matches the current URL

    3) Symfony calls the method associated with the matched route (called the controller) so that we can build the page.

    Does that help? It's a good question - understanding this flow is a crucial step!

    Cheers!

  • 2016-04-24 Josh Hardman

    What is actually calling showAction()?

  • 2016-04-24 weaverryan

    PHPstorm! With the Darcula theme :). We have some other PHPStorm goodies over here: http://knpuniversity.com/scree...

    Cheers!

  • 2016-04-23 Emilien Ramos

    Please what's your IDE ?

  • 2016-03-23 weaverryan

    Oh no! I have seen in rare cases that it doesn't work for *some* people. I would open a support request with PhpStorm to see if they can help. Make sure you're also using the latest version of PhpStorm - that might not make a difference, but it's worth a try.

  • 2016-03-22 utkarsh srivastava

    Hello

    I've added php annotations plugin and restarted phpstorm but it still doesnt prompt the autocomplete. Please help me with this.

  • 2016-01-26 weaverryan

    Yea, thanks for pointing this out! There was at least one other user that also commented (on another chapter) - so I've added a note about this: https://github.com/knpuniversi.... It was an oversight - you *definitely* want this awesome plugin :).

    Thanks!

  • 2016-01-24 Levan Lomia

    omg man thank you. I was struggling abaout that too. just read your comment accidentally

  • 2016-01-24 ZB

    Make sure to also install the PHP Annotations plugin to PHP Storm. I was struggling to make that @Route auto-complete work