Symfony 3 Tutorials List

I’ve been asked a few times now if there is a Symfony 3 track available yet at Code Review Videos?

The answer is: yes!

It’s a work-in-progress, but there are already plenty of videos available.

Did you know? There are over 250 videos over 38 courses available right now.

I have been meaning to put together a more formally structured list, so here we go:

Symfony 3 Tutorials List

I’ll keep this list updated as new courses become available.

1. Introduction to Symfony 3

This is a beginner friendly Symfony 3 tutorial series.

I figured the best way to learn a new topic – something which can be quite boring and dry if you just learn the theory stuff – would be to immediately build something cool.

This course covers a lot of the fundamentals by building a reproduction of your GitHub profile.

By the end of this series you will have hands-on experience with:

  • Symfony 3
  • Routing
  • Twig Templates
  • Bootstrap 3
  • Symfony Services
  • Guzzle / RESTful API interactivity with GitHub

You don’t need a GitHub profile to take part in this course. You can use anyone’s profile. No excuses! Get learning, and welcome to Symfony 3 🙂

https://www.codereviewvideos.com/course/beginner-friendly-hands-on-symfony-3-tutorial

2. Doctrine

Doctrine allows you to create, read, update, and delete records from your database.

This is pretty much essential knowledge for any developer who needs to get things done.

Doctrine has a ton of unusual terms like hydration, persistence, fixtures, migrations, annotations… and without much context, it can be really confusing at first to figure out what they all mean.

We’ll go through an example of scraping Reddit’s PHP subreddit to explain a large number of these terms, and also in the process start relating entities together, and optimising our queries.

We also cover Doctrine’s Query Builder, and Doctrine Query Language (DQL), and discuss when might be appropriate to use one or the other.

This beginner friendly short course is all about demystifying Doctrine, and getting your started – quickly – with some hands on exercises to cover the basics of working with your database in Symfony 3.

https://www.codereviewvideos.com/course/doctrine-databasics

3. Forms

Symfony’s form component is incredibly versatile.

However, initially it can be a source of confusion.

In this course we cover the fundamentals of using the form – concepts which if you do not know or understand will make life much more difficult for you when you get to the more complex form types that Symfony can offer.

We start with a basic contact form, and then move on to adding and editing records in our database using Doctrine entities.

From there we will cover:

  • form styling – particularly integration with Bootstrap 3
  • form customisation
  • form fragments
  • data validation

And then on to a selection of examples which cover how to use Symfony’s form in a number of more realistic / real world ways.

https://codereviewvideos.com/course/beginner-s-guide-to-symfony-3-forms

Symfony 3 Intermediate Tutorials List

These tutorials are aimed at Symfony developers who are comfortable with the basics of a Symfony project.

It doesn’t matter whether that is Symfony 2, or Symfony 3. The syntax differences between Symfony2 and Symfony3 are not too difficult to figure out for any developer with a project or two under their belt.

If you are new to Symfony, I’d advise not starting with projects in this list to begin with. Make a simpler site, get a feel for the framework, then tackle these bigger projects without losing all your hair in the process.

Symfony 3 RESTful API

Probably the most important topic currently facing back-end Symfony developers is – how do I present my code via a RESTful API?

In Symfony there are a number of ways to solve this problem. In this series I show you one way using:

  • FOSRESTBundle
  • Testing using Behat 3 and PHPSpec 2
  • File Uploading using Flysystem
  • User management with FOSUserBundle
  • Handling login with LexikJWTBundle

This allows your front end developer(s) to interact with your Symfony 3 application using React, Ember, AngularJS, or any other technology your project needs.

https://codereviewvideos.com/course/symfony-3-rest-tutorial

New Courses

I have a long list of forthcoming courses, plenty to keep me going for the foreseeable future.

As a site member, you are more than welcome to submit course ideas and suggestions, and ask questions about video content.

What might not be immediately obvious is that all the previous courses on Symfony 2 topics here at Code Review Videos are in the most part, directly transferable to Symfony 3. There really wasn’t that huge of a change between Symfony 2 and Symfony 3. Not like when we went from Symfony 1 to Symfony 2 anyway.

I really hope you find these courses, and the rest of the content here to be extremely useful.

Don’t struggle learning all this stuff on your own. Let me help you learn Symfony faster and easier.

Site membership is $24.97 a month, or $49.97 a month for a team.

Debugging By Dumping

By now, most of us will likely have used the dump($var); function made available for us in Symfony 2.6.

If you haven’t, or you think you can’t because you a) don’t have the latest and greatest version of Symfony, or b) don’t use Symfony, then never fear, you can include the VarDumper component in any project. No excuses.

Whilst the  dump($var); function is incredibly useful, in one instance so far, it has caused me more headaches than it has solved.

The Situation

I’m working on a new RESTful API using Symfony 2 as my back end.

Along the way, I want to restrict Users from being able to access other peoples data, for obvious reasons.

Without getting too deep into the code – as it’s really not that important to this problem / solution – I hit upon an issue where I wasn’t getting the expected output. Such is life of a developer.

However, I can tell you are getting twitchy from having not yet seen any code, so to placate your code cravings, here is the method:

    /**
     * @return array
     */
    public function findAll()
    {
        $accounts = $this->repository->findAll();

        foreach ($accounts as $account) {
            $this->denyAccessUnlessGranted('view', $account);
        }

        return $accounts;
    }

See, I told you, not much to look at.

At some point along the way (and in truth, I haven’t figured out exactly where as of yet), I know that $this->denyAccessUnlessGranted(‘view’, $account);  is having a bad time.

To begin with, I wanted to see exactly what the contents of $accounts was before it even hit the foreach loop.

To the dumper!

    /**
     * @return array
     */
    public function findAll()
    {
        $accounts = $this->repository->findAll();

        exit(dump($accounts));

        foreach ($accounts as $account) {
            $this->denyAccessUnlessGranted('view', $account);
        }

        return $accounts;
    }

Alas, no:

the-output-of-symfony-vardumper-dump

The next thing you might think is – ok, just use print_r($var); and be done with it.

Unfortunately, that’s not an option when dealing with most Doctrine entities. If you try, you may get lucky, you may hit funky maximum nesting level errors, or worse, you may crash your DHC client. Guess which I encountered?

My Solution

Never the less, there is a solution. Quite an old school solution. Something I used to use all the time before the VarDumper component was a thing:

exit(\Doctrine\Common\Util\Debug::dump($yourVariableHere));

This will give you an equivalent of print_r($var); but without the nasty blow ups:

the-output-of-doctrine-dump

It’s an old technique sir, but it checks out.

Now just to figure out why the test is failing, and everything will be right with the world once more.

How to fix: You have requested a non-existent service “test.client” with Behat 3

So, it’s been a long day of development.

And the last 50 minutes have been particularly painful.

I’ve been bringing FOSUserBundle, Dunglas API Bundle, Lexik JWT Bundle, and Behat (amongst a good few others) together into one project for the first time.

Most of today has been productive. I’ve solved two of my big headaches, but as the hours have gone by, tiredness has set in.

And rather than call it a night, I did my usual “I’ll just see if I can…” once too many times, and buggered everything up.

If I had been behaving, I could have quickly done a little git bisect magic and found the source of my woes. Alas, I had not been behaving.

Anyway, the issue:

Run bin/behat , encounter error:

  [Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException]
  You have requested a non-existent service "test.client".

Wot do?

Well, there is a major shortage of Google help on this one.

The two most likely answers were not it.

Behat had been working just fine. I knew it was my mistake. But the project is growing and there’s just a ton of possible files that could have changed. When will I learn?

As it turned out, I had changed my behat.yml file in my tired stupor:

# behat.yml 
 extensions:
    Behat\Symfony2Extension:
      kernel:
        env: "test"
        debug: "true"

I’d changed env to a new Symfony Environment I had created so as not to keep messing up my local dev database every time I re-ran behat.

In my case changing back to env: “test” solved all my problems.

Ok, well not all of them… plenty of work still to do. But that’s it for this evening.

I hope that saves someone a headache in the future.

Time to commit and go to bed.

Adding Tumblr to HWIOAuthBundle

Tumblr HWIOAuthI recently needed to add in Tumblr social authentication to a Symfony project. I made use of the excellent HWIOAuthBundle, which made the whole process a breeze.

Unfortunately, out of the box, there is no direct support for Tumblr.

However, no fear, as manually adding support in is simple enough.

Follow the installation instructions through to the end of Step 2. At the bottom of the section on Configuring Resource Owners is the option for ‘Others‘.

To get this to work, it’s mainly a bit of back and forth between the Tumblr API docs and your config.yml file, so let me spare you the time:

hwi_oauth:
    # list of names of the firewalls in which this bundle is active, this setting MUST be set
    firewall_name: main # important to change this to match the firewall you are adding hwioauth too
    resource_owners:
        tumblr:
            type:                oauth1
            client_id:           your_tumblr_api_client_id_here
            client_secret:       your_tumblr_api_client_secret_here
            access_token_url:    https://www.tumblr.com/oauth/access_token
            authorization_url:   https://www.tumblr.com/oauth/authorize
            request_token_url:   https://www.tumblr.com/oauth/request_token
            infos_url:           https://api.tumblr.com/v2/user/info
            scope:               "read"
            user_response_class: HWI\Bundle\OAuthBundle\OAuth\Response\PathUserResponse
            paths:
                identifier:     response.user.name
                nickname:       response.user.name
                realname:       response.user.name

The paths section is interesting.

We must specify at least these three for HWIOAuthBundle to not error out.

What I’m doing here is using a dotted array access format. Kinda confusing sounding, but really what this is saying is : $response[‘user’][‘name’] .

Why the same data for each field?

Well, Tumblr doesn’t return much in the way of account data here.

You can see the full output from Tumblr here:

PathUserResponse.php on line 122:
array:2 [▼
  "meta" => array:2 [▶]
  "response" => array:1 [▼
    "user" => array:5 [▼
      "name" => "futuristicallycrookedbread"
      "likes" => 0
      "following" => 6
      "default_post_format" => "html"
      "blogs" => array:1 [▼
        0 => array:29 [▼
          "title" => "Untitled"
          "name" => "futuristicallycrookedbread"
          "posts" => 4
          "url" => "http://futuristicallycrookedbread.tumblr.com/"
          "updated" => 1441562102
          "description" => ""
          "is_nsfw" => false
          "ask" => false
          "ask_page_title" => "Ask me anything"
          "ask_anon" => false
          "followed" => false
          "can_send_fan_mail" => true
          "is_blocked_from_primary" => false
          "share_likes" => true
          "likes" => 0
          "twitter_enabled" => false
          "twitter_send" => false
          "facebook_opengraph_enabled" => "N"
          "tweet" => "N"
          "facebook" => "N"
          "followers" => 0
          "primary" => true
          "admin" => true
          "messages" => 0
          "queue" => 0
          "drafts" => 0
          "type" => "public"
          "subscribed" => false
          "can_subscribe" => false
        ]
      ]
    ]
  ]
]

This is the result of using Symfony’s VarDumper component on line 122 of PathUserResponse.php .

How did I know to add the dump($response); statement in there?

Well, we specified in the config.yml file that we are expecting a User Response to be:

user_response_class: HWI\Bundle\OAuthBundle\OAuth\Response\PathUserResponse

I just opened up that file and added in the dump, using the $response variable that had been defined earlier on line 113.

There is a little bit of extra config in security.yml :

security:
    providers:
        social_user_provider:
             id: oauth_user_provider

    firewalls:
        main:
            anonymous: ~
            oauth:
                resource_owners:
                    tumblr:        "/login/check-tumblr"
                login_path:        /login
                use_forward:       false
                failure_path:      /login
                oauth_user_provider:
                    service: oauth_user_provider

    access_control:
        - { path: ^/login, role: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/connect, role: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/, role: ROLE_USER }

Alongside the other HWIOAuth routes, you will need to add in one for Tumblr:

# app/config/routing.yml - or where ever you are storing routes
tumblr_login:
    path: /login/check-tumblr

The oauth_user_provider  service must exist, so here is my definition:

# services.yml (or where ever)
services:
    oauth_user_provider:
        class: AppBundle\Model\OAuthUserProvider

This should work for other social auth providers, with only a little modification. As much as this looks like loads of config (hey, it’s a Symfony project!), it’s actually really pretty easy to add in new social providers. I was pleasantly surprised.