Simple module system for CI3 |
03-31-2016, 06:29 AM
(This post was last modified: 03-31-2016, 08:24 AM by josepostiga. Edit Reason: Typo )
Hey devs. So, I've been working on a project that requires the use of multiple CI application folder: one for admins, other for the customers backoffice and a third one for the customers applications. It's a SaaS application and I didn't want to be using different controllers folders for each different scenario because, well, their basically 3 different apps!
During development, I've reached a point where I was repeating myself by copying and pasting the same helpers, configs, models, etc between those application folders. So, naturally, I checked the so called application packages, as described here: https://codeigniter.com/user_guide/libra...n-packages Unfortunately, that functionality only works inside each application folder and I wanted that outside those folders, so that I could share the code amongst every application. Composer wasn't a valid option here (I know you were thinking that by now, weren't you? ![]() So I went straight to the CI autoloader method, on the Core Loader class, and made a few changes. Simple changes, that would made possible for CI to handle packages outside the application folders. But enough talking. Let's get dirty. Step 1. The modules folder structure. I wanted something along this lines: /project-root/modules <- The modules base folder /project-root/modules/module-1 <- A wild module After this, the structure should be as documented here: https://codeigniter.com/user_guide/libra...n-packages, so CI should expect the config, helpers, models, etc... But then I though that it would be nice to have a "global" autoload config file to, well, autoload a specific set of modules. I could, in the end, still declare each module to autoload in each CI application instance but it could get messy when I need to remove, edit or update a module that's being autoloaded in X applications at some point down the road. That would be cool, I though, and keep things simple and organised. So, in addition to the structure shown above, CI should check for an autoload.php file on the modules root folder, like this: /project-root/modules/autoload.php The specific of that file is that any declared module to load should not have the folder structure declared. Further explanation on this on the next step. Step 2. The changes on the Core Loader class. Inspecting the code was pretty easy. The code is very well written and pretty self explanatory. The block modified was the _ci_autoloader method. The original code is as follow: PHP Code: protected function _ci_autoloader() The part about the packages is the one we're interested in, and that's the one I've edited. The final code: PHP Code: protected function _ci_autoloader($path = '') As you can see, I've added a recursion loader when checking for the packages. It would check for an autoload.php file, handle that, go to next cycle. Easy! And here's the autoload.php file: PHP Code: <?php Conclusions Of course this kind of hack to the core is a little messy, and needs careful handle when upgrading versions! But, finally, I could use my modules anywhere on those various CI application instances. I think it deserves the additional 2 minutes on each version upgrade. Also, I know this solution may have some limitations but we're all devs, and we can make things work to our own needs. I just wanted to share this mod with the community and I'd love to discuss it and know what's your thoughts on this regard. ![]()
Best regards,
José Postiga Senior Backend Developer
I used a custom module feature within APPPATH for TendooCMS, using config.xml file to store all module informations, such as version, namespace, name, description, author, language path, main file. You can test out this free app to see what i'm talking about http://nexo.tendoo.org
NexoPOS 2.6.2 available on CodeCanyon.
Another approach - just as something else to consider - is if the Backoffice needs something from the Admins - it gets it just like an API would - but in this case its an "internal" API. i've been surprised by how quickly you can wrap some data up in a JSON array and send it off with a few lines of CURL. you can even wrap database result objects in JSON and codeigniter treats them just the same as if they came from a local model. and you don't need a "rest server" - if this is a private API then you just need two lines of code in the receiving application controller method.
PHP Code: $request = file_get_contents('php://input'); it also opens up a bunch of options in terms of staging, having different applications on different servers, etc etc. |
Welcome Guest, Not a member yet? Register Sign In |