Modular design for composer package - php

I'm working on a framework-like application, for which I would like people to be able to develop modules.
Modules add additional functionality to the core application by providing information to the core about their capabilities. Examples include modules for allowing access to MySql, or the file system or emails.
While modules can provide as much or as little extra functionality as they like, there is a Module class that is used to wrap the functionality provided, and each module should provide at least one of these classes to be included into the application.
Are there any guides or good practices on methods of module registration in PHP in the composer ecosystem. It would be additionally useful if the modules could provide aliases, and describe any configuration they require.
Clarification Edit
I have a core application, we'll call it example-app
Anyone using example-app should be able to introduce new functionality easily using the modular framework of the app.
So, let's say we have two modules example-module-1 and example-module-2. The app needs to know that these modules exist when it is run from the command line.
Everything should be managed from composer, so you will require the core application, and any modules that you wish to use with it. For example
"require" : {
"php": ">=5.5.0",
"example/example-app" : "^1.0",
"example/example-module-1": "^1.0",
"example/example-module-2": "^1.0"
},
What I would like to know is, is there a methodology for the modules to inform the core app at the time of installtion of their existence.
I already have a Module interface that imported modules can sit inside of, I just need a way to make the core app aware of where these classes are defined amongst all the other composer installed dependencies (e.g. I don't want to create a huge class list and step through each one doing instanceof).
The only thing I can think to do at the moment is to provide an additional companion app (something like bin/example-app-config) that each module calls as part of it's composer scripts. It could use cli parameters to tell the core app what the module class is called as well as any other requirements it has. However this doesn't sit right with me as it seems like it wouldn't be OS independent.

(I'm researching this topic and found your question from long ago.)
It looks like composer now supports enumerating installed packages by type that might help you achieve what you would like. Please see: https://getcomposer.org/doc/07-runtime.md#knowing-which-packages-of-a-given-type-are-installed

Related

How Symfony container collects vendor classes?

I am working on very old legacy code, mostly procedural. Trying to improve it. Rewriting applications is impossible right now. The plan is to add a few libraries which would help organize things and improve that way.
I added a Symfony dependency-injection component in order to do that. It would provide the possibility to fetch needed services with its dependency easy.
I watched symfonycast tutorial on how to play with container. And with that knowledge, I managed to write a simple loader to start the container and to use services made by me. It is simple, it guesses FQCN based on file path, and then uses reflection to get dependencies. But I can not figure out how to load vendor classes, because here you can not guess namespace that way. :)
The question is: What exactly Symfony uses to load classes from the vendor folder, does it reads composer.json files to see namespaces, does it uses some composer feature, or something else?
Loading classes is different than instancing services.
The first can in fact use regular composer facilities to discover vendored classes in a legacy project like yours, even if they weren't installed with composer. This uses the standard php autoload mechanism with some added magic.
To include the, let's say lib/ legacy directory in the discoverable files you would add the following to composer.json:
"autoload": {
"classmap": ["lib/"]
}
And then run composer dump-autoload. Note that by including vendor/autoload.php in your legacy files you could even forego the require directives for your dependencies and rely on composer as well. This can be a path for migrating them to composer-managed dependencies, too.
Service instancing requires not only being able to locate the classes themselves, but also their respective dependencies so the container can create the object tree automatically. This usually involves hand-writing service definition files: classes in the vendor/ folder are not automatically registered as services. A bundle (or your own definitions) enables support for an specific library.
Take for instance the Mailer component: you can use it as a standalone library, but for framework integration (which includes service definitions and depen) you'd need to install Mailer bundle as well.
The exception where automatic service registration applies (when using symfony framework, not the standalone dependency injection component) is for files under src/. During container compilation, services.yaml is loaded and the ContainerConfigurator with help from FileLoader, looks for *.php files the directories configured as a resource, creating service definitions for them.
I guess you could do a similar thing for your legacy dependencies in a CompilerPass by using a similar technique or by trying to leverage the composer classmap but, specially if your legacy dependencies do not follow a PSR loading standard, I'd advise against it, since it can pull in tests, example files, etc.

PHP, GIT, Location for reusable components

Thanks for your attention, this is a question of organization, I work with PHP and GIT for version control. I use Netbeans IDE to program, GIT integrated (although I am still a rookie).
Normally, I follow the approach that Symfony2 specifies for organize the project files, but I use my own framework for my projects.
The (main) question is: Any component or code part which has its own version control must be located under the /vendor/directory?
For example:
I have my project files in src\Acme\ProjectX\, also the utility package which use all my projects: src\Acme\Util\, and it is under the version control too (GIT).
and now let's remember the basic skeleton of a project based on Symfony or similar:
/app (application related elements)
/src (source code of the project)
/vendor (third party libraries)
/web (front end controller, the web directory, assets resources etc...)
So, Must be 'Acme\Util' included in the vendor directory? And, is necessary to use composer to declare the dependences?
In addition, the Utility package has a lot of classes but only few are used in projects. Must I remove those are not using by the project.
Summarizing, It will be nice if someone can contribute his knowledge for help me to represent an scenario like this.
I hope I could explained...
Thanks in advance!
Vendor directory
It's a good practice to separate external dependencies and the application code. If you are using Composer you can change it to something else.
Unused classes
Unused classes shouldn't matter if they aren't being loaded. They'll just take a bit of extra disc space.
It might be a good idea to separate the Utility package into multiple packages if you find yourself frequently using only a small part of it.
Dependency managers
It isn't necessary to use a dependency manager, but it sure does help. Having to install, configure and maintain everything manually (especially with many dependencies and sub-dependencies) would be a horror.

Automatically discover composer packages

I'm wondering what the best way (if there is a way) for an application to auto-discover [relevant] PHP "packages" installed by Composer.
My use case specific scenario:
I have a PHP app that includes my "framework" (for lack of a better word). This framework brings some basic functionality (routing, admin etc).
I'm slowly building in more advanced functionality, say, a blog module. This module is entirely self contained in it's own directory (but obviously has dependencies on the framework).
I'd like this blog module to be a self contained Composer package, so that I can selectively require the package in my app's root composer.json file.
Now, I need for the framework to know that it's there so that it can, for example, set the routing correctly and load up any admin functionality that the module requires.
What I've thought so far:
I'm relatively experienced in PHP, but "proper" OOP and autoloading is a little bit beyond my knowledge at the moment, so please forgive if there are inbuilt functions to do this. I don't even know what terms to Google!
I have thought I could maybe read the installed.json file which composer puts at vendor/composer/installed.php but I'm not sure how to set up my packages (e.g. blog) so they announce what they are. I'd like to future proof it so that I'm not looking for known module names (or regexing vendor or package names), but rather looking for packages to say "hey framework, I know you! You can use me!"
Maybe I can somehow instruct Composer (through the package's composer.json file) to stick in an arbitrary key/value pair in installed.json?
Any suggestions welcome, or directions as to what sort of Googling I should be doing.
Oh welcome to the world of managing dependencies on your framework.
I have some experience with auraphp, where we dealt with similar issue. You can read the blog post Composer-Assisted Two-Stage Configuration .
So what we finally ended-up adding https://github.com/auraphp/Aura.Web/blob/a3870d1a16ecd3ab6c4807165ac5196384da62cd/composer.json#L26-L36 these lines in the packages that need to understand to load by the framework.
You can also see how this bundle can also get autoloaded with the configurations.
in your composer.json
https://github.com/harikt/Aura.Asset_Bundle/blob/6ea787979390e69bf6ecb1e33ce00ed90f306e2f/composer.json#L21-L27
and the config/Common.php ( https://github.com/harikt/Aura.Asset_Bundle/blob/223126cedb460e486c4f0b242719c96c14be5385/config/Common.php ) , note we have other development modes also. For a detailed look check https://github.com/auraphp/Aura.Web_Project or https://github.com/auraphp/Aura.Framework_Project
Hope that helps a bit to look into the code and work on your own solution.

Laravel 4 plug-in system

I looking for some plugin structure for Laravel based applications.
For example a forum software, a cms or a e-commerce application can benefit from a plugin structure.
My question is what is the best way to implement this plugin system so that third party plugins can extend the application. The main issue is that it should be dynamically extendible and users should be able to install these plugins easily without messing with the app code.
This question also extends to themes but thats another question. Any ideas?
Laravel is a framework, not a CMS like Wordpress or Joomla, so plugin system that fits everybody may be quite hard to create as Laravel can be used in many ways, but I can really see the benefit of easy packages in some contexts.
The Packagist has been already mentioned and it doesn't solve directly your problem but how about:
Find good usable packages from Packagist for the purposes you need
Define common plugin architecture (common API for binding things together, installer, package format, migration, updates etc) on top of Packagist packages
Create installer that fetches packages via Packagist/Composer and adds sets sane default settings and configuration for the packages and integrates them into the defined plugin architecture
Document and plan this really well and the others will soon follow
I'm a little confused about the question, but I believe what you are looking for is already implemented in Laravel 4. They are just called Packages, and can be found at http://www.packagist.org and easily installed and autoloaded into your application using Composer.

PHP / MySQL stand-alone installer/updater script?

I'm looking for a script that will quickly implement package install/update functionality for my framework. It should be able to do the following things:
Must be PHP 5 compatible.
Should be able to install and update components' files and database tables.
Should allow defining of package dependencies and have a form of conflict resolving.
Should allow UPDATE SQL-statements when the developer of the package provides it. (To make database alterations without losing data).
Should be able to 'jail' an update package to a target folder.
Should be able to define and detect different package types to apply mentioned 'jail'.
Should provide an API to integrate it in custom backend.
Should allow downloading of the packages, preferably over HTTP (rather than FTP or others).
I plan on using this as a stand-alone utility to easily provide updates for modular frameworks as well as custom code for our clients.
If you have recommendations of tools that are similar or used in an open source framework to base it off that would be good as well. :)
I don't know of any magic tools to do this, but a couple that might help you do these tasks are Phrake and Composer.
Phake is a PHP version of Ruby's Rake util. You could use these scripts to set up your database, update files and run unit tests.
For package management you could use Composer to manage your dependencies (it can also download from PEAR if you depend on packages from those systems) and of course this could be incorporated into your build scripts.

Categories