Basic Zend Framework 2 structures
When we consider the Zend Framework 2 structure, we must be aware that Zend Framework 2 doesn't actually care how our directory structure looks like, as long as we tell Zend Framework 2 in our configuration where all the paths can be found.
In the skeleton application we see that our configuration can be found in the config/application.config.php
file. But that file solely exists there because in the public/index.php
it is being loaded. If we, for example, want to change the location of that configuration file to somewhere else, we (in this case) only need to change it in the public/index.php
file. The same goes for the module and vendor directory, as these can be anywhere we like, as long as we tell the application.config.php
file where exactly that location is.
If we want to change the public directory, we can safely change it to any name we want, as long as we tell our web server where the new DocumentRoot
is. Obviously making a good structure is of course, the key to a successful application, and therefore the skeleton application was created. That doesn't mean that different structure requirements have to make us stop using Zend Framework 2, as the framework can be fully configured to such requirements.
However, we can assume that because we are using the skeleton made available by Zend, it displays a very optimal structure for us to develop in.
When we list the initial folder of our skeleton application, we note some of the following objects of importance:
config
module
public
vendor
init_autoloader.php
As we can see there are many objects in our folder, but these have no significant importance to our basic application.
Folder – config
The
config
folder consists of the following objects by default:
autoload/
global.php
local.php.dist
application.config.php
Probably the most important file in this folder would be the application.config.php
as it contains all of our main configuration options. If we open this file we can see that it has a couple of options set to make our application work.
The file contains, for example, the modules
key, which tells the framework which modules we need to load in for our application. It also contains the module_listener_options - module_paths
, which tells our framework where to find our modules and libraries, which modules and vendor are by default.
The config
folder also contains an autoload
folder, which in itself contains two files which are the global configuration override and the local configuration override files. Both files are empty by default.
Folder – module
The default
module
folder consists of the following important objects:
Application/config/
module.config.phpApplication/language/src/Application/Controller/
IndexController.phpApplication/src/Application/Controller/
IndexController.phpApplication/view/Application/index/
index.phtmlApplication/view/Application/error/
404.phtmlApplication/view/Application/error/
index.phtmlApplication/view/Application/layout/
layout.phtmlApplication/
Module.php
The application module gives away the basic structure that we would like to see when creating a new module. The most important file that we see here is the Module.php
, which tells the framework how our module is built up, where it can find our controllers, and many more.
Depending on how our application is built up, we would also want to have a configuration file for each module as we would like to keep the application as dynamic as possible. In the skeleton application we can see that our Module.php
contains a method called Module::getConfig()
; all it does is a simple include to the config/module.config.php
file. Although we theoretically could just define the configuration in the Module.php
,it is nicer if we separate the actual configuration file from our code, as that also brings a lot more maintainability with itself if we don't need to change the code for a simple change in configuration.
We can also see a language
folder in this folder, which contains all the i18n (short for internationalization as it contains 18 characters between I and N) files needed for translating our application. Although probably used by a lot of developers, not all of our application will require translation, so we might not need this folder at all in our project.
But if we do require i18n
and l10n
(localization) then it would be beneficial to do this module wise instead of application wise, again for maintainability as we don't want the application (which is the whole application) to define i18n/l10n
for all the modules, as theoretically not all of the modules have to be there. That is why working module oriented makes the code a lot more dynamic, but also maintainable as we can safely assume that if an error occurs in one of our modules, the problem also lies in that module.
The next folder src
might very well be one of the most interesting folders in our module, as it contains—as we might have guessed—the source of our module. The folder src
only contains another folder called Application
, which is the defined namespace of the classes inside.
Make sure that you name your subdirectories in src
to the namespace they are using. Otherwise it might not only lead to conflicts, but also confusion and inconsistencies. For example, if your module is called Winter
, then our directory should be called src/Winter
, to make sure that all our Winter
namespaces are in that directory. That way we can safely assume that all our code for that namespace has been neatly put in that directory and its sub directories.
The subfolder in Application
is in our skeleton application Controller
, which contains only the IndexController.php
. The IndexController.php
is an extension of the Zend\Mvc\Controller\AbstractActionController
, which is generally used for our day-to-day controllers; however, there is also the AbstractRestfulController
in the same namespace, which we can use if we want to create a restful service.
Next up is the view
folder, which contains all our view scripts. View scripts are basically template files we use to do the actual displaying to the user requesting the page. As we can see in the default module.config.php
of our Application
module, we have the view scripts configured to point to the view
directory, which tells the framework that when it needs to find any view scripts, it should look in that folder.
As we can see the view
folder is built up with the same structure as in the configuration file. The Application
folder refers to the namespace which is using this view script that is, Application
, then we see that there is also a layout defined, which is used as a global layout for our module—and the rest of the project if none is defined elsewhere—and an error
folder, that is only used whenever an error occurs in the application. If we want to read up more about how the layouts work in Zend Framework 2, you should take a look at Chapter 4, Using View.
Tip
The layout
folder and the error
folder are usually considered to be the main template files for the project. This does not mean, however, that we can only have one layout defined; all we need to do is just define another layout configuration in our module file, which makes a specific module different to the others.
That concludes the buildup of our module
folder, and when creating other modules—when using the skeleton application—it requires us to use the same folder structure.
Folder – public
The public
folder contains all of the files that the public may see. We need to make sure our application is secure, so we will only put images, style sheets, and JavaScript files in here. The only file related to the framework here, will be the index.php
file, as that is the file that initializes our application, and is used only when an HTTP request is made. Although we can put PHP files here, we would strongly recommend against it, as it can potentially make your project open for vulnerabilities.
Folder – vendor
The
vendor
folder contains—as the name suggests—libraries that are made by a third party. In our default project this will only contain the Zend Framework 2 libraries, which are needed to run the project (located in the zendframework/library
folder). Whenever we are going to use third party libraries like Smarty
or Doctrine
, these will be placed here.
Tip
If we have a homemade library that is (or can be) non application specific we would recommend putting it in here as well, especially if the library is maintained somewhere else. Once we begin scattering our libraries around in other folders, it is almost impossible to maintain consistency and maintainability.
File – init_autoloader.php
The init_autoloader.php
file makes sure our project can find the classes and namespaces we are trying to use. It is called by the public/index.php
file.
For the Zend Framework 2 to start up and configure itself, a couple of actions happen. If we use the skeleton application, the following flow of information can be assumed:
/public/index.php
: This is the first file that is going to be ran as that is the only public script file related to the application. When run, the script is including theinit_autoloader.php
in the root folder to the script and after that it initializes the Zend Framework 2./init_autoloader.php
: This file does exactly what it says it does, it initializes the autoloader. One of the best features of Zend Framework 2 is the extensity of the autoloader. All this file does is make sure the autoloader has most of the namespaces and classes that we use known (but not loaded up yet) before we go on and initialize the application, that way the autoloader can simply load up the class whenever it is requested. Although the skeleton application has a very lazy autoloader, which we shouldn't use in this form, in a production environment it can be a very powerful tool to create the best performance for your application.
What's next?
After the public/index.php
has loaded up the locations of known classes and namespaces, it is ready to start up the Zend Framework 2 MVC application.
Get the
config/application.config.php
file. It actually doesn't do anything with this file at the moment.Run the
Zend\Mvc\Application::init($configurationArray)
, where$configurationArray
is the variable that contains the read configuration from step 1.Initialization of the
ServiceManager
, which handles all the services in the application.Invoke
Zend\EventManager\SharedEventManager
.Factory
Zend\ModuleManager\ModuleManager
.Request the
ModuleManager
from theServiceManager
and run itsloadModules()
method.This will then resolve all the modules and load in the module-specific configurations.
Request the
Zend\Mvc\Application
from theServiceManager
.It will run the
bootstrap()
method.
The
public/index.php
will now execute therun()
method on the fully initializedZend\Mvc\Application
, which will make the sure the routing, which will trigger the bootstrap, route, dispatch, render and finish events, making sure the application has done what was requested of it.After the
Zend\Mvc\Application
has completed itsrun()
method, it will execute thesend()
method, which will send the output made by therun()
method back to the client.
Here is a flow chart diagram to show how the process goes a bit more graphically: