Adding Custom Code Libraries in a Package
Packages will often need to include custom PHP code for some of their
functionality. For example, when adding our custom event to the
on_start()
method, it will be smarter for us to include this
functionality in a separate custom script, rather than directly in the
on_start()
method. So instead of this:
public function on_start()
{
\Events::addListener(
'on_page_view',
function ($e) {
$c = $e->getPageObject();
// do something with the current page object
});
);
}
Let's do this:
public function on_start()
{
$listener = new \Concrete\Package\Statistics\Src\Page\PageListener();
$listener->addListeners();
}
Let's look at this class. Anything preceded with
\Concrete\Package\PackageHandle\Src
will automatically map to
packages/package_handle/src/
. From this point forward, everything
within the src/
directory must exactly match the class casing. So
our class would be located here:
packages/statistics/src/Page/PageListener.php
and its namespace
would be Concrete\Package\Statistics\Src
. This is the automatic
namespace for any custom code found inside a package's src/
directory.
Removing \Src from Package and Application Class Files
In early versions of 5.7 we automatically mapped everything inside of
Concrete\Package\YourPackage
and Application\
that wasn't already
covered by an autoloader mapping into the src/
directory. This led to
attractive class names like this
Concrete\Package\MyPackage\ServiceProvider\Provide
→
packages/my_package/src/ServiceProvider/Provider.php
Unfortunately, this led to ambiguities. For example, if someone
creates a file at packages/my_package/src/Block/Updater.php
and
references it using \Concrete\Package\MyPackage\Block\Updater
– we
don't know whether to load from src/
or from the blocks/
directory
found inside my_package
. For this reason, we've added \Src\
to the
namespace of all files loaded from a package's src/
directory or an
application's src/
directory.
This isn't ideal; it's ugly and semantically unnecessary. It communicates more about Concrete CMS's implementation of autoloading than an application really should. With that in mind, we've introduced some configuration options for packages and custom code to eliminate this segment.
Fortunately, 5.7.4 makes it easy to ignore this and work around it in a couple different ways.
Registering Custom Autoloaders
First, you can easily register custom autoloaders to points within the
src/
directory. Let's say instead of
Concrete\Package\Statistics\Src\Page\PageChecker
we wanted to map this
to MyVendor\ConcreteStatistics\Page\PageChecker
. We'd just add this to
our controller.php
protected $pkgAutoloaderRegistries = array(
'src/MyVendor/Statistics' => '\MyVendor\ConcreteStatistics'
);
Now, anything found inside src/MyVendor/Statistics/
will begin its
namespace with MyVendor\ConcreteStatistics
. So our page checker's
class would be
namespace MyVendor\ConcreteStatistics\Page;
class PageChecker
{
}
And the file system would look like:
packages/statistics/src/MyVendor/Statistics/Page/PageChecker.php
and out on_start()
method would look like this:
public function on_start()
{
$listener = new \MyVendor\Statistics\Page\PageListener();
$listener->addListeners();
}
Removing \Src
from Concrete\Package namespace.
The above example works well for custom code, but what about the
Concrete\Package
namespace? This namespace is automatically
generated for many things. For example, if you want to include a
custom Captcha library in your package, you'll normally need to make
sure a file is present at
packages/your_package/src/Captcha/YourCustomCaptchaController.php
and its class is automatically generated as
Concrete\Package\YourPackage\Src\Captcha\YourCustomCaptchaController
.
Fortunately, you can remove \Src
from this namespace as well. Just
add this boolean to your package's controller.php
:
$pkgAutoloaderMapCoreExtensions = true;
and make sure that you move any auto-mapped src/
files from within
packages/your_package/src/
into
packages/your_package/src/Concrete
.
From there on, all files found in src/
in your package no longer need
to have \Src
in their namespace. Your custom captcha controller's
class would be
namespace Concrete\Package\YourPackage\Captcha;
class YourCustomCaptchaController
{
}
And the file system would look like:
packages/your_package/src/Concrete/Captcha/YourCustomCaptchaController.php
.
Intermingling Approaches
These autoloading approaches are complimentary. You can define
multiple custom autoloaders as well as the autoloader core extension
map boolean. Everything maps to within the src/
directory.