Advanced: Using Composer to Install Your Package and Third Party Libraries

Installing Your Package via Composer

Since version 8, Concrete CMS can be installed via Composer (more details here).

You can also install Concrete packages via Composer.

In order to do so, you need to create a composer.json file in your package root directory, using the second part of the name key to the package handle (package_handle in this case), and setting the type configuration key to concrete5-package.

Next, you have to add your package to a package directory (Composer uses Packagist by default), or configure the composer.json file of your Concrete installation by adding a repositories key describing how Composer can find your package (this is useful for example if your package is not pubicly available - more details here).

Using Third Party Libraries in Your Package

Now that you know how to include and reference custom libraries in your package, you can start solving some real problems with your Concrete packages. But what about those times when those tough problems are already solved for you? What if the exact thing you need already exists on packagist, and you want to include it in your package via PHP's Composer. (Note: if you're not familiar with Composer, you'll want to read this first.)

This is easy to do. Let's say you are creating a statistics package and you want to use LavaCharts in it. LavaCharts is a PHP library that abstracts Google's JavaScript Chart API to PHP. Instead of writing JavaScript, you build your charts with object-oriented PHP. It's nice. LavaCharts is available through Composer, so you can add it in the require section of your package composer.json file.

Third party libraries may have dependencies that are already present in Concrete, so if you call composer install or composer update in your package directory, you may end in having two copies of the same library (one in Concrete and one in your package).

In order to do so, you can use the composerpkg command available here.

In order to know which Concrete version your package requires (so that it can't be installed via Composer in older versions, and to let composerpkg know which libraries are available in Concrete core), you can add a line in the require section of your package composer.json file describing the core version (for example: "concrete5/core": ">=8.5.0").

If you are distributing your package, you can also let Composer assume a specific PHP version, so that the third party libraries will be compatible with the official Concrete distribution (for example, Concrete 8 requires PHP 5.5.9). This can be done by using the platform key of the config section of your package composer.json file.

Autoloading Package Code

Your package may include custom PHP classes that are available in a custom namespace.

In order to let Concrete know how to autoload these classes, you can use the getPackageAutoloaderRegistries() method of your package controller.php file.

But since we are using Composer, we can use the package composer.json file (with the autoload configuration key), so that we avoid adding another autoloader to Concrete.

Complete Example

To summarize all the above, let's see an example of a package when:

  • the package handle is package_handle
  • the package requires the LavaCharts third party library
  • the package has custom PHP code in the CustomNamespace namespace available in the src directory under your package root

Here's the content of the composer.json file in your package root directory:

{
    "name" : "your_name/package_handle",
    "type" : "concrete5-package",
    "require": {
        "concrete5/core": ">=8.5.0",
        "khill/lavacharts": "2.5.*"
    },
    "autoload": {
        "psr-4": {
            "CustomNamespace\\": "src/"
        }
    },
    "config": {
        "platform": {
            "php": "5.5.9"
        }
    }
}

Here's the content of the controller.php file in your package root directory:

<?php

namespace Concrete\Package\PackageHandle;

use Concrete\Core\Package\Package;

defined('C5_EXECUTE') or die('Access Denied.');

class Controller extends Package
{
    /**
     * The minimum concrete5 version.
     */
    protected $appVersionRequired = '8.5.0';

    /**
     * The package handle.
     */
    protected $pkgHandle = 'package_handle';

    /**
     * Initialize the autoloader when installing the package.
     */
    public function install()
    {
        $this->setupAutoloader();
        parent::install();
    }

    /**
     * Initialize the autoloader when the system boots up.
     */
    public function on_start()
    {
        $this->setupAutoloader();
    }

    /**
     * Configure the autoloader
     */
    private function setupAutoloader()
    {
        if (file_exists($this->getPackagePath() . '/vendor')) {
            require_once $this->getPackagePath() . '/vendor/autoload.php';
        }
    }
}

To install the package in a composer-based Concrete installation:

cd path/to/the/concrete5/root/directory
composer require your_name/package_handle

To prepare the package for distribution in non composer-based Concrete installations:

cd path/to/the/package/directory
composerpkg install