A new FuelPHP is in the process of being born!
Over the last month, we finally found the time to work on what will become FuelPHP v2.0, and we're moving fast. There's still a lot to do (see the todo list for 2.0-alpha), but in general the new version is taking shape, with more features completed every day.
Time then to highlight some of the changes, and explain what the impact of these changes will be.
The old 'frontend' package (fuel/fuel) has been split into a new 'frontend' (fuelphp/fuelphp) and an 'application' (fuelphp/demo-application) composer library. In the application folder itself you'll find the typical Fuel folder structure: classes, config, lang, modules, views. This split means you will be able to upgrade through Composer, without impact to your application code.
In the classes folder, view has been renamed to Presenter. Besides this folder, you'll find the Controller, Model, Migration and Task folders, which are now separate namespaces, and all autoloadable. The Routing engine can route to controllers (default), tasks and migrations. The last two will be used by the oil front controller. This also means that tasks and migrations are no longer something special, but will be created the same way as controllers.
In your Application you'll also have folders for cache, logs and tmp. There are discussions to move these all to a var folder to clean up the application root a bit, but that hasn't been decided yet.
If you use Composer to install your applications too, we have provided a Composer installer to have them automatically installed in the correct folder, ready for the framework to use.
As already mentioned, version 2.0 will have everything setup to be installable using Composer. The framework itself has been split into several packages, all Composer installable, and most of them designed to be framework independent. Using Composer throughout also makes it easy to include other Composer libraries, available from Packagist or another by Composer supported platform.
By default FuelPHP will now use the PSR-0 standard for classloading. Its implementation is actually a superset (the PHPFIG has suggested this will be PSR4), but it is fully compatible with PSR-0.
We also decided to adopt PSR-1, which means that instead of
snake_case names the methods & variable names are now
And just to be complete, we have not adopted PSR-2, which is not a standard in our opinion, it's a religion. As a coding standard, we will continue to use the current standard, taken the changes related to PSR-1 into account.
In FuelPHP v1.x, you had Modules, and you had Packages. Modules were defined as extensions to the frontend, the application, and Packages were defined as extensions of the backend, the framework core. This has been changed.
In 2.0, a new concept of Application is introduced. A single installation can contain multiple applications, which can have separate frontloaders or a single frontloader with logic to determine which to call, but can also call each other. You can for example decide to have a frontend application and a RESTful API driven backend application, installed in the same FuelPHP installation. When you need to scale, simply move one of the two to a second server. Or you want to split the frontend of your application from the admin interface, but still allow them to talk to each other. Applications are completely isolated from each other, with separate environment and config, and no direct access to each others data or code. Oil, the current commandline tool for code generation and batch operations, will be rewritten as a separate Application.
Every Application will have it's own configuration, environment settings, etc. You can even run one in 'development' mode, and one in 'production' mode, of the same FuelPHP installation!
Within an Application, you can have modules. They will have much more functionality then they have now, so there will be no need anymore to find alternative solutions for frontend modularity.
A module can:
The features of the current module system, such as fallback to the application or core level for config, lang and views, will remain.
Packages will no longer exist in the current sense of the word. They will be replaced by Composer libraries (which a lot of people call packages, probably due to their repository being called packagist, but according to the composer documentation, you should use the word "library". So we will).
Composer libraries may contain a PackageProvider (we might have to revise this name...) class, which serves two purposes. One is to replace what is currently the bootstrap, used for initial setup and preparation for when the library is loaded (by Composer in this case). Within the Application, you can enable or disable a loaded library. Only enabled libraries can be accessed by your Application. The provider class also contains methods to perform construct or destruct actions when you enable or disable a library. Note that happens per application, so make sure nothing is done globally!
A library can contain the standard composer functionality, adding classes to enrich the backend or framework functionality, but can also contain a 'classes' folder structure in which you can place a module. Or a 'modules' folder with multiple modules. It is the task of the PackageProvider to inform the application that the module exists, where to find it, how to call it, etc. This will make your application very extendible.
Like in 1.x, version 2 also have a static interface to most of the frameworks functionality. Unlike 1.x, this interface doesn't provide just static (and therefore global) methods, it operates on an instance of either the same class or the class it is designed to be a facade for. Which specific instance depends on the type of instance being called, and the context in which you call it.
In 2.0, core classes are layered in a context hierarchy. Every class lives in a one or more specific contexts. Any FuelPHP installation will have the following contexts:
2.0 will have full multi-lingual support. That starts with the framework itself, where Exception messages from the core classes will be shown in your servers system locale. Every Application will keep separate language containers for every language you activate. Which means that contrary to version 1.x, you can use multiple languages within a single request. Loading a language file for one language will no longer overwrite one previously loaded for another language.
Language operates within the Application and Request context. Everything you load at the Application level will be available to all requests, language files you load within the context of a Request will only be available inside that request, and possible sub-requests.
Configuration now operates within the Global context and the Application context. Within the global context you will find all configuration related to the server, the PHP installation, or the framework installation as a whole. Think about locale, timezones, etc. Within the Application context you'll have all your application specific settings, like security, routing specifics, etc.
Input operates in the Global context and the Request context. In the Global context, all external input (GET/POST/PUT/DELETE/PATCH) will be processed and stored. Every Request will have it's own Input instance, to which you can pass the HTTP method to simulate, and the all input you want to pass on, up to simulating cookie data and file uploads.
For all classes that operate in multiple contexts, an automatic inheritance system is implemented, which will allow you to transparently access data made available by the instance one up in the class hierarchy. Updating such a value will only update the current instance, and will not impact data stored at higher levels.
When you use one of the Facade classes in your application, they will detect the current context when you call them, and will use the correct object for that context. For example, if you would use
\Input::get() in your Controller, it will know it operates in the Request context, it will know which Request, and will give you all GET variables assigned to that request, together will whatever GET variables are inherited from it's parent instance.
Version 2 will be completely driven by a very versatile and fast Dependency container. It allows you to store class references, define identifiers (aliases) for classes, and define the type (singleton, multiton, etc). It also supports specific and generic extensions that you can hook into a class definition, and will run upon instantiation of a class. This can for example be used to inject external dependencies at runtime, completely transparent to your application.
Every FuelPHP specific composer library can be equiped with a ServiceProvider class. It replaces the current package bootstrap mechanism, and can be used to run specific setup code for the library. The ServiceProvider can also contain a
provide() method that will inform the Dependency container which classes or identifiers are provided by the library, and can contain the class registration and extension code required to instantiate such a class. This mechanism will allow you to create framework agnostic libraries, that use the ServiceProvider to make their functionality available to the framework.
As the name lead to much confusion and discussion about CamelCasing of the name we decided that it is time for a better name. ViewModel is the name the concept has in MVVM (Model-View-ViewModel), but it similar to the MVP (Model-View-Presenter) concept, which we think provides better clarity about its function. They will remain very much optional though and FuelPHP will remain MVC.
The old v1.x. Query Builder needed to go, we have been unsatisfied with it for some time - especially its lack of real platform independence. 2.0 will introduce a new Query Builder or DataBase Abstraction Layer (DBAL), more object oriented, more and more advanced features, and fully platform independent. Upon release there will be support for MySQL, PostgreSQL, MSSQL and SQLite, but more will follow.
2.0 will also come with a new version of Fuel's famous ORM. Completely refactored, and event driven to allow you to plug optional functionality in without problems. Need a model that supports both Nested sets, versioning, and soft-delete? No problem, you can mix-and-match!
Most of the model definition will be converted into a more object oriented approach, doing away with the sometimes complex array structures you have to create in the current version. Object oriented access is the preferred way of working, the complex array structure used by the current find() method will no longer be used (but will be available in the legacy support pack, if we can make a compatible version).
Migrations will no longer be special classes with an awkward namespace and naming system, they will be Controller alike, and autoloadable like all other classes. The flat hierarchical system with sequence numbers will be replaced by a dependency system. Migrations without dependency can run in any particular sequence, those with dependencies will run in order of their dependencies. Migrations will be tracked in a tree-like structure, to reflect the dependencies, and to detect any circular dependencies (which would be a bad thing!).
We also want to look into possibilities for migrations that always run (everytime to do a migrate run), automatic rollback in case somewhere in the chain a migration fails, and to add options for database seeding and generation of (random) test data. And we're looking into options to capture, log, and process migration results.
Oil will become an Application within the new version of FuelPHP. This means it has an Application wrapper class and its own internal routing. Its own Front Controller is still named
oil (without extension) and has almost no differences with the normal
index.php front controller. We're thinking about giving oil a web interface (in a future version), so you can run commands and generate code without needed a commandline.
Tasks will be reimplemented as Controllers in the "Tasks" namespace, which means their methods require an 'action_' prefix and they're inside a subnamespace of the Application. The routing to these Tasks works through the normal routing mechanism, but requires switching the Routing engine from "Controller" to "Task" mode. When using the oil front controller, this will happen automatically. The Request class will facilitate this when you want to call a Task method from your application controller.
All current Oil command-classes will be reimplemented as Tasks.
A complete new documentation system will be created. It will be driven by Markdown for easy maintainability, and will have a functional focus instead of an API / Class focus. This means it will resemble more of a "howto" collection, and less of an enless list of method definitions. If you want API information, we will also provide an API browser, generated by PHPDocumentor, for direct access to class and method information.
There are ideas to link the documentation to the FuelPHP paste bin, so that you can find all snippets posted publicly using the paste bin, related to the subject you have been reading. We will still provide static HTML versions of the documentation, for those who want them available offline.
We'll provide as much backwards compatibility for 1.x as is possible. Some things will need a bit of search & replace, though doable project wide if your IDE/texteditor is capable of that.
Other things will require a little bit of rewriting, migrations are an example of that as mentioned. Any Core extensions will not and cannot be backwards compatible for the most part.
Also, code that has directly accessed class properies might need changing, as properties are no longer exposed by default, but require you to use getters and setters (some classes will provide a magic methods for property access, but not all).
As always, we're looking forward to your feedback. Other features you want to see? Suggestions for further improvements? Let us know, or hop onto IRC (#fuelphp) to discuss them in person.