Modules and modularity, concepts that run through Jet like a red thread, as you have already noticed when reading the documentation. Yes, I like modularity very much and it has always worked well for me in practice and has brought only positive results. But what exactly is modularity? What is it good for? Why and how to "chunk" an application? There can be different perspectives on this. So first I would like to clarify how modularity is understood in the world of applications built with PHP Jet.
What is this modularity?
It may be an abstract concept, but in reality it is all around us. Everything around us is made up of some parts, basic building blocks, but they are interconnected, they can work together and form one functional whole. An example? How about a car? It has an engine module, an axle module, a brake system module, an electronics module (made up of a number of modules). Or a computer (whether it's a good old PC or a smartphone - it's still a computer). Yes, computers ... However, just look at Von Neumann's diagram. A computer is modularity itself (processor, memory, controllers, ...). But even our own body is modular. Every organ is a module, every limb is a module. Even human society is modular and we each play a role in it (we are modules ourselves). So modularity (in the sense of a whole made up of building blocks) is something quite natural and we see it at every turn. And it is natural to make applications this way as well. That is, to think of applications as a whole made up of building blocks. There are a number of huge advantages to this.
Advantages of modularity
If you design your application well, it will always be clearer than if everything is in one pile, so to speak.
- Work organization
"Franta, please, I need to edit the view of the shopping cart popup. I am sending the graphic. You can find it in the Shop.ShoppingCart module and it's view popup_content. Thanks!" This is very important when working in a team. Whether it's a small team or a company with dozens of projects and a bunch of employees, it's always important to communicate and organize work easily and efficiently. And modularity and the right application architecture design goes directly towards that.
- Code Reusability
Once you have a quiz module for your CMS, you can definitely use it on the next project where the client wants quizzes. You just copy a directory from another project and then you can tweak the view (and possibly other things) according to the client's wishes. That you don't have to do it again is clear. But more importantly you don't even have to prep it and from all sorts of places and directories. You just use and modify the module that is in one directory - no complicated searching.
Jet application modules
As I mentioned, the topic of modularity comes up a lot in Jet. The Autloader has its modules, the cache has its backends as modules, and so on. That's also modularity, but it's not the modularity we'll talk about here. As you might have guessed from, for example, the chapters on MVC, an application module is something more.
It can be said that application modules are micro-applications together forming the whole application and Jet provides the basic ecosystem for these micro-applications and ensures their basic integration.
What application modules can do
Installation / deinstallation
Modules can be installed and uninstalled. A module can have its own install/uninstall scripts.
For example, modules can remain installed but be temporarily disabled.
Meta Information and Manifesto
The module carries information about itself in the form of a manifest. This information can include common things like a description of the module, but also, for example, a set of ACL operations for the authorization system. You can extend this set of information in your applications and systems.
Custom application module classes
A module can carry its own classes. On the contrary, it must even carry at least one class marked as main - the Main class inheriting from Jet\Application_Module. But in addition to this main class and also controllers, a module can have other classes of its own that it needs (and that are not needed for other modules and parts of the application!)
As we will see in a moment, each module has its own namespace, whose name is determined by the exact concept.
Custom page definitions
We've already come across this in the MVC theme. The module can provide additional page definitions. In practice, this is mainly used for modules designed for administration and the like.
Custom menu item definitions
Similar to how the module defines pages, it can provide menu item definitions. Again, this is used in practice especially for modules intended for administration and the like.
Custom view scripts
Of course, besides the controllers, the module also needs its view scripts.
If the module needs some data for its work, it can be stored in the module directory.
Modules can work together
One module can get an instance of the other module (more precisely, its main class Main)) and work with it (of course, after checking the availability of the module). Thus, there can be and often is a binding between modules in real practice. The binding should ideally not be too tight (it should be taken into account that the required module is not available). But module interdependence is a common and desirable thing.
Modules can be marked as mandatorial
The module can be marked as mandatorial. This means that it must always be installed.
Location, layout, namespaces and module names
Modules are by default in the ~/application/Modules/ directory. Each module has its own directory. But beware! Directories can be nested. This is very important and makes it possible to group modules thematically. I highly recommend this. So a directory in the modules directory is not automatically a module, but there may be other subdirectories within it. A module is only the directory that contains the files manifest.php containing module metadata and Main.php containing the main module class.
The directory nesting is not only important for module organization and clarity. Directories and their nesting also make up the module name and namespace. Let's show this with an example of one of the modules in the sample application. As a guinea pig, let's take a directory that is in the ~/application/Modules/Content/Articles/Admin/ directory. This directory is the module named Content.Articles.Admin. Thus, the module name exactly matches the directory path. The only difference is that, for practical reasons, the slashes (which didn't work for me in practice) are replaced by periods. If I want to operate on a module somewhere, I will need this information - its name.
If you open the Main.php script in ~/application/Modules/Content/Articles/Admin/ (i.e. the file containing the main class of the module), you will see this:
So yes, the namespace of all module classes also corresponds to a directory. Let's stop at the namespace. This starts with the root namespace of JetApplicationModule. But nothing prevents you from defining your own root namespace for modules by system configuration.
Thus, the name and root of the directory where the module is located is the determinant of its name and namespace. Of course, you can rename or copy (clone) modules. Just change the directory and namespace in the module scripts - in practice, this is a trivial and useful operation.
Let's not just theorize, so let's reach again for one of the modules of the sample application and again for the Content.Articles.Admin module, which is designed for managing articles in the administration. On this module, let's discuss the typical directory layout of the module.
|Directory / File||Meaning of|
As the name suggests, this is the module installation directory.
(You may have noticed the _ at the beginning and as you already know, this directory is not supposed to be for the production environment - just for the record :-) )
The directory may (or may not) contain scripts called during module installation/uninstallation. In these scripts, everything necessary can be done. That is, create database tables, copy dictionaries to the main dictionary directory and so on.
In addition to the scripts, the directory can contain the necessary data for installation (e.g. files that the installation script copies somewhere, etc.).
None of this is mandatory. Installation/uninstallation works without this directory and scripts.
|As mentioned, the module can define menu items. This sample module defines its menu items in the administration menu.
Of course, it is not mandatory and a module that does not need the menu does not need to have this directory at all. Nor is it dogma that the menu must be for administration - on the contrary, the definition can be for whatever is needed.
|As you can see, the module defines a page for the base admin, which will be at the URL /admin/articles/ and the module itself will be available to users at this URL.
Again, not every module has to define some pages and the directory is therefore completely optional. Likewise, it is not dogma that page definitions should be for administration.
|And here are the view scripts of the module. The demonstration module has a view for the list of articles (list.phtml) and their editing (detail.phtml) in the administration.
None of this is mandatory. What kind of view the module will have, if any, is purely your business.
|If the module is to be used for MVC, it must have at least one controller class. The default is the Main control, but there can be more controllers.
However, if you are creating a module that will not provide content to pages anywhere and therefore will not need controllers, then of course it does not need to have any controllers.
|Listin.php||And another optional thing - just to illustrate and demonstrate what is possible. That being said, a module can have its own classes. And in this file there is a class for working with a list of articles. If a module has its own classes, they can of course be organized into directories following the same convention as the rest of the system.|
|Main.php||This is mandatory. The module must have a Main class that inherits from Jet\Application_Module (or from another class that must inherit from Jet\Application_Module). This class is the main point through which the module can communicate with the rest of the system and with other modules. Therefore, it is mandatory.|
|manifest.php||The file containing the manifest of the module, i.e. its metadata. This is logically required.|
Please also take a look at how modules are created, installed, activated, just how to work with them.