We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Truly modular Phalcon application

I have been working with phalcon for pretty long time and I belive I came to some point at which I think I can make it public.

Previously I have made this topic: https://forum.phalcon.io/discussion/17365/phalcon-is-not-trully-modular-framework-and-how-to-solve-it

Work done so far:

  1. Absolutely no code leaves modules directory
  2. Configuration files are in json (tho it wouldn't be a problem to make them yaml/xml etc)
  3. CLI support with option to add your own task (there are few built in tasks like generating modules, dumping routes etc)
  4. Migrations are inside modules, format is pretty much unchanged
  5. Router works differently than in phalcon, routes are read from configuration file
  6. All modules have option to inject services, initialize code etc.
  7. Modules are not simple arrays anymore, meaning you can get instance of any (or active) module class And much more

This is how app directory looks like: https://i.imgur.com/JhoJK6J.png (I probably should change plural to singular for some directories)

Each module needs to have a short definition:

{
    "name": "core",
    "version": "1.0.0",
    "enabled": true,
    "priority": 0
}

Modules are loaded by priority (i plan to add dependencies to them) Each modules have their own migrations which are executed automatically based on what is set in module_versions in database There is Acl and Auth module which implements basic auth and acl for:

  1. Routes
  2. Entities

Uses twig instead of volt because of few reasons:

  1. Nesting
  2. Namespaces (yes you can include templates from another module by: include '@modulename/some/template.twig'
  3. Overriding templates (crud generates twig template on the fly instead of relaying on templates)

But the biggest change is in routing because in phalcon, only the active module gets loaded. It isnt the case in my app. All modules are being loaded but only active one is executed. And routes are being kept in routes.json:

{
    "inventory": {
        "type": "crud",
        "prefix": "/inventory",
        "controller": "inventory",
        "children": {
            "import_from_tme": {
                "path": "/import-from-the-supplier",
                "action": "importFromTheSupplier"
            },
            "stocktaking": {
                "path": "/stocktaking/export",
                "action": "exportStocktaking"
            }
        }
    },
    "inventory_changelog": {
        "type": "crud",
        "prefix": "/inventory-changelog",
        "controller": "changelog"
    },
    "supplier": {
        "type": "crud",
        "prefix": "/supplier",
        "controller": "supplier"
    }
}

yes you can generate routes by name, there are 3 different types of routes like 'normal', 'crud', 'include'

Long story short: I think I have made phalcon trully modular, it needs some work to make it more proper and if anyone is interested in development of a skeleton let me know

  1. That would be a bad idea. I want modules to be autonomic. But maybe a local.config which would override a any module configuration if needed.
  2. Same as first point, a local config that would allow for modules to be overriden.
  3. Minor thing, can be done, can be improved

As for questions:

  1. I didn't yet implement forwarding but this could be done with little effort.
  2. CLI tasks? Any module can have its own task. Like core has https://i.imgur.com/0BG1y5V.png Auth has: https://i.imgur.com/eMC6WMh.png

Basically it finds any *Task.php inside Vendor/Module/Cli and executes it

My CLI is basically the same app as MVC but without http request. Phalcon devtools are not needed in my app. I've implemented generators in CLI like symfony does. For modules/migrations/etc. Im using few symfony components:

    "require": {
        "swiftmailer/swiftmailer": "^5.4",
        "symfony/console": "^3.3",
        "symfony/templating": "^3.3",
        "twig/twig": "^2.4",
        "ext-json": "*",
        "ext-fileinfo": "*",
        "ext-soap": "*"
    }

We can work something out if you are interested. But I don't want webpack. Im using just gulp for everything. My frontend is pure AngularJS with ES6 classes instead of functions. Even gulpfile is a class (which reads javascripts from modules - that needs some improvement as well)