Starting in Symfony2: Course 3 (2.4+)

UPGRADE! Check out the newest version of this tutorial

Welcome back for part 3 of our Starting in Symfony2 series! In part 3 of this series, we're going to discover even more about Symfony and begin to learn more about how Symfony really works under the hood. Over the next hour or so, we're going to learn what a service is, find out more about the core Symfony services, and create a few of our own. In Doctrine, we'll create some Doctrine associations, including ManyToOne and ManyToMany relationships. We'll also talk about lifecycle callbacks and event listeners. Plus a ton more!

Highlights:

  • Doctrine relations, metadata, and the JoinColumn
  • ManyToMany relationship that's bidirectional, owning versus inverse side and why that matters
  • Loading fixtures with shared data
  • Creating shortcuts with your very own base controller!
  • Doctrine extensions: timestampable, sluggable
  • Ajax: returning Json from a controller, setting the content type and the _format parameter
  • Customizing error pages at the template and controller level
  • Overriding bundle templates
  • Embedding other controllers with Twig's render tag
  • Services! What they are, where to find and use the core services, and a step-by-step on how to create your own. Also, demystifying dependency injection.
  • Creating your very own Twig extension
  • Doctrine lifecycle callbacks and how to create and leverage your own doctrine event listener service

Your Guides

Ryan Weaver Leanna Pelham

Questions? Conversation?

  • 2016-03-17 Shairyar Baig

    Hi Ryan,

    Thanks, you were right as soon as i referenced one property I could see rest of the data as well. I also noticed if I do this inside my User Entity set method of jobSeekerProfile

        public function setJobSeekerProfile(\AppBundle\Entity\JobSeekerProfile $jobSeekerProfile = null)
    {
    $this->jobSeekerProfile = $jobSeekerProfile;
    $jobSeekerProfile->setJobSeekerUser($this);
    return $this;
    }

    I can query the User entity and it fetches the linked profile fields as well in one go and displays them. The profiler does say a single query has been made so thats nice too.

  • 2016-03-14 weaverryan

    Hi Shairyar!

    Ha, *very* good attention to detail to notice this. You're going to *love* the answer I think :).

    This is lazy loading. When you query for the User, it does *not* also query for the Profile. That's for performance - after all, maybe you don't need the Profile on this request. Instead, it creates this "fake" object (a proxy) and puts that on your jobSeekerProfile property. If you dump this, you'll see it's empty (we don't have the profile data yet). But as soon as you reference even *one* property on the profile, a lazy query is made in the background to get the data. That's why it works :). In fact, if you do $user->getJobSeekerProfile->getFirstName() and *then* dump the User object, you should see that suddenly this proxy object has data on it.

    If you want to avoid the second query - because you know you *will* need the profile information, you need to join and select it when you query for the User: https://knpuniversity.com/scre... (of course, this happens in the security layer, so you would need to likely extend your user provider to control this query).

    Cheers!

  • 2016-03-14 Shairyar Baig

    Hi Ryan,

    I am playing around with oneToOne relationship today and need to clear few concepts

    I have 2 entities `User` and `Profile`

    I want the User to be the owing side so when I query for user i want the profile linked with user to get fetched too

    This is my User.orm.yml



    oneToOne:
    jobSeekerProfile:
    targetEntity: AppBundle\Entity\JobSeekerProfile
    inversedBy: jobSeekerUser
    cascade: ["persist"]

    This is my Profile.orm.yml


    oneToOne:
    jobSeekerUser:
    targetEntity: AppBundle\Entity\User
    mappedBy: jobSeekerProfile

    I am able to save all the date just fine using a form so my question is when i query for the user my object looks like this



    object(AppBundle\Entity\User)[783]
    private 'id' => int 57
    private 'password' => string '$2y$13$JJR4wM3Vjlwzbled9NlZFuTUAj/.czmdYCE3czqRi0GJvZoNkXUWa' (length=60)
    private 'roles' =>
    array (size=1)
    0 => string 'ROLE_JOBSEEKER' (length=14)
    private 'isActive' => boolean true
    private 'apiToken' => string '3g9nek0d70owwk4g4o0gss4cog4gwkk' (length=31)
    private 'lastLoginTime' => null
    private 'facebookId' => null
    private 'linkedinId' => null
    private 'jobSeekerProfile' =>
    object(Proxies\__CG__\AppBundle\Entity\JobSeekerProfile)[818]
    public '__initializer__' =>
    object(Closure)[792]
    public '__cloner__' =>
    object(Closure)[793]
    public '__isInitialized__' => boolean false
    private 'id' (AppBundle\Entity\JobSeekerProfile) => int 41
    private 'firstName' (AppBundle\Entity\JobSeekerProfile) => null
    private 'lastName' (AppBundle\Entity\JobSeekerProfile) => null
    private 'age' (AppBundle\Entity\JobSeekerProfile) => null
    private 'country' (AppBundle\Entity\JobSeekerProfile) => null
    private 'city' (AppBundle\Entity\JobSeekerProfile) => null
    private 'address1' (AppBundle\Entity\JobSeekerProfile) => null
    private 'address2' (AppBundle\Entity\JobSeekerProfile) => null
    private 'zipCode' (AppBundle\Entity\JobSeekerProfile) => null
    private 'homeContactNumber' (AppBundle\Entity\JobSeekerProfile) => null
    private 'mobileContactNumber' (AppBundle\Entity\JobSeekerProfile) => null
    private 'jobSeekerUser' (AppBundle\Entity\JobSeekerProfile) =>
    &object(AppBundle\Entity\User)[783]
    private 'gender' (AppBundle\Entity\JobSeekerProfile) => null
    private 'username' => string 'ggg@xuz.com' (length=17)

    notice the firstname, lastname and so on appearing as null, the data in fact does exist and if i do


    $user->getJobSeekerProfile()->getfirstName();

    It gives me the firstname i am looking for, is this normal behaviour of symfony? why is it not displaying that data when i dump the entire object?

  • 2014-09-11 weaverryan

    Hey there!

    Hmm! Well, first, the error is unrelated to loading fixtures. I think there is an error in your code or on some 3rd party library and when you run doctrine:fixtures:load, Symfony is loading and showing you that (unrelated) error.

    In the core of Symfony, there is no UserListener class, which is why I know it's not coming from the core of Symfony. FOSUserBundle *does* have a UserListener, so something may be misconfigured with it if you're using it. Otherwise, check your code. It looks to me like we have a service registered somewhere with a class of UserListener, but that it's missing 1 or more items in the arguments key.

    Cheers!

  • 2014-09-11 squall2501

    when i write php app/console doctrine:fixtures:load show me Catchable Fatal Error: Argument 1 passed to Userlistener::_construct

  • 2014-09-08 weaverryan

    Hi Ricardo!

    This part of your code looks fine. But do you have an `$owner` property? When you run "doctrine:schema:update", it calculates the SQL by looking at the *properties* on your entity (not the getter methods or setter methods). So, make sure you have the following inside `Event`:



    /**
    * @ORM\ManyToOne(targetEntity="Yoda\UserBundle\Entity\User")
    */
    protected $owner;

    These lines here should cause the doctrine:schema:update to notice the new owner_id column. If it still doesn't work, let me know! It's also possible that you already have the owner_id column in your database, which is why Doctrine is not adding it. Check your database to be sure :).

    Cheers!

  • 2014-09-06 ricardo

    please answer the question when I make changes in the organization, doctrine did not detect any change in the command doctrine: schema: update

  • 2014-09-05 ricardo

    i copy paste the same code in entity event but when i write command

    php app/console doctrine:schema:update --dump-sql

    php app/console doctrine:schema:update --force

    never take the atribute owner only show me this message

    ALTER TABLE event CHANGE time time DATETIME NOT NULL

  • 2014-09-05 ricardo

    Strange I have the same code in my entity

    id;

    }

    /**

    * Set name

    *

    * @param string $name

    * @return Event

    */

    public function setName($name)

    {

    $this->name = $name;

    return $this;

    }

    /**

    * Get name

    *

    * @return string

    */

    public function getName()

    {

    return $this->name;

    }

    /**

    * Set time

    *

    * @param \DateTime $time

    * @return Event

    */

    public function setTime($time)

    {

    $this->time = $time;

    return $this;

    }

    /**

    * Get time

    *

    * @return \DateTime

    */

    public function getTime()

    {

    return $this->time;

    }

    /**

    * Set location

    *

    * @param string $location

    * @return Event

    */

    public function setLocation($location)

    {

    $this->location = $location;

    return $this;

    }

    /**

    * Get location

    *

    * @return string

    */

    public function getLocation()

    {

    return $this->location;

    }

    /**

    * Set details

    *

    * @param string $details

    * @return Event

    */

    public function setDetails($details)

    {

    $this->details = $details;

    return $this;

    }

    /**

    * Get details

    *

    * @return string

    */

    public function getDetails()

    {

    return $this->details;

    }

    /**

    *

    * @return User

    */

    public function getOwner()

    {

    return $this->owner;

    }

    /**

    *

    * @param User $owner

    */

    public function setOwner(User $owner)

    {

    $this->owner = $owner;

    }

    }

    but when I write the command php app/console doctrine:schema:update --dump-sql only show me

    ALTER TABLE event CHANGEW time time DATETIME NOT NULL

    not on the new owner attribute, which I can do nothing appears?

  • 2014-07-22 Andrei Velent

    Thank you, Ryan.

    Created a service too)

  • 2014-07-22 weaverryan

    Hey Andrei!

    You can't make changes to associated entities in preUpdate. Your situation makes good sense, but it's just not possible. But, here are 2 alternatives:

    1) I usually create a service lass (e.g. UserManager::banUser) and call it. Inside of that function, I would ban the user and cancel his orders (you could even dispatch a Symfony even from here if you want, though that adds complexity). This is easy. The downside is that if someone bans a user manually (and doesn't call this method), then it doesn't work. But I like how explicit it is.

    2) You *may* (I have never tried it, and it's a bit more advanced) be able to leverage the onFlush event: http://doctrine-orm.readthedoc.... As you can see, it *does* have the ability to persist new changes, though you have to do some special stuff.

    Good luck!

  • 2014-07-20 Andrei Velent

    Is any way to use preUpdate event of User entity to change fields in another one? For example, if user status has changed to banned, all his orders should became cancelled or something like that.

  • 2014-07-08 somecallmetim27

    Thanks for the quick response! These tutorials are really well done in a great many respects. They're wonderfully put together. I'm really looking forward to the updates. :)

  • 2014-07-08 weaverryan

    Hey there!

    We're working on the update for this tutorial right now, but I'm definitely sorry you're having problems. But definitely feel free to push issues here and I'll see if I can help. And regardless, we're already part way through re-recording this episode to be nice and fresh :).

    Cheers!

  • 2014-07-07 somecallmetim27

    These tutorials really do desperately need an update. Not much has changed, but if your brand new to this kind of work, a small change can cause problems that can take hours to figure out. And then, there's an additional problem. When something doesn't work as expected, there's no easy way to know if you've made a mistake or if the trouble is due to a small change in the framework.

    And that can be exceptionally frustrating...

  • 2014-07-03 somecallmetim27

    Thanks so much for sharing that!!! Very helpful.

  • 2014-06-27 weaverryan

    Hey there!

    Yep, it's still relevant :) - there aren't many big feature changes between Symfony versions. You will encounter some small differences, but nothing huge. We're also going to update this episode starting next week, so the updated version will be available a few weeks after (and if you already own this version, you will be automatically updated to the new version when it comes out).

    Hope that helps!

  • 2014-06-26 somecallmetim27

    Is this tutorial still relevant? If I'm using 2.5, is this useful/helpful?

  • 2014-06-09 weaverryan

    It's actually a change that's special *only* to the include and require tags. Both originally used {%, but then someone thought, isn't an "include" or a "render" something that should just be "echo'd"? So, for example, {{ render(...) }} just makes more sense: render this controller, and then echo it (e.g. {{ }}). It's a cosmetic change, but {{ }} is newer for include and render :).

    Cheers!

  • 2014-06-09 Dizzy Bryan High

    Symfony 2.4

    I'm not able to register my report controller,
    I do have the following in Base5\EventBundle\DependencyInjection\Base5EventExtension

    public function load(array $configs, ContainerBuilder $container)

    {

    $configuration = new Configuration();

    $config = $this->processConfiguration($configuration, $configs);

    $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));

    $loader->load('services.yml');

    }

    }

    though symfony wasnt poicking this up so i manually added - { resource: "@EventBundle/Resources/config/services.yml" } to config.yml and this does register it, any ideas why the other way does not work?

  • 2014-06-09 Dizzy Bryan High

    I'm using {%, I was under the impression that logical code uses {% and "Saying something used {{, so the {% has changed to {?

  • 2014-06-08 weaverryan

    Awesome! Do you actually have {% or do you have {{? The {% is the old syntax (but still works) and the {{ is the new syntax. And overall, one tricky part with all of this is that debugging error templates is tough: you're already in Symfony's "an error happened, I'm trying to rescue you" part of the system. So, if you have yet another error, the message will likely be not nearly as helpful as it normally is :).

    Cheers!

  • 2014-06-08 Dizzy Bryan High

    in error404.html i was using:
    {% render controller('EventBundle:Event:_upcomingEvents' %}
    I took that from keefekwan's post from below, not sure if its a symfony2.4 specific but render needs to have its own parenthesis.
    i changed it too:
    {% render(controller('EventBundle:Event:_upcomingEvents')) %}

    and is working now :)

  • 2014-06-08 Dizzy Bryan High

    Hi thanks for looking into this.

    I'm getting the same error message and stack trace the only difference is that, when i use: $debug = false in In the ExceptionController.
    I don't get the Symfony debug bar at the bottom of the page.

    Th error is saying it cant find a route for /foo, but rather than rendering the actual template, its supplying me with the error message.

    When i view a url such as http://s2.events.local/web/app.php/thispagedoesnotexist

    I also get a route does not exist error, not the nice 404 page.

    Now whats interesting is that I temporarily broke the edit event controller. if i goto: http://s2.events.local/web/app_dev.php/3/edit

    With debug = false, i do get the generic "Ahh crap! the servers are on fire!!!" message instead of the error code, and the symfony2 debug bar.

    So the concept is working, just not for 404 errors

    Am i right in thinking that symfony automatically detects a route does not exist, and then generates the 404, I'm thinking that there's some problem within my 404 template, that's displaying the upcoming events.

    If i remove the {% render controller('EventBundle:Event:_upcomingEvents' %} from the error404.html.twig it all works, so i will check what i did wrong for adding events to the 404 page!

  • 2014-06-08 weaverryan

    Cheers - you're keeping me on my toes too :)

  • 2014-06-08 Dizzy Bryan High

    I actually like the trip ups, makes me dig around to see what could be wrong, and understand how its all working, keeps me on my toes!

  • 2014-06-07 weaverryan

    Hey!

    You're right - this is just caused by the same issue as below :). If we add ^/regsiter to access_control, then it should pass. The 302 is being caused (as you probably guessed) by us being redirected to the login page.

    If you see any other issues, let me know!

    Thanks again!

  • 2014-06-07 weaverryan

    Hey!

    Don't worry about the Symfony version - the tutorial uses 2.1 at this time (updating soon), but with some added notes in the few spots where 2.2 is different :). But, about your issue, I *do* see the same behavior as you. And actually, we don't really use the registration page after episode 2 (which is why I didn't see it), but this is a bug introduced at the end of episode 2 (http://knpuniversity.com/scree.... When we change the access_control to require login on all pages, we need to also add an entry for ^/register that requires IS_AUTHENTICATED_ANONYMOUSLY (just like the ^/login line). Without this, the bottom access_control matches, which requires you to be logged in.

    We're updating episode 2 right now, so I'll make sure we fix that! I've created an issue on it (https://github.com/knpuniversi....

    Sorry for tripping you up - but thanks for posting about it :).

    Cheers!

  • 2014-06-07 weaverryan

    Hey there!

    Hmm. So, what you're describing sounds like the big, beautiful developer exception message that you receive when you're in dev mode (e.g. app_dev.php). When we add $debug = false to Symfony's core ExceptionController, we're temporarily changing things so that even though we're in dev mode, we see the production, boring user-facing "error" template. So, obviously, this isn't happening for you for some reason. I *did* just pull down the code and try this (specifically, I used the "start" of the project, added $debug = false to ExceptionController::findTemplate and then went to /foo), and I *do* see the boring, user-facing error template.

    So, take another look and let me know what you find :).

    Cheers!

  • 2014-06-07 weaverryan

    Cheers - when we're done updating *all* of the tutorials to the latest version, this should be even smoother :)!

  • 2014-06-07 Dizzy Bryan High

    Hello again!

    Just after creating the _events.html.twig and adding the debug=false to the exception controller

    (video position: 49.21)

    I am getting a route not found error for /foo

    [2/2] NotFoundHttpException: No route found for "GET /foo"

    [1/2] ResourceNotFoundException:

  • 2014-06-06 Dizzy Bryan High

    I've reset back to the start folder, and checked the url again
    when i goto http://s2.events.local/web/app_dev.php/register
    It still redirects me to the login page

    I've done a router:debug and the /register route is listed:
    user_register ANY /register

    I tried downloading the master branch directly from git-hub and i still have the same issue.

    What i noticed when running: php composer.phar install
    is that the entry for Symfony is as follows:
    Installing symfony/symfony (2.1.x-dev f10364a)
    Cloning f10364a07e037a021e77fb92566bb06fa42df34b

    Is there a different set of source files for Symfony 2.2,
    i cant find one on git and the download on this page the composer.json also seems to use 2.1

  • 2014-06-05 Dizzy Bryan High

    Hi i restarted this using the start folder, but i run into a problem when doing the unit tests:

    Time: 1.45 seconds, Memory: 16.00Mb

    There was 1 failure:

    1) Yoda\UserBundle\Tests\Controller\RegisterControllerTest::testIndex

    Failed asserting that 302 matches expected 200.

    D:\Ampps\www\s2.events.local\src\Yoda\UserBundle\Tests\Controller\RegisterControl

    lerTest.php:24
    FAILURES!

    Tests: 1, Assertions: 1, Failures: 1.

    if i try to visit the register page directly in the browser i get redirected tot the login page.

    i have this annotation on my register controller:
    /**
    * @Route("/register", name="user_register")
    * @Template
    */

  • 2014-06-05 Guest

    Ignore this for now, i'm reatarting the tutorial from the start files in the download (I've just downloaded the latest from the link on this page)

    I've run "composer.phar install" (which i guess means i'm now using symfony 2.2 and not 2,4)
    Ive also created my parameters.yml to use my db conn, so will try this from your start point and see how i get on, wish me luck!

  • 2014-06-04 Guest

    The command: php app/console assetic:dump --env=prod --no-debug
    does not copy any files.
    I think i probably don't have the right resource files in the right directories,

    I didn't actually start from the start directory structure supplied with the tutorial, i just continued my existing code from lesson2, maybe this is the problem and i don't have the right files in place, i did try copying css files from the finish directory, but the assestic command still does not match the results in the video.

  • 2014-06-04 Dizzy Bryan High

    excellent resource for git, thanks i will delve into this deeper.

  • 2014-06-04 weaverryan

    Ah, you know what the issue is? I just remembered, we run "git grep" from *inside* the Symfony directory (e.g. vendor/symfony/symfony) - you can see this around 1:25 in the video. So we're not searching in *our* repository, we're searching in Symfony's repository.

    However, this will only work if Composer downloads Composer via git (it has the ability to clone the repository via git or download a tar file and unzip it) - I think it may have downloaded the tar file in your case (which is totally fine, but would explain why your git grep wasn't finding anything). I'll update my issue on it.

    About git - try this guy out - it may help, and it's at least really fun: http://try.github.com/

    Cheers!

  • 2014-06-02 Dizzy Bryan High

    Hi there thanks for your reply.
    Iv'e managed to get it working, for the first time git grep was used, i couldnt get it to work so i just followed what changes to be made from the video.

    Though on the second time its used: git grep "An Error Occurred"
    I was still not getting results so i posted here.

    I've got it working now, the problem seemed to be that the vendor directory was in the .gitignore file, so the whole vendor directory was not getting committed hence the not finding "An Error Occurred"

    I did get a tonne of warnings about errors in code, mainly variables and methods not defined, when adding and committing the directory, but i just did the commit anyway. and now the git grep "An Error Occurred" returns results!

    A screencast on Git would be great, version control is totally new to me and i don't really understand its power, it seems its a must have skill for developers.

  • 2014-05-31 weaverryan

    Hey again!

    No worries - if you have a question, other people probably do too :). So, you're right that you need to have things committed in order for "git grep" to work, so that's a good step. We should be sure that you've committed everything before running this, so I've added an issue to add a note about that - https://github.com/knpuniversi....

    Oh, and I don't think `git --add-all` works - but you probably actually typed something more like `git add --all .` - I just wanted to clarify that for any future person.

    Now, the title of the terminal window is unrelated - sometimes when you run a command, it'll change the title of the windows. I must've just been messing with "less" at some point before doing this - but nothing that's affecting anything here :).

    So, you *should* be seeing results when you run:

    git grep event_show

    If you're not: A) double check to make sure everything is committed and B) try something even more basic, like:

    git grep php

    You should see *a lot* of results from that :).

    Cheers!

  • 2014-05-31 weaverryan

    Hey there!

    Hmm, so jQuery is in the base template in the code (https://github.com/knpuniversi..., but it's totally possible that it's there, but somehow snuck in (i.e. that detail wasn't included in the video). I opened up an issue so that we'll make sure it's included when we update the video :) (https://github.com/knpuniversi.... The same is true with the jquery.blockUI.js file. Thanks for the message!

    Cheers!

  • 2014-05-31 Dizzy Bryan High

    Hi there, sorry for all these posts, feel free to get rid of them if they are not wanted!

    I can't seem to get grip grep to work, it just returns nothing "a blank line"

    i admit i have never used git before so am in at the deep end, maybe its a good idea for a screencast?

    I've done:
    git --add-all .
    git --commit -m "commited by dizzy"

    but grep still returns nothing

    I have noticed in the video the tab name where the grep commands are typed is titled less

    Is this command done from within phpstorm's terminal window or some other process?

    is the "less" tab the same as the less compiler or something else?

  • 2014-05-31 Dizzy Bryan High

    hi there, something not in the video or docs is that the jQuery script is not actually in the base.html.twig template so i had to add that to the javascripts block:

    <script type="text/javascript" src="//code.jquery.com/jquery-1.11.0...."></script>

    the refreshing was a silly coding error on my part, i had missed out the . for the class on the click function so the actual jQuery was not being assigned to the click.

    growlUI, generates an undefined error

    i just noticed there's a js file in the completed folder called blockui.js but don't see it included on any of the twig files.

  • 2014-05-30 weaverryan

    Hey!

    We do just get it working first (without AJAX), which includes a full page refresh and a redirect. But after this section: http://knpuniversity.com/scree... - it should work without a full page refresh. If the JavaScript were broken and so it did a full page refresh, you should be seeing a JSON response at this point from the controller. So let me know what you're seeing - probably something minor :).

    Cheers!

  • 2014-05-30 Dizzy Bryan High

    Hi there, i might be missing something here, After adding the Ajax, the page still does a full refresh, is this whats intended? i thought the point in using ajax would be to update the db with the attendee/unattend and display the message without a full page refresh?.

    Or is the tutorial simply showing how to get the data via json??

  • 2014-05-29 Dizzy Bryan High

    yep that fixes it, thanks, knew it had to be something simples!

  • 2014-05-29 weaverryan

    Hey there!

    I think the problem is that you're not logged in - so $this->getUser() is returning null instead of *your* use object. If you login, it should go away. And really, we would need to make sure that this controller requires you to be logged in - e.g. we should check for the IS_AUTHENTICATED_REMEMBERED role. We don't have that check in the tutorial, but I'll create a ticket to add it in the future. The good news is that you're not doing anything wrong - just need to login!

    Let me know if that fixes it!

  • 2014-05-29 Dizzy Bryan High

    hi there I've run into a problem and cant work out whats wrong.

    I get the following error on attend.json:

    ContextErrorException: Catchable Fatal Error: Argument 1 passed to Base5\EventBundle\Entity\Event::hasAttendee() must be an instance of Base5\UserBundle\Entity\User, null given, called in D:\Ampps\www\s2.starwarsevents.local\src\Base5\EventBundle\Controller\EventController.php on line 241 and defined in D:\Ampps\www\s2.starwarsevents.local\src\Base5\EventBundle\Entity\Event.php line 278

    some things i've noticed phpStorm reports that "add and "contains" is not found in class

    /**
    * @param \Base5\UserBundle\Entity\User $user
    * @return bool
    */
    public function hasAttendee(User $user)
    {
    return $this->getAttendees()->contains($user);
    }

    if(!$event->hasAttendee($this->getUser())){
    $event->getAttendees()->add($this->getUser());
    }

    i think this is where the problem lies the add is not adding the user hence its null

    any ideas i'm using symfony 2.4

  • 2014-05-27 weaverryan

    Small, but I appreciate it! We'll get that right when we update the video (should be June).

    Thanks!

  • 2014-05-27 Dizzy Bryan High

    someone might have pointed this out before,
    in the video where you set the order for loading the fixtures, you don't actually set the EventBundle to 20, its just copy and pasted (though it is mentioned in Leannes voice over, so not a biggy)

  • 2014-05-19 weaverryan

    Ha, great! And thank you very much :)

  • 2014-05-19 Jonny

    Ignore this, I'd forgotten to add the service, certain I had but alas I'd not add the prePersist service tag. Cheers great tutorials by the way.

  • 2014-05-19 Jonny

    Integrity constraint violation: 1048 Column 'password' cannot be null'

    When add the $this->setPassword(null); to setPlainPassword I get the the above error.

  • 2014-05-05 weaverryan

    Hey!

    Yes, I can repeat this. So, there are 2 interesting things:

    A) In the update of this screencast, we're going to remove the `cascade={"remove"}`. It was originally explained incorrectly and isn't actually the behavior we want. Se https://github.com/knpuniversi.... Basically, saying this on the $owner property says "when this event is deleted, delete the user". That's obviously not a good thing.

    B) With the cascade, when you delete the event, it deletes the user. But since you're logged in as this user, on the next request, Symfony tries to get information about the currently-logged-in user (which you just deleted). This causes the error. If you look at the stack trace for the error, it's coming from a class called ContextListener, which is responsible for "refreshing" the User entity on each request in the security system.

    So, that's a fun error to hit as it touches on some interesting topics! But we'll definitely remove that cascade in the future.

    Thanks!

  • 2014-05-03 Guest

    Weird, after going through this a few times, I just noticed that the Delete option in Edit mode no longer works when using (cascade={"remove"}), and (onDelete="CASCADE") for the $owner annotations in Event.php. I get the following error:

    The identifier id is missing for a query of KK\UserBundle\Entity\User

    When I remove the cascade={"remove"} and the @ORM\JoinColumn(onDelete="CASCADE") lines from the $owner annotations, the delete function works.

    After checking the db, the user is indeed deleted along with all of the events instead of just the selected event. Any idea what's causing this?

  • 2014-04-13 Guest

    One more instance of missing a '=' in the public function getRecentlyUpdatedReport(), opened a pull request as well as your recommendation on the type hinting for the deprecation of getRequest().

  • 2014-04-12 weaverryan

    Pull request for this one merged too - good typo catch :).

    Cheers!

  • 2014-04-12 weaverryan

    Pull request merged - thanks!

  • 2014-04-12 Guest

    Missing an '=' for public function updatedEventAction() in the ReportController, also made a pull request for this.

    $rows[] = implode(',', $data);

  • 2014-04-12 Guest

    If using Symfony 2.4 as I am you'll get an error in this code:
    {# app/Resources/TwigBundle/views/Exception/error404.html.twig #}
    {# ... #}

    {% block body %}
    {# ... #}

    <section class="events">
    {% render 'EventBundle:Event:_upcomingEvents' %}
    </section>
    {% endblock %}

    Using {% render controller('EventBundle:Event:_upcomingEvents' %} works perfectly. Already submitted a pull request among others.

  • 2014-03-24 John

    Ha! That was indeed the issue. Thanks for spotting that Ryan.

  • 2014-03-24 weaverryan

    Hey John!

    I've just sent a PR with the fix: https://github.com/JohnRCrawfo...

    It was just a simple indentation problem. It's always in the small details - I missed it myself when I looked at your original config!

    Cheers!

  • 2014-03-20 John

    Hi Ryan, I removed the annotations (I actually didn't originally have them there in the first place... I just put them there as I thought it was really needed). I also double checked that I had the sluggable listener activated, and it is (https://github.com/JohnRCrawfo... ) However when I try and run my fixture (https://github.com/JohnRCrawfo... ) I still get this error: http://pastebin.com/diYiA296

  • 2014-03-20 weaverryan

    Hey John!

    Hmm, it looks good to me - I was checking it against the gedmo docs: https://github.com/l3pp4rd/Doc....

    But, remove the annotations in your entity so they don't confuse things. Also, double-check to make sure you have the sluggable listener activated (https://github.com/stof/StofDo.... The null slug in the fixtures definitely means that the slug behavior just isn't working at all.

    Let me know if these 2 things above work or not and we'll go from there!

    Cheers!

  • 2014-03-19 John

    I've just tried to use the slug, but instead of using Annotations (which I don't really like as I see them more as comments than code) I've used Yaml to create my entity. The only issue is that the slug fields are always null when I try and run my fixtures.

    Currently this is what my entity looks like: https://github.com/JohnRCrawfo... and the Yaml config for it is: https://github.com/JohnRCrawfo...

    Am I missing something?

  • 2014-02-12 weaverryan

    Hey lennondtps!

    Yes, you're right - thanks for the report! I've fixed it at https://github.com/knpuniversi... (and it's correct in the video).

    Cheers!

  • 2014-02-11 lennondtps

    Hello, I think that you have a typo here

    // src/Yoda/EventBundle/Entity/Event.php
    // ...

    use Doctrine\Common\Collections\ArrayCollection;

    public function __construct()
    {
    $this->events = new ArrayCollection();
    }

    ----------------------------
    $this->attendees = new ArrayCollection(); is the correct right?

  • 2014-01-21 weaverryan

    Hi Thomas!

    Actually, the desired behavior is simply that if an Event or User is deleted, all entries in the join table are deleted. It may actually happen that way *without* specifying joinColumns and inverseJoinColumns, I don't remember exactly :). About testing this, it's interesting :). It's not a functional test, which is usually a test where you fake a browser and click things. It's also not a unit test, where you test how a function works, but "mock" out any real-world dependencies (meaning, you test, but "fake" the database). Something like this is often called an integration test: it looks and smells like a unit test, but instead of "mocking dependencies" (something you'll learn as you get into those more), you use the real database connection. I'd worry about getting functional tests first, then unit tests, then these integration tests.

    And yes, if you want to do some testing, that would be very helpful! But again, we're actually looking to see that if we delete the User, any user_event entries (the join table) for that user are gone. The same thing should happen if you delete an Event. The intended behavior was *not* that if we delete an Event, it deletes the User. If that's happening, we'll want to tweak the code a little bit here. Mostly, I wanted to show people these joinColumns and inverseJoinColumns.

    Thanks!

  • 2014-01-21 Thomas

    I was having a hell of a time figuring out why render wouldn't work. this new syntax worked like a charm. And clearing the cache because i forgot I was in the prod environment.

    with IIS it makes things more difficult because short circuiting the exception function to trick it into thinking we're in prod didn't seem to work. I have to use the URL rewrite module in IIS and just change it to app.php or app_dev.php as needed. and remember to clear the cache. The command doesn't seem to work too well either, i just go and select all in app/cache/prod and delete. It's just quicker. I don't really want to spend too much time figuring out why the command doesn't seem to work right.

    I am only using IIS because my client has a windows server so I am forced to, or else I would be on ubuntu or something similar using apache or nginx. I am finding some gotchas with the code and configurations so I am glad more good is coming out of my frustration :)

  • 2014-01-21 Thomas

    Sorry, that annotation was supposed to be both CASCADE like in the video.

    Yes this one does seem to work. I need to write a functional (or unit? (one thing I hope to gain from these is being able to test well. I purchased the behat/mink tutorial too) test to see if deleting the user deletes the events (the desired result, right?)

    I did some research and apparently MS SQL takes the super safe approach and doesnt allow cyclical relations with both CASCADE whereas other SQL products ignore the possible issue and let the user deal with it, in effect.

    I can do some more testing and let you know! it will give me good practice in testing. I basically just have to delete the user and make sure that the event that he created is gone too. if so then the cascading works. right ? :)

  • 2014-01-21 weaverryan

    Hey Thomas!

    I've got a question/answer over to you about the User->Member thing on episode 2, but it shouldn't be an issue. And what's nice, even if you *do* need to change the name of your table, you can do it without renaming the entity.

    About the error here, it's new to me! It looks like you need to be a bit more careful with your CASCADE paths in MSSQL (I don't happen to use this, but we do want code that works on it).

    Did the above change (with NO ACTION) fix things for you or is this still an issue? I don't have access to MSSQL, but if you have a working version, we can tweak things or add a note.

    Thanks!

  • 2014-01-21 Thomas


    /**
    * @ORM\ManyToMany(targetEntity="Yoda\UserBundle\Entity\Member")
    * @ORM\JoinTable(
    * joinColumns={@ORM\JoinColumn(onDelete="CASCADE")},
    * inverseJoinColumns={@ORM\JoinColumn(onDelete="NO ACTION")}
    * )
    **/

    This does not work on MSSQL Server 2012. I get

    Introducing FOREIGN KEY constraint 'FK_427D8D2A7597D3FE' on table 'event_member' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints."

    Note: I am using "member" instead of "user" for the "user" table because when I tried to create that entity it says that user is a reserved word.

  • 2013-12-17 weaverryan

    Hey frimousse!

    No problem at all :). You can also always open up an issue on our GitHub (https://github.com/knpuniversi..., even if you think it might be your fault ;).

    Cheers!

  • 2013-12-17 frimousse

    Hi, I did everyhting as in the video and after dropping the schema, creating the schema, running the fixtures again and querying the table, the slugs do not appear. Where should I look to see the source of the problem? (I obviously already looked into Event and config.yml since those were the two files modified to accept the slugs. Sorry my mistake! Everything works fine now. If I could I would have deleted this post but there is no such option.

  • 2013-09-17 weaverryan

    Hi Enkhbilguun E.!

    I've already updated the script on the website! Check it out here: http://knpuniversity.com/scree.... With that update, everything should be good - this was a very small detail that we mentioned anyways and doesn't affect anything else :).

    Thanks!

  • 2013-09-17 Enkhbilguun E.

    Hi Ryan,

    When would you release updated?

  • 2013-09-16 weaverryan

    Hi dpfkg!

    Actually, you're right - I just re-checked and the explanation about the "cascade={"remove"}" part was reversed. In other words, because the cascade is on the Event, it means that deleting the Event will delete the User. That's actually not the behavior we want, so we'll fix that in an upcoming update. But I have changed that paragraph to accurately explain how the cascade works - see https://github.com/knpuniversi...

    Thanks for pointing that out!

  • 2013-09-15 dpfkg

    I'm a bit confused about the cascade operation. Doesn't "cascade={"remove"}" on the Event side mean, that deleting the Event will remove the User as well?

    Over here http://docs.doctrine-project.o... the example is using "cascade={"remove"}" on the User side.

  • 2013-08-29 Tapan Kumar Thapa

    Hello Weaverryan,

    Today i have checked the "Defination of Moar" and found it is same as More..So please forgive me for this.

    Thanks

  • 2013-08-28 weaverryan

    Thanks Tapan Kumar Thapa! I've fixed it over at https://github.com/knpuniversi...

    Cheers!

  • 2013-08-28 Tapan Kumar Thapa

    I think under "table overview" name of

    Moar Security should be More Security

  • 2013-08-05 weaverryan

    Thanks Nate! And actually, render is now a function (the tag still exists, but the render function is more "preferred"), in part because it just makes more "sense". Render returns a string, so we echo it:

    {{ render(controller('EventBundle:Event:_upcomingEvents')) }}

    Anyways, thanks for the comments!

  • 2013-08-02 Nate Evans

    The syntax for the Twig render function is a bit different in Symfony 2.3


    {% render(controller('EventBundle:Event:_upcomingEvents')) %}
  • 2013-08-01 Nate

    sorry.... Disqus formatting fail...

    here's the code:

    <a href="{{ path('event_unattend', {'id': entity.id}) }}" class="attend-toggle" {{ entity.hasAttendee(app.user) ? '' : ' style="display: none"' }}>
    Oh no! I can't go anymore!
    </a>

    <a href="{{ path('event_attend', {'id': entity.id}) }}" class="attend-toggle" {{ entity.hasAttendee(app.user) ? ' style="display: none"' : '' }}>
    I totally want to go!
    </a>

  • 2013-08-01 Nate

    The style for toggling visibility of the attend links was a bit screwy for me in this example.

    Setting the visibility via the 'hidden' class wasn't workable because jQuery show/hide adds and removes a 'display: none' style. In the example, after clicking the link, the other sibling would not be displayed.

    I modified the twig on the link tags to this and it worked just right:




    Oh no! I can't go anymore!



    I totally want to go!


    Other than that, awesome tuts!

  • 2013-06-20 weaverryan

    Hi Simon Cossar!

    Ah, I'm really glad you like the new format! You're not missing anything - we're still working on updating episodes 3 and 4 to the new format. We hope to be finished with at least episode 3 by next week.

    Thanks!

  • 2013-06-19 Simon Cossar

    I really liked the format of the first two Symfony videos, where you
    have the code and the commentary online underneath each of the video
    segments. Is there anything like that for parts 3 and 4? I've been
    looking everywhere, but maybe I'm missing something obvious.

  • 2013-05-13 weaverryan

    Hi Andrey!

    We're in the process of updating the screencasts for Symfony 2.2 (we're done with episodes 1 and 2 already!). Like you mentioned, for now, we're just updating the code, script and adding notes in videos to point out where things are a bit different - because not too much has changed fortunately. We'll update this episode sometime within the next month (with some new features too, like in-browser video playing and an online-viewable script with code blocks to make finding things easier).

    In the mean time, here's the trick! Before Symfony 2.2, the error controller was just a normal controller (no constructor arguments) that used the `FrameworkBundle:Exception:show` syntax.

    But in Symfony 2.2, it's now a service and has - as you saw - a constructor argument. So, here's what you'll need to do now:

    1) Override the class just as before

    2) Register your controller as a service. This works just like registering any other service. Make sure your service takes a single argument, which is the "twig" service (or, even better, you can set the "parent" of your service to "twig.controller.exception", which is the service for the normal error controller: http://symfony.com/doc/current...

    3) Set the twig.exception_controller setting just like before, except now use the "controller as a service" syntax: http://symfony.com/doc/current.... For example, assuming your new service is called "main.error_controller", then you'd have:

    twig:
    exception_controller: main.error_controller:showAction

    I hope that helps - and thanks for your support!

    Cheers!

  • 2013-05-10 Andrey

    Check out the Episode 2 - Ryan actually discusses every single detail about security - while implementing the UserBundle.

    There is nothing more you need to know - it's very informative.

  • 2013-05-10 Andrey

    The part "Customizing error pages at the template and controller level" seems to be outdated in everything that is describing overriding ExceptionController class, since there seem to be a Twig_Environment in constructor now:

    http://api.symfony.com/2.2/Sym...

    I know it's sh*tload of work, and I really appreciate everything you do!!! But would it be possible to update this part, if only in code - not video - that would be awesome!!!

    Thank you in advance!

    Another happy student/customer, Andrey.

  • 2013-01-12 weaverryan

    Hi Almog!

    Yes, dependency injection *is* a fancy term isn't it? :). That's the standard term you hear most, at least around the Symfony world for the idea of injecting one dependency into another. I think the idea is fundamental enough that you can call it by many names. "Dependency Injection" is the most common around Symfony2, but I also think it's a rather *scary* sounding term for a nice, simple concept.

    Anyways, glad you got un-confused, and thanks for your comment!

  • 2013-01-12 Almog Baku

    Hey!,
    Why use this fancy "dependency injection" instead of just saying "reference"?? Haha.. you made me confused.

    Please keep it "universal".. use the common terms!

  • 2012-12-07 Daniele Tieghi

    Hey guys, your screencasts are simply awesome!
    I hope you come out with the next ones soon!!!
    Thank You!

  • 2012-11-21 Dmitriy

    Can you make video about Security Bundle - crating, using and another stuff about security?