Buy

Proper Bundle composer.json File

With a Subscription, click any sentence in the script to jump to that part of the video!

Login Subscribe

We put the bundle into our app temporarily because it made it really easy to hack on the bundle, test in the app and repeat.

But now that it's getting kinda stable, it's time to move the bundle into its own directory with its own repository. It's like watching your kid grow up, and finally move into their own apartment.

Find your terminal, and kick that lazy bundle out of your house and into a new directory next door:

mv lib/LoremIpsumBundle ../LoremIpsumBundle

In PhpStorm, let's open that second directory inside a new window, and re-decorate things a little bit. Ok, a lot to keep track of: application code, bundle code and terminal. To confuse things more, open a third terminal tab and move it into the bundle, which, sadly, does not have a git repository yet!

Let's add one!

git init
git status

Add everything and commit!

git add .
git commit -m "Unicorns"

Bootstrapping composer.json

To make this a shareable package, it needs its very-own composer.json file. To create it, run:

composer init

Let's call it knpuniversity/lorem-ipsum-bundle, give it a description, make sure the author is correct, leave minimum-stability alone and, for "Package Type" - this is important! - use symfony-bundle. That's needed so that Flex will automatically enable the bundle when it's installed. For License, I'll use MIT - but more on that later. And finally, let's not add any dependencies yet. And, generate! Let's definitely ignore the vendor/ directory.

{
"name": "knpuniversity/lorem-ipsum-bundle",
"description": "Happy lorem ipsum",
"type": "symfony-bundle",
"license": "MIT",
"authors": [
{
"name": "Ryan Weaver",
"email": "ryan@knpuniversity.com"
}
],
"require": {}
}

Hello .gitignore file and hello composer.json! This file has a few purposes. First, of course, it's where we will eventually require any packages the bundle needs. We'll do that later. But I am going to start at least by saying that we require php 7.1.3. That's the version that Symfony 4.0 requires.

... lines 1 - 11
"require": {
"php": "^7.1.3"
}
... lines 15 - 16

Autoloading Rules

Second, the composer.json file is where we define our autoloading rules: Composer needs to know what namespace our bundle uses and where those classes live.

Up until now, we put those autoload rules inside the main project. Let's steal that section and remove the line for our bundle. Paste that into the bundle and remove the App line. The KnpU\\LoremIpsumBundle\\ namespace lives in just, src/.

... lines 1 - 14
"autoload": {
"psr-4": {
"KnpU\\LoremIpsumBundle\\": "src/"
}
}
... lines 20 - 21

Using a "path" Repository

So... yay! We have a standalone bundle with its own repository! But, I'm not quite ready to push this to Packagist yet... and I kinda want to keep testing it inside my app. But, how? We can't composer require it until it lives on Packagist, right?

Well, there is one trick. Google for "composer path package".

Click on the "Repositories" documentation and... all the way at the bottom... there's a path option! This allows us to point to any directory on our computer that contains a composer.json file. Then, suddenly, that library becomes available to composer require.

Copy the repositories section, find our application's composer.json and, at the bottom, paste this. The library lives at ../LoremIpsumBundle.

Tip

The course code contains LoremIpsumBundle project inside itself, hence you won't see ../ on the repository URL in the code blocks.

83 lines composer.json
... lines 1 - 75
"repositories": [
{
"type": "path",
"url": "LoremIpsumBundle"
}
]
... lines 82 - 83

Thanks to that, our application now knows that there is a package called knpuniversity/lorem-ipsum-bundle available. Back at the terminal, find the tab for our application and composer require knpuniversity/lorem-ipsum-bundle, with a :*@dev at the end.

composer require knpuniversity/lorem-ipsum-bundle:*@dev

A path package isn't quite as smart as a normal package: you don't have versions or anything like that: it just uses whatever code is in that directory. This tells Composer to require that package, but not worry about the version.

And, cool! On my system, it installed with a symlink, which means we can keep hacking on the bundle and testing it live in the app.

Oh, and since Symfony flex noticed that our package has a symfony-bundle type, it actually tried to configure a recipe, which would normally enable the bundle for us in bundles.php. It didn't this time, only because we already have that code.

Now that everything is reconnected, it should work! Refresh the page. Yes! That bundle is properly living on its own.

Next, we actually already have some tests for our bundle... but they still live in the app. Let's move these into the bundle and start talking about properly adding the dependencies that it needs.

Leave a comment!

  • 2018-05-09 Diego Aguiar

    Awesome! I'm glad that you could fix it by yourself :)
    Thanks for sharing your solution with us

    Cheers!

  • 2018-05-08 Bertin van den Ham

    I've find a solution for Vagrant Homestead.
    First add the seperated folder to your Homestead.yaml

     
    #Homestead.yaml
    folders:
    ...
    # added new line where my local bundles are
    - map: ~/Documents/Development/bundles/
    to: /home/vagrant/documents/development/bundles/

    And then in my composer.json file

     
    #composer.json
    "repositories": [
    {
    "type": "path",
    "url": "/home/vagrant/documents/development/bundles/MenuBundle"
    }
    ]

    And finally the commend: composer require bham/menu-bundle:*@dev works.

  • 2018-05-08 Bertin van den Ham

    Hey weaverryan ,

    I've found the problem. I'm working on a vagrant machine (Homestead) and the local bundle directory is not know in the vagrant structure. To solve this problem I've created a private Github repo and pushed my bundle to it.
    Then I've created a version v1.0.0 and added the following to my composer.json

     
    # composer.json from application
    {
    "type": "project",
    "license": "proprietary",
    "require": {
    "php": "^7.1.3",
    "bham/menu-bundle": "^1.0",
    ...
    },
    "repositories": [
    {
    "type": "vcs",
    "url": "git@github.com:username/name-to-bundle.git"
    }
    ]
    }

    When running the command: composer require bham/menu-bundle
    composer asks for an token to authorize my to use the git repo.

    Now everything works find.
    And for developing i could work directly from my vendor bundle directory because it has its on Github Repo.

    But i will try to make it work localy with vagrant because its easer to develop when the bundle is localy.

  • 2018-05-08 weaverryan

    Hey Bertin van den Ham!

    Hmm. Ok, let's try one thing quickly. Change your composer require to this:


    composer require bham/menu-bundle:@dev

    We had a report from one other user that the * was causing problems. This might fix your *second* problem, which could be related to the first problem :). I don't see any issues with your autoloading config. So, let's try the above to make sure we get the bundle in correctly. If you ARE still having this error, let me know - we'll look closely into the autoload stuff.

    P.S. Nice job with the formatted code-blocks - you're a KnpU pro ;)

    Cheers!

  • 2018-05-07 Bertin van den Ham

    I've moved my bundle in its own directory but getting the following error:

    "(1/1) ClassNotFoundException
    Attempted to load class "BhamMenuBundle" from namespace "Bham\MenuBundle".
    Did you forget a "use" statement for another namespace?"

    There is something wrong with the namespace but i've followed the same steps.
    I've added the composer path

     
    # config/bundles.php
    "repositories": [
    {
    "type": "path",
    "url": "../MenuBundle/"
    }
    ]

    These are my files;

    Application

     
    # config/bundles.php
    return [
    ...
    Bham\MenuBundle\BhamMenuBundle::class => ['all' => true],
    ];

     
    # vendor/bham/menu-bundle/src/
    /**
    * BhamMenuBundle
    */

    namespace Bham\MenuBundle;

    use Symfony\Component\HttpKernel\Bundle\Bundle;

    /**
    * Class BhamMenuBundle
    * @package Bham\MenuBundle
    */
    class BhamMenuBundle extends Bundle {

    }

    Bundle

     
    #MenuBundle/composer.json
    {
    "name": "bham/menu-bundle",
    "description": "Generate a menu with BhamMenuBundle",
    "type": "symfony-bundle",
    "license": "MIT",
    "authors": [
    {
    "name": "Bertin van den Ham",
    "email": "bertinvandenham@gmail.com"
    }
    ],
    "require": {
    "php": "^7.1.3"
    },
    "autoload": {
    "psr-4": {
    "Bham\\MenuBundle\\" : "src/"
    }
    }
    }

    Also run the command composer dumpautoload.
    Also removed the cached directory and removed the composer.lock file
    but now i'am getting this error:

    composer require bham/menu-bundle:*@dev

    " [InvalidArgumentException]
    Could not find a matching version of package bham/menu-bundle. Check the package spelling, your version constraint and that the package is available in a stability which matc
    hes your minimum-stability (stable)."

    Does i miss some configs?

  • 2018-05-02 Greg

    Hey weaverryan

    I don't know why too. I made this tutorial with another computer same OS, same version of composer and I had the same problem. This tip worked again so it is a good thing to know ;)

    And thanks to you and all your team for the great works.

    I'm totally addict at KnpUniversity ;)

    Cheers!

  • 2018-05-02 weaverryan

    Hey Greg!

    Hmm, interesting! Thanks for sharing your fix! We're going to check into it, but me may very well add a note about this - I'm not sure why the * worked for me, but not you! But, happy it's working now :).

    Cheers!

  • 2018-05-02 Greg

    Composer version 1.6.4 2018-04-13 12:04:24 and I'm using macOS High Sierra 10.13.4

    Ok it's work if I remove the *
    I just need to do


    composer require knpuniversity/lorem-ipsum-bundle:@dev

    I hope it helps other people.

    Thanks guys for your time.

    Cheers!

  • 2018-05-01 Diego Aguiar

    Uhmm, my belt is running out of tricks...
    Which composer version (try updating it) and OS are you using?

  • 2018-05-01 Greg

    the same error

    fish: No matches for wildcard 'knpuniversity/lorem-ipsum-bundle:*@dev'. See `help expand`.
    composer require knpuniversity/lorem-ipsum-bundle:*@dev -vvv

  • 2018-05-01 Diego Aguiar

    wow... Ok, remove your "composer.lock" and try again but add "-vvv" to command, so we can get more debugging information

  • 2018-05-01 Greg

    the same :)

  • 2018-05-01 Diego Aguiar

    Hmm, everything looks fine. Probably is something with the cache. Try clearing your composer's cache

    composer clearcache
  • 2018-05-01 Greg

    Thanks for imgur I forgot the name ;)

    No my composer.json file of the Bundle is not in "src" folder.
    You can see it on the screen Screenshot

  • 2018-05-01 Diego Aguiar

    You can upload them to imgur (or any other platform) and share the url.

    The composer.json file of your "Bundle" project lives inside the "src" folder? It has to live at the root of the project
    That may be the problem

  • 2018-05-01 Greg

    Hey Diego Aguiar

    I know that the problem is from the url of the repositories but my composer.json is in my project and the url is the relative path.

    I made 3 screenshots to show you my hierarchy folder but I don't know how to share it.

    But I can explain:
    I have a big folder inside of it I have my folder for my App and my folder for the "Bundle".
    So inside my App I have my composer.json at the same level of symfony.lock. In this composer I have my key "repositories" like above. And in my Bundle folder at the same level of the folder src I have my other composer.json with the name "knpuniversity/lorem-ipsum-bundle"

    So in the url the relative is well "../LoremIpsumBundle".
    And I understand totally the necessity of "*@dev" .

    But thanks for you help ;)

  • 2018-05-01 Diego Aguiar

    Hey Greg

    I was able to reproduce it. So, there must be something with one (or both) of your composer.json file.
    The "repositories" key should be defined in the composer.json inside your application, and the "url" field is a relative path to the "Bundle" folder.
    Then, it is important to put back the "*@dev" or you will be fetching the real "knpuniversity/lorem-ipsum-bundle"

    I hope it helps ;)

  • 2018-05-01 Greg

    Hey weaverryan

    this is my repositories setting:


    "repositories": [
    {
    "type": "path",
    "url": "../LoremIpsumBundle"
    }
    ]

    my 2 folders are at the same level. for the naming this is exactly knpuniversity/lorem-ipsum-bundle

    I'm gonna keep looking ;)

    Thanks for your answer.

    Cheers!

  • 2018-04-30 weaverryan

    Hey Greg!

    Ok, so let's look at each part!

    > I have a little issue, when I did composer require knpuniversity/lorem-ipsum-bundle:*@dev, I have this message
    fish: No matches for wildcard 'knpuniversity/lorem-ipsum-bundle:*@dev'.

    This makes me think that your "path" package isn't setup correctly. Here are some things to check :)

    A) Make sure you have the "repositories" section setup correctly that we added: https://knpuniversity.com/s...

    B) Double-check the name of your library in your new composer.json that lives in the bundle. Is it exactly knpuniversity/lorem-ipsum-bundle?

    > So I removed the *@dev but after that the error is

    This is probably just because, due to some issue with the path repository, you are *actually* downloading the *real* knpuniversity/lorem-ipsum-bundle. And so, you are getting basically the "final" version of the bundle, which actually does not include the word_provider option (we remove this in one of the last chapters).

    Check into the first issue - I think the both problems come from there somehow!

    Cheers!

  • 2018-04-30 Greg

    Hey weaverryan

    I have a little issue, when I did composer require knpuniversity/lorem-ipsum-bundle:*@dev, I have this message
    fish: No matches for wildcard 'knpuniversity/lorem-ipsum-bundle:*@dev'. See `help expand`.

    So I removed the *@dev but after that the error is

    In ArrayNode.php line 311:
    !!
    !! Unrecognized option "word_provider" under "knpu_lorem_ipsum"
    If I removed the "word_provider" like Jennifer Koenig, I have a invalid service

    Invalid service "App\Service\CustomWordProvider": class "App\Service\Custom
    !! WordProvider" does not exist.

    What's wrong ?
    thanks

  • 2018-04-23 weaverryan

    Yep, for sure - good not! This is a particularly confusing tutorial as we flip around between 2 different code bases (the bundle & the project). The "repositories" section lives in your "app" code at this point, not in the composer.json of LoremIpsumBundle :).

  • 2018-04-23 weaverryan

    Hey Jennifer Koenig!

    Ah man! Ok, we *really* work hard to make sure the code *actually* works :). So, let's figure this out! When I download the course code from this page, I actually do NOT have *any* config/packages/knpu_lorem_ipsum.yaml file. There IS one in the finish directory, but not the start. Are you seeing something different?

    Cheers!

  • 2018-04-23 Jennifer Koenig

    Just a note: the "respositories" section of composer.json belongs in the "start" directory's composer.json... not in the LoremIpsumBundle composer.json

  • 2018-04-23 Jennifer Koenig

    When I try to install the bundle (in the "start" directory) I get the following error:

    Executing script cache:clear [KO]
    [KO]
    Script cache:clear returned with error code 1
    !!
    !! In ArrayNode.php line 319:
    !!
    !! Unrecognized option "word_provider" under "knpu_lorem_ipsum"
    !!

    What am I doing wrong? Where can I start debugging? I compared the services.xml of the newly created bundle and that in finish, and they are the same.

    --
    update: I was able to fix this by removing the "word_provider" entry from config/packages/knpu_lorem_ipsum.yaml in the start directory.