Bootstrapping the Bundle & Autoloading

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.

Heeeeey Symfony peeps! I'm excited! Because we're going to dive deep in to a super interesting topic: how to create your own bundles. This is useful if you need to share code between your own projects. Or if you want to share your great new open source library with the whole world. Actually, forget that! This tutorial is going to be awesome even if you don't need to do either of those. Why? Because we use third-party bundles every day. And by learning how to create one, we're going to become experts in how they work and really get a look at Symfony under the hood.

As always, you can earn free high-fives by downloading the source code from this page and coding along with me. After unzipping the file, you'll find a start/ directory with the same code that you see here. Follow the README.md file for steps on how to get your project setup.

The last step will be to open a terminal, move into the project, sip your coffee, and run:

php bin/console server:run

to start the built-in PHP web server.

Introducing KnpUIpsum

Head to your browser and go to http://localhost:8000. Say hello to The Space Bar! This is a Symfony application - the one we're building in our beginner Symfony series. Click into one of the articles to see a bunch of delightful, fake text that we're using to make this page look real. Each time you refresh, you get new random, happy content.

To find out where this is coming from, in the project, open src/Service/KnpUIpsum.php. Yes! This is our new creation: it returns "lorem ipsum" dummy text, but with a little KnpUniversity flare: the classic latin is replaced with rainbows, unicorns, sunshine and more of our favorite things.

... lines 1 - 2
namespace App\Service;
... lines 4 - 9
class KnpUIpsum
{
private $unicornsAreReal;
private $minSunshine;
public function __construct(bool $unicornsAreReal = true, $minSunshine = 3)
{
$this->unicornsAreReal = $unicornsAreReal;
$this->minSunshine = $minSunshine;
}
/**
* Returns several paragraphs of random ipsum text.
*
* @param int $count
* @return string
*/
public function getParagraphs(int $count = 3): string
{
$paragraphs = array();
for ($i = 0; $i < $count; $i++) {
$paragraphs[] = $this->addJoy($this->getSentences($this->gauss(5.8, 1.93)));
}
return implode("\n\n", $paragraphs);
}
... lines 37 - 338
}

And, you know what? I think we all deserve more cupcakes, kittens & baguettes in our life. So I want to share this functionality with the world, by creating the KnpULoremIpsumBundle! Yep, we're going to extract this class into its own bundle, handle configuration, add tests, and do a bunch of other cool stuff.

Right now, we're using this code inside of ArticleController: it's being passed to the constructor. Below, we use that to generate the content.

... lines 1 - 2
namespace App\Controller;
... lines 4 - 14
class ArticleController extends AbstractController
{
/**
* Currently unused: just showing a controller with a constructor!
*/
private $isDebug;
private $knpUIpsum;
public function __construct(bool $isDebug, KnpUIpsum $knpUIpsum)
{
$this->isDebug = $isDebug;
$this->knpUIpsum = $knpUIpsum;
}
/**
* @Route("/", name="app_homepage")
*/
public function homepage()
{
return $this->render('article/homepage.html.twig');
}
... lines 37 - 75
}

Isolating into a new Bundle Directory

Ok, the first step to creating a new bundle is to move this code into its own location. Eventually, all the code for the bundle will live in its own completely separate directory & repository. But, sometimes, when you first start building, it's a bit easier to keep the code in your project: it let's you hack on things really quickly & test them in your app.

So let's keep the code here for now, but isolate it from the app's code. To do that, create a new lib/ directory. And then, another called LoremIpsumBundle: this will be the temporary home for our shiny bundle. Inside, there are a few valid ways to organize things, but I like to create a src/ directory.

mkdir lib
mkdir lib/LoremIpsumBundle
mkdir lib/LoremIpsumBundle/src

Perfect! Now, move the KnpUIpsum class into that directory. And yea, you could put this into a src/Service directory, or anywhere else you want.

New Vendor Namespace

Oh, but this namespace will not work anymore. We need a namespace that's custom to our bundle. It could be anything, but usually it has a vendor part - like KnpU and then the name of the library or bundle - LoremIpsumBundle.

... lines 1 - 2
namespace KnpU\LoremIpsumBundle;
... lines 4 - 9
class KnpUIpsum
... lines 11 - 340

And, that's it! If we had decided to put KnpUIpsum into a sub-directory, like Service, then we would of course also add Service to the end of the namespace like normal.

Next, back in ArticleController, go up to the top, remove the use statement, and re-type it to get the new one.

... lines 1 - 2
namespace App\Controller;
... line 4
use KnpU\LoremIpsumBundle\KnpUIpsum;
... lines 6 - 77

Handling Autoloading

So... will it work! Yea... probably not - but let's try it! Nope! But I do love error messages:

Cannot autowire ArticleController argument $knpUIpsum... because the KnpUIpsum class was not found.

Of course! After creating the new lib/ directory, we need to tell Composer's autoloader to look for the new classes there. Open composer.json, find the autoload section, and add a new entry: the KnpU\\LoremIpsumBundle\\ namespace will live in lib/LoremIpsumBundle/src/.

77 lines composer.json
... lines 1 - 36
"autoload": {
"psr-4": {
"KnpU\\LoremIpsumBundle\\": "lib/LoremIpsumBundle/src/",
... line 40
}
},
... lines 43 - 77

Then, open a new terminal tab. To make the autoload changes take effect, run:

composer dump-autoload

Registering the Service

Will it work now? Try it! Bah, not yet: but we're closer. The error changed: instead of "class not found", now it says that no KnpUIpsum service exists. To solve this, open config/services.yaml.

Thanks to the auto-registration code in here, we don't normally need to register our classes as services: that's automatic. But, it's only automatic for classes that live in src/. Yep, as soon as we moved the class from src/ to lib/, that service disappeared.

And that's ok! When you create a re-usable bundle, you actually don't want to rely on auto-registration or autowiring. Instead, as a best-practice, you should configure everything explicitly to avoid any surprises.

To do that, at the bottom of this file, add KnpU\LoremIpsumBundle\KnpUIpsum: ~.

... lines 1 - 5
services:
... lines 7 - 37
KnpU\LoremIpsumBundle\KnpUIpsum: ~

This adds a new service for that class. And because we don't need to pass any options or arguments, we can just set this to ~. The class does have constructor arguments, but they have default values.

Ok, try it again! Yes! It finally works! We've successfully isolated our code into its own directory and we are ready to hack! Next, let's make this a bundle with a bundle class and start digging into how bundles can automatically register services.

Leave a comment!

  • 2020-04-20 Diego Aguiar

    Hey Talent Chambachemoto

    You can download the course code by clicking on the "Download -> Course Code" button at the top right corner of this page

    Cheers!

  • 2020-04-19 Talent Chambachemoto

    Can someone please help me the sourcecode for download please.

  • 2020-04-08 Diego Aguiar

    Hey Andrada Ganesha

    I got a bit lost among all the messages :)

    Looks like you had just forgotten to copy the .env file to your project, right?
    About the autowiring error, that's because you need to copy the files inside config directory as well

  • 2020-04-08 Andrada Ganesha

    oh sorry, another error just when I thought it all goes well:

    Environment variable not found: "SLACK_WEBHOOK_ENDPOINT".

    How to fix that?
    Thank you!

    Edit: Solved it by watching the course from Symfony 4 Fundamentals - Environment Variables

  • 2020-04-08 Andrada Ganesha

    I have copied an .env file from another Symfony 4.4.7 version to the course files and now it is working. But...this file should be in the course files for the project to run correctly!!

  • 2020-04-08 Andrada Ganesha

    And I get this error when I try to paste course files only the public folder and the ones in src, only the needed ones in Symfony 4.4.7:

    Cannot autowire service "App\Controller\ArticleController": argument "$isDebug" of method "__construct()" is type-hinted "bool", you should configure its value explicitly.

  • 2020-04-08 Andrada Ganesha

    I have installed just the code from the course in the start folder and on running composer install this is what I get:

    - Installing symfony/web-profiler-bundle (v4.0.6): Loading from cache
    - Installing symfony/twig-bundle (v4.0.6): Loading from cache
    - Installing symfony/profiler-pack (v1.0.3): Loading from cache
    Package symfony/lts is abandoned, you should avoid using it. Use symfony/flex instead.
    Generating autoload files
    Executing script cache:clear [KO]
    [KO]
    Script cache:clear returned with error code 255
    !!
    !! Fatal error: Uncaught Symfony\Component\Dotenv\Exception\PathException: Unable to read the "/Users/andrada/Sites/test-symfony/bin/../.env" environment file. in /Users/andrada/Sites/test-symfony/vendor/symfony/dotenv/Dotenv.php:54
    !! Stack trace:
    !! #0 /Users/andrada/Sites/test-symfony/bin/console(22): Symfony\Component\Dotenv\Dotenv->load('/Users/andrada/...')
    !! #1 {main}
    !! thrown in /Users/andrada/Sites/test-symfony/vendor/symfony/dotenv/Dotenv.php on line 54
    !! PHP Fatal error: Uncaught Symfony\Component\Dotenv\Exception\PathException: Unable to read the "/Users/andrada/Sites/test-symfony/bin/../.env" environment file. in /Users/andrada/Sites/test-symfony/vendor/symfony/dotenv/Dotenv.php:54
    !! Stack trace:
    !! #0 /Users/andrada/Sites/test-symfony/bin/console(22): Symfony\Component\Dotenv\Dotenv->load('/Users/andrada/...')
    !! #1 {main}
    !! thrown in /Users/andrada/Sites/test-symfony/vendor/symfony/dotenv/Dotenv.php on line 54
    !!
    Script @auto-scripts was called via post-install-cmd

    Any ideas? I am running PHP 7.3.16

  • 2020-04-08 Diego Aguiar

    Hey Andrada Ganesha

    I believe something didn't go well when copying the course files to your Symfony4.4 project. I just tried installing the course code and it works (at least in my machine. I'm using PHP 7.4.3
    This course uses Symfony4.0 but if you want to work with Symfony4.4 you can run

    composer upgrade "symfony/*" --with-dependencies


    and everything should work fine

    Please, give it a try and let us know if you keep getting problems. Cheers!

  • 2020-04-08 Andrada Ganesha

    Well, some help here would really be appreciated! If I install symfony 5 and then I copy paste the course code then I cannot get it to work at all due to error after error.
    I have cloned symfony 4 and now I try to figure out what is the best way to incorporate the course code as again I experienced errors and missing services like the slack one and then phpunit error and then composer error on doctrine which does not get fixed with package install. The symfony version is 4.4.7.
    Please help!

  • 2020-04-08 Victor Bocharsky

    Hey Andrada,

    Woops, we're sorry about that! Actually, the concept of creating Symfony bundles remains the same in Symfony 5, so everything we're showing in this course should be valid for Symfony 5 applications. Could you clarify what exactly does not work? Because "nothings works" does not say much. If you have an error - please, share in the comment and we would be glad to help you handle it.

    Cheers!

  • 2020-04-08 Andrada Ganesha

    This tutorial is listed under Symfony 5 when in fact it is a Symfony 3 or 4 tutorial!
    Nothing works when the code is installed...

  • 2020-03-30 dvonrohr

    Just in case you run into the same. I got the error 'curl_multi_setopt(): CURLPIPE_HTTP1 is no longer supported' when i execute 'composer install'.

    Following fix helped me: https://github.com/symfony/...

  • 2020-01-08 Victor Bocharsky

    Hey Luis,

    Perfect! I'm really happy to hear it :)

    Cheers and good luck with your project!

  • 2020-01-06 Luis Enrique Farfán Prado

    Thank you very much for the recommendation!

    It helped me clarify the concept of bundle and I already know how to implement my project.

  • 2020-01-06 Victor Bocharsky

    Hey Luis,

    In Symfony, bundles are mostly meant to be just reusable modules, i.e. some part of code that you can share between a few projects. For example, open source bundles that do some useful things are a good example of this, like KnpSnappyBundle that bring PDF generation into your project. So, instead of implementing this yourself you just can install a ready-to-use solution, i.e. bundle. But if you're not going to have a few projects where you want to share some code between them - you would not be interested in bundles. I'd recommend you to just implement it in your project using PHP logic and using Symfony instruments (components) etc.

    Cheers!

  • 2020-01-03 Luis Enrique Farfán Prado

    Hi,

    I have to make a web application that allows to have several modules with different functionalities, this is because certain clients will have access to certain modules. In symfony 4 would this be done by creating bundles? or is there any other way to do it?

    Thanks, I await your response.

  • 2019-12-11 Victor Bocharsky

    Hey Maik,

    It was a small BC break from the new PHP version in case some code abuses some extra check on array. Actually it comes from "doctrine/annotations", but in 1.7 they fixed it, see related issue: https://github.com/doctrine...

    So, basically, you have two options: Downgrade your PHP version to 7.3 or continue using 7.4 but you would need to upgrade "doctrine/annotations", I suppose just executing "composer update doctrine/annotations" will do the trick. Make sure the downloaded version is 1.7 or higher in the console output.

    I hope this helps!

    Cheers!

  • 2019-12-04 Maik Tizziani

    Executing script cache:clear [KO]
    [KO]
    Script cache:clear returned with error code 1
    !!
    !! // Clearing the cache for the dev environment with debug
    !! // true
    !!
    !!
    !! In FileLoader.php line 168:
    !!
    !! Notice: Trying to access array offset on value of type null in /mnt/d/proje
    !! cts/php/learning/symfony4/test/config/routes/../../src/Controller/ (which i
    !! s being imported from "/mnt/d/projects/php/learning/symfony4/test/config/ro
    !! utes/annotations.yaml"). Make sure annotations are installed and enabled.
    !!
    !!
    !! In DocParser.php line 995:
    !!
    !! Notice: Trying to access array offset on value of type null
    !!
    !!
    !! cache:clear [--no-warmup] [--no-optional-warmers] [-h|--help] [-q|--quiet] [-v|vv|vvv|--verbose] [-V|--version] [--ansi] [--no-ansi] [-n|--no-interaction] [-e|--env ENV] [--no-debug] [--] <command>
    !!
    !!
    Script @auto-scripts was called via post-install-cmd

    And at least the command composer update doctrine/annotations fixes the problem.

  • 2019-12-04 Diego Aguiar

    Hey Maik Tizziani

    Thanks for the detailed instructions. Can you tell me what error were you having?

    Cheers!

  • 2019-12-04 Victor Bocharsky

    Hey Maik,

    Thanks for this tip! Yes, we're recommending to do "composer install" to bootstrap the project, that's what we're saying in the README when you download the course code. But if you do "composer update" instead - it might install some newer versions that is not quite compatible out of the box and more actions need from your side.

    Cheers!

  • 2019-12-03 Maik Tizziani

    in composer.json say nexy slack client has to be version 2.1.0

    "nexylan/slack-bundle": "^2.0<2.2",

    the problem with the slack message is the new slack client that works a little bit different an is not compatible to the course codes

  • 2019-12-03 Maik Tizziani

    i'm using php 7.4, composer 1.9.1 and symfony cli 4.10.2 on microsofts linux sub system at the moment. and i have to update the doctrine/annotations package and the framework-extra-bundle

    perhaps you can add "version": "v1.8.0" to your composer.lock files, this fixes the problem for the annotations to fix the issue for most people.

    1st: composer install (error message about annotation)
    2nd: composer update doctrine/annotations
    3rd: composer update sensio/framework-extra-bundle

    i updated the framework bundle to fix some issues in productiv envoirment

    and 1 deprecated message can be eliminated easily, remove symfony/lts, this is not needed if using flex

  • 2019-09-30 Diego Aguiar

    Dang! That was strange but I'm happy to hear that it's working now. Let's keep coding!

  • 2019-09-30 Capucine Chamin

    I cloned the repository
    https://github.com/knpunive... from where I found this
    page. Since that, I deleted the project and I followed the tutorial by
    implementing a bundle in my own project (and it works well).

    Now I just retry (clone + composer install + symfony serve) and.. it's OK ! Sorry for this false error...

  • 2019-09-26 weaverryan

    Hey Capucine Chamin!

    Hmm, interesting - don't like that at all! Do you get this error when using the start/ directory of the course download from this page? Or something different? Also, you might try manually deleting the vendor/ directory then re-running <codec>composer install. This is a weird error... because it looks like this one file (router.php) is... simply (mysteriously!) missing.

    Let me know!

    Cheers!

  • 2019-09-25 Capucine Chamin

    Hi,

    When I start the server, I've got the following errors :

    PHP Warning: Unknown: failed to open stream: No such file or directory in Unknown on line 0
    PHP Fatal error: Unknown: Failed opening required 'D:\XXXXX\symfony-bundle\vendor\symfony\web-server-bundle/Resources/router.php' (include_path='C:\xampp\php\PEAR') in Unknown on line 0
    PHP Warning: Unknown: failed to open stream: No such file or directory in Unknown on line 0
    PHP Fatal error: Unknown: Failed opening required 'D:\XXXXX\symfony-bundle\vendor\symfony\web-server-bundle/Resources/router.php' (include_path='C:\xampp\php\PEAR') in Unknown on line 0

    The same config for my others Symfony projects is OK.

    I tried to update the project "composer update" (one warning, symfony/lts is abandoned) but then "cache:clear" command failed :

    Circular reference detected for service "nexy_slack.client", path: "nexy_slack.client -> Nexy\Slack\Client -> nexy_slack.client".

  • 2018-12-03 Vladimir Sadicov

    Hi Carlos Eduardo

    Nice catch! There was a little package incompatibility in course code. But now it's fixed. The best solution for you is to re-download course code and try again. Everything should work!

    Cheers!

  • 2018-12-01 Carlos Eduardo

    I'm getting this...

    (1/1) UndefinedMethodException
    Attempted to call an undefined method named "hasBeenStarted" of class "Symfony\Component\HttpFoundation\Session\Session".

    ... just after downloading, "composer install" and "php bin/console server:run".

    Any clue??

  • 2018-09-26 Diego Aguiar

    Thanks Tom Moore

    I'm checking it.
    Cheers!

  • 2018-09-26 Tom Moore

    Hi SymfonyCasts team (or any users who stumble upon this thread before the code is updated) after downloading the code and trying to run `composer install` as per the instructions, I got the following error:
    ```
    [ErrorException]
    Declaration of Symfony\Flex\ParallelDownloader::getRemoteContents($originUrl, $fileUrl, $context) should be compat
    ible with Composer\Util\RemoteFilesystem::getRemoteContents($originUrl, $fileUrl, $context, ?array &$responseHeade
    rs = NULL)
    ```
    Running `composer update symfony/flex --no-plugins` and then `composer install` fixes the problem.

    security-checker also gave a 'ko' for known vulnerabilities in symfony/http-foundation (v4.0.6), though doesn't stop the project from installing.

  • 2018-04-10 Diego Aguiar

    Hey Dennis

    I'm afraid that you will have to upgrade your php to version 7.1, or use Symfony 3

    Cheers!

  • 2018-04-10 Dennis

    Hi Ryan,

    When I run composer install, it says I have 34 problems. Most of the problems is wrong PHP version. How can I fix this?

    doctrine/common v2.8.1 requires php ~7.1 -> your PHP version (7.0.10) does not satisfy that requirement.

    Best regards,
    Dennis