99 lines
2.5 KiB
Markdown
99 lines
2.5 KiB
Markdown
|
Plugins in Phar Archives
|
||
|
========================
|
||
|
|
||
|
This is a short guide on how to create single-file portable plugins using
|
||
|
MakePhar.
|
||
|
|
||
|
|
||
|
## The workflow
|
||
|
|
||
|
1. Your application should export functions that can be called by the plugin
|
||
|
on load, such as `myapp_plugin_register` in the example below.
|
||
|
2. Locate the .phar plugins to load, and `@include` them one at a time.
|
||
|
3. Process the plugins etc that has been registered from the successfully
|
||
|
loaded .phar libraries.
|
||
|
|
||
|
|
||
|
## Example files
|
||
|
|
||
|
### src/plugin.php
|
||
|
|
||
|
<?php
|
||
|
|
||
|
// Prevent standalone use, as it doesn't make sense
|
||
|
if (!is_callable('myapp_plugin_register')) {
|
||
|
error_log("This is a plugin for MyApp and can't be used standalone");
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
// Register the plugin
|
||
|
myapp_plugin_register(new MyPlugin\MyPlugin());
|
||
|
|
||
|
### composer.json
|
||
|
|
||
|
{
|
||
|
"autoload": {
|
||
|
"files": [ "src/plugin.php" ],
|
||
|
"psr-4": { "MyPlugin\\":"src/" }
|
||
|
}
|
||
|
}
|
||
|
|
||
|
### makephar.sdl
|
||
|
|
||
|
phar "myplugin.phar" {
|
||
|
library;
|
||
|
include {
|
||
|
dir "src";
|
||
|
dir "vendor";
|
||
|
}
|
||
|
exclude {
|
||
|
dir ".git";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
## Notes and Considerations
|
||
|
|
||
|
* Try not to bundle unneccesary or duplicate dependencies using composer. It is
|
||
|
possible to include multiple composer `autoload.php` files (as is done when
|
||
|
including the phar libraries) but effectively only the first matching loader
|
||
|
will be used. Thus, if you have required a library in the plugin that is also
|
||
|
present in the main application, the main version will be loaded rather than
|
||
|
the plugin version.
|
||
|
|
||
|
|
||
|
|
||
|
## Problems and Solutions
|
||
|
|
||
|
### Getting the directory of the running phar
|
||
|
|
||
|
You can get the path of the command invoked using `$_SERVER['SCRIPT_NAME']`:
|
||
|
|
||
|
$root = dirname($_SERVER['SCRIPT_NAME']);
|
||
|
|
||
|
Note that the script *can* be a symbolic link, in which case you need to call
|
||
|
on `readlink` before you call `dirname`:
|
||
|
|
||
|
// Get the path of the script, eg. /usr/bin/myapp
|
||
|
$root = $_SERVER['SCRIPT_NAME'];
|
||
|
// Unwrap the links, eg. /usr/bin/myapp -> ~/myapp/myapp.phar
|
||
|
while (readlink($root)) {
|
||
|
$root = readlink($root);
|
||
|
}
|
||
|
// Finally get the directory (~/myapp)
|
||
|
$root = dirname($root);
|
||
|
|
||
|
Use this to locate your plugins.
|
||
|
|
||
|
### Find out if running from within a Phar
|
||
|
|
||
|
You can easilly find out if running from within a .phar archive by calling
|
||
|
`Phar::running()`.
|
||
|
|
||
|
if (Phar::running()) { inside_phar(); }
|
||
|
|
||
|
This doesn't make sense to use in phar plugins, as the main application can
|
||
|
also be in a phar, in which case it will be true even for non-phar plugins.
|
||
|
|