Categories
How To

More Complicated Composition

A slightly more complicated setup for Composer? Why not!

Once you’ve made your basic composer.json file and you’ve got your library included, it’s time to consider a more complication situation.

Let’s take the following example. You want to include two plugins/add-ons, a javascript library, oh and one of those plugins doesn’t use Composer. Don’t worry, we can do this.

Organize Your Notes Organize Your Notes

Step one is to make a list of what you need to install and where it needs to go. Because in this situation, due to the use of the javascript, we’re not going to be using that autoloader.

  1. list all your repositories 
  2. mark which ones do and don’t use Composer
  3. determine where they need to go

For this example, we want the javascript files to go in the assets/js/ folder in our plugin, and we want the plugin/add-ons to go in plugins/

Okay, that’s straightforward. But we need to address something.

Top ↑

Avoid AutoTune Avoid AutoTune

I mentioned we’re not using the autoloader and I cited the javascript as why. That was a partial lie. You see, even though Composer makes an autoload file, and even though it is a dependancy manager, it actually tells you not to commit your dependancies to your own repository.

The general recommendation is no. The vendor directory (or wherever your dependencies are installed) should be added to .gitignore/svn:ignore/etc.

Official Composer Documentation

The biggest reason why is one you absolutely will run into here, and it’s that when you add dependancies installed via git to another git repo, they end up as submodules, which are a special hell of their own. Only it’s worse. They’re not even really submodules, and you end up with empty folders.

Seriously, I wasted two hours on this when I first ran into it.

But that said, it’s really wise to omit your vendor folder because your plugin does not need 3 megs of files if all you want is one javascript file. Right? This means we need to add one more dependancy to Composer, and that’s Composer Copy File.

Top ↑

Adding The Normal Dependancies Adding The Normal Dependancies

Right now, our requires section looks like this:

    "require": {
        "slowprog/composer-copy-file": "^0.2.1"
    }

So when you add in your normal dependancies, like the PHP library, you get this:

    "require": {
        "slowprog/composer-copy-file": "^0.2.1",
        "example/php-library1": "^1.3"
    }

You’ll do this for the javascript libraries as well:

    "require": {
        "slowprog/composer-copy-file": "^0.2.1",
        "example/php-library1": "^1.3",
        "example/js-library1": "^0.2.1",
        "example/js-library2": "^2.30"
    }

Top ↑

Adding the Weird Stuff Adding the Weird Stuff

Okay but I mentioned one of the PHP libraries I wanted to use didn’t have a composer.json file, which means I can’t include it like that. Instead, I have to add this section above the requires section, in order to create a new package to add:

    "repositories": [
        {
          "type": "package",
          "package": {
            "name": "example2/php-library",
            "version": "1.0.0",
            "source": {
              "url": "https://github.com/example2/php-library",
              "type": "git",
              "reference": "master"
            }
          }
        }
    ],

Right? That’s all kinds of weird, but basically I’m telling Composer that there’s a package called example2/php-library and it gets its data from https://github.com/example2/php-library – which means I can then add it to my requires like this:

    "require": {
        "slowprog/composer-copy-file": "^0.2.1",
        "example/php-library1": "^1.3",
        "example/js-library1": "^0.2.1",
        "example/js-library2": "^2.30",
        "example2/php-library2": "dev-master",
    }

Top ↑

Copy Everything Copy Everything

Once you have your files in and required, everything gets put in vendor which is great except for the part where we’re not going to use the autoloader. In fact, we’re going to add /vendor/ to our .gitignore file to make sure we keep our plugin small.

No, we’re going to use that copy code we mentioned above like this:

    "scripts": {
        "post-install-cmd": [
            "SlowProg\\CopyFile\\ScriptHandler::copy"
        ],
        "post-update-cmd": [
            "SlowProg\\CopyFile\\ScriptHandler::copy"
        ]
    },
    "extra" : {
        "copy-file": {
            "vendor/example/php-library1/": "plugins/php-library1/",
            "vendor/example2/php-library2/": "plugins/php-library2/",
            "vendor/example/js-library1/dist/js/file.min.js":  "assets/js/file.min.js",
            "vendor/example/js-library2/dist/js/file2.min.js": "assets/js/file2.min.js"
        }
    }

The first portion triggers a copy every time you install or update the Composer setup, and the section section (in extras) is what runs. 

Now you include the libraries in your code like you’d downloaded and copied them, only you don’t have to worry so much about keeping them up to date. As long as you’ve got your composer versions, you’re good to go.