If you’ve dug into pestle, my command line PHP framework and Magento code generation tool, you’ve probably noticed it wasn’t super friendly to use pestle based code in your own PHP projects. That changes starting today. Pestle is now a packagist library, which means you can include it in your composer based projects with
//File: composer.json
{
"require": {
"pulsestorm/pestle": "1.0.*"
}
}
and then use any pestle function
<?php
//your framework probably takes care of requiring the composer autoloader
require_once 'vendor/autoload.php';
$xml = simplexml_load_string('<root/>');
//call any pestle function via a native PHP namespace
\Pulsestorm\Xml_Library\simpleXmlAddNodesXpath($xml, 'foo/bar[@baz=hello]/science');
\Pulsestorm\Pestle\Library\output($xml->asXml());
Coverage isn’t 100% at the moment — if you run into a function you can’t use please open an issue and let us know. The rest of this article goes into the nerdy details that most pestle users won’t need to worry about. Here be modules, compilers, transpilers, and dragons.
What is Pestle
Right now pestle is, first and foremost, an open source command line tool for generating Magento 2 code. It’s been vital to my writing about Magento 2 — being able to get someone started with a boilerplate module before jumping into an advanced topic is invaluable. Pestle’s users have also found it an invaluable tool in generating Magento 2’s endless 90’s-style java boilerplate.
While that’s pestle from an engineering product point of view, pestle is also a place where I can experiment with an alternate universe version of PHP where the system took inspiration from python style modules instead of java style classes. Specifically, one of the project’s goals is creating a python-like module importer that pulls in single specific functions from a module of code without polluting the global namespace. That’s what the pestle_import
function does.
I’m sure anyone with the word agile, scrum, or manager in their title is rolling their eyes and/or convulsing at this, but finding a way to incorporate wonk-ish software engineering projects into your work-life is vital as an engineer/programmer. While you would never set out to build a system like this for your clients, having built a system like this helps you understand third party systems that are similar.
The Problem
Unfortunately, PHP’s meta-programming around functions and namespaces (not to mention my free time to pursue this) isn’t as robust as I’d like. The current implementation of pestle_import
relies on exporting a number of includes and serialized files to /tmp/pestle_cache
and importing these into the current namespace when you run pestle.phar
. This felt like a reasonable trade-off for the phar
file/CLI runtime.
However, expecting folks who wanted to use pestle functions in their own application to deal with all these temp files didn’t seem reasonable. That’s where pestle’s new export_module
command comes in.
The export_module
command takes an individual pestle module.php
file and resolves the pestle_import
calls manually, replaces called functions with their namespace equivalents, and packages up the modules using PHP’s lesser known namespace bracket syntax.
We use export_module
to build the library/all.php
file. This file includes every pestle function, safely packaged up into their own namespaces. We selectively include this file with a little composer autoloader magic, and everything’s good to go for application developers.
The tradeoff here is, unlike the pestle.phar
and /tmp/pestle_cache
approach, every function is loaded, even if its not used. While not ideal, given the modern PHP landscape, what’s one more 7696 line file between friends.
Future Goals
Ideally, I’d like to get pestle to a point where pestle_import
and the autoloader library approach are identical. Whether that means changing the phar
to use a compiled/transpiled PHP namespace library or finding a clever way to have the autoloader selectively load functions without temp files remains to be seen. Fortunately, most pestle
users can remain blissfully unaware of these details and just use the CLI and/or composer library.
Do you have strong opinions about this sort of thing? I’d love to hear them. Open an issue, a pull request, or just yell at me on Twitter.