Concrete5

Q&A: Using Composer in a concrete5 Package

I get letters! This is from Jay:

Is there a way that you can provide documentation or a how to step by step instructions on how to integrate 3rd party libraries which I guess are now called services and not helpers so that concrete can find the classes. I have used several different approaches such as src folder, composer.son files and such and sooner or later they all break without any meaningful error messages. I am trying to incorporate LavaChart.

This is easy to do. First, I'm not sure whether you're using custom code in your application/ directory or you have created a package, but I would strongly recommend encapsulating this functionality in a concrete5. Packages let you upgrade all the code bundled together, add functionality over time, and keep related code together. Plus, interacting with PHP's Composer is easy to do from within a package.If you're new to the concrete5 package format, here's a lot of documentation on it.

Let's say I'm creating a statistics package and I want to use LavaCharts in it. For those who don't know, 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 I'll include it that way. (Note: if you're not familiar with Composer, you'll want to read this first.)

Setup and Install Your Package

Follow the instructions at the link above to set up a basic concrete5 package, with a controller file. Since we're working on a dummy statistics package, I'll call this "awesome_statistics.". You'll have a directory named awesome_statistics within your package root, and a controller file. Then you'll install this package through the concrete5 Dashboard. No, it won't do anything yet – but now that it's installed you can use it to include third party libraries.

Install Libraries via Composer

Next, create a composer.json file in your package root, and add the relevant JSON to it.

{
    "require": {
        "khill/lavacharts": "2.5.*"
    }
}

This file should be found at packages/awesome_statistics/composer.json. This tells composer that we want to include the 2.5 branch of the LavaCharts package. Then, we run "composer update" from within our package directory.

/path/to/composer update

This will create a composer.lock file, which locks the exact version of the included library, and downloads the version into a vendor/ directory in the same location, while also installing any dependencies that LavaCharts needs to function. We now have a composer.json file, a composer.lock file, and a vendor directory in our statistics package directory.

Including the Libraries in the Package

Now that we have the libraries available in our package, before we can use them in our code we have to load them. This can be accomplished by defining an on_start() method in our package controller, and including the autoload.php file that comes with every Composer package in this method. If you don't have an on_start() method in your package controller, create one. Once you have the method, add this line at the top of it:

public function on_start()
{
    require $this->getPackagePath() . '/vendor/autoload.php';
}

That's it! The dynamically generated autoload.php file is the key to autoloading all classes in a Composer package. Once you've included that, you'll have full access to all the classes used by your library.

Referencing code in your controllers and views

Now that you're auto-loading classes, you can use them everywhere throughout concrete5. For example, here's how you might create a chart in a concrete5 single page controller. Just import the namespace at the top of your class file

use Khill\Lavacharts\Lavacharts;

And use it from within your controller method:

public function view()
{
    /*
     * Business logic of populating the $statistics array is up to you - this is just an example of how we can reference the
     * class
     */
    $statistics = $this->someMethodToPopulateStatistics();
    $lava = new Lavacharts();
    $views = $lava->DataTable();
    $views->addDateColumn(t('Date'))->addNumberColumn(t('Visits'));
    foreach($statistics as $result) {
        $views->addRow(array($result['visit'], $result['total']));
    }
    $title = t('Visits in the last 7 days');
    $chart = $lava->LineChart(t('Visits'))->dataTable($views)->title($title);
    $this->set('chart', $chart);
}

Then, from within your view, use the chart per the LavaCharts documentation:

<div id="my-chart"></div>
<?php
echo $chart->render('my-chart');
?>

You'll have to take care to include any JavaScript LavaCharts needs to function, of course.

Summary

That's it! You can use this approach to include anything from Packagist that you'd like. If your package is installed in concrete5, the on_start() method will be run, and the vendor autoload file will be included.

Loading Conversation