PHP framework for rapid prototyping
This structure facilitates other developers to quickly get into the project and efficiently create prototypes with fast database access and a flexible environment for own extensions.
No 3rd Party PHP Libraries are used for the essential workload of a MVC driven PHP engine.
Doxygen is integrated in the Documentation context for automatic HTML documentation.
The L10n mechanic will be integrated via Cascade ViewHelper.
The software can be customized and extended as desired, as it is intended to save time for developers.
As a developer, I wrote the same codes over and over for kickstarting standalone webapps. I repeated the same time-consuming steps for every prototype project. Sure, I could have used bigger frameworks like Typo3 (big inspiration for me), because of future compatibility and flexibility, but for small prototypes, i wanted to have my own reusable framework. Without the pain of complex version updates. Devworx is my personal framework, that was shaped by experience through many years of development.
The solution can be controlled in the frontend and API context via controllers and actions. The LoginHash can be provided by Cookie or via request header.
Devworx comes with the idea to use itself in different contexts, based on JSON configuration files. The available contexts are globally defined in the devworx.php and are used by the \Devworx\Frontend class.
The currently available contexts are Devworx, Frontend, Api, Development and Documentation.
See ./Public/.htaccess and Devworx\Cache\HtaccessCache to learn, how the context is determined by URI.
The solution can be configured via JSON files, based on the provided context, that are stored in the Configuration folder. These files are used to configurate the system itself, as well as as the frontend page.
See Context/Devworx/Resources/Private/Layouts/Page.php and Context/Devworx/Configuration/Context.json
Devworx comes with a powerful rendering engine named Cascade, that allows the user to perform logic and math inside the template, without switching to PHP.
Cascade parses a template character-wise with lookahead to identify nodes for the Abstract Syntax Tree. The code is interpreted into Nodes that can be compiled and evaluated.
Test-Szenarios: Context/Development/Resources/Private/Templates/Backend/Cascade.php
- Parser
- Character based Lexer mechanic
- Look-ahead
-
Interpreter
- Node based AST
- HTMLNode
- HTMLViewHelpers
- Datatypes
- Identifier
{a} - Constants
{true} {false} {null} - Number
{1.23} - String
{'hello'} - Object
{foo:'hello', bar:user.name, baz:false, bim:3.1415} - Array
{0:'hello', 1:user.name, 2:false, 3:3.1415} -
Context interaction
- Namespace aliasing
{namespaces.d = Devworx\ViewHelper} - VariableAccess
{user.name} - Assignment
{user.role = 'master'}
- Namespace aliasing
-
Operations
- Unary
{a++} {!a} {a ?? b} - Binary
{a + b} {a ** b} {a > b} {a !| b} - Ternary
{a ? b : c} - Variable comparison
{user.role == 'master' ? 'CHIEF' : 'WORKER' } - Array/Object merging
{foo:'bar'} + {custom:'value'} - Custom operators
{a !| b} {a !& b} {a !^ b} //nor, nand, xnor
- Unary
-
Functions
- Named and unnamed arguments
- Regulated PHP System Functions
{sqrt()}, {sin(2.31)}, {abs(-4.2)} - Function aliases
{tolower('ABC')} //strtolower - ViewHelpers
{d:format.currency(value:3.1415,decimals:2)}
- Result-Piping
{user.age * 3.1415 -> d:format.currency(symbol:'YEN') -> tolower()}
- Compiler constructs a precompiled concatenated array of strings inside a function call for caching
- Evaluator executes the logic of each Node and evaluates the results
- Caching works with a custom file cache, hashed by controller, action, context and variables
This context is used for internal mechanics like Login, Registering, Password Handling and Cache Management. This is basically the user interaction context
This context is used for the "normal" processing of the user frontend, like a Dashboard or the customized routines of your project.
For standard rendering, the Cascade\Renderer\CascadeRenderer is used.
This context is used for JSON based interaction, with controllers. To use the api context, you can either request ./api/ or provide the X-Devworx-Context header with the login hash of the user as the value.
As long as the cookie or the header is set, the api can be easily accessed with JavaScript fetch API.
For standard rendering, the Devworx\Renderer\JSONRenderer is used.
This context is used for automated documentation with doxygen and can be accessed by requesting ./documentation/.
To ensure doxygen is working, check the Context/Documentation/Configuration/Context.json configuration and Context/Documentation/Configuration/Doxygen.txt
If you want to regenerate the documentation, see DoxygenUtility or flush the Documentation cache via the action CacheController::flush.
Internally, the Documentation controller routes the HTML files of the Doxygen Documentation to the frontend via the action Documentation::show.
No renderer is used, because the files are routed directly.
This context is used for extending or maintaining the project. This includes managing models, performance tracking, file statistics and backups. This context is not finished yet.
Here you can test new features without affecting the frontend context directly.
All the utility classes, as well as some core classes, have static functions for easy reuse in different codes. The Devworx\Frontend class handles the whole architecture statically.
Controllers, Requests, Repositories, Models, Renderers and Views work by instancing.
Classes are loaded automatically by namespace. e.g.: Devworx\Frontend loads Context/Devworx/Classes/Frontend.php.
Utility classes such as DebugUtility make implementing debugging and error handling logic easier.
Exceptions are caught by an own Exception-Handler.
The Database class serves as a PDO database interface and is accessible by calling it statically. It contains basic functions for database interaction.
Database entries (aka Models) in Devworx have a basic structure that allows for easy data handling and mapping to any AbstractModel.
- uid PK int (Unique ID of the row)
- cruser int (UserID of the creation user)
- created timestamp (Creation timestamp)
- updated timestamp (Timestamp of last update)
- hidden tinyint (Hidden-Flag)
- deleted timestamp (Deletion timestamp)
The Repository class enables caching of schemas and easy access to specific database tables in controller context. It contains functions like findBy, findOneBy, findAll, put, add, remove and delete. System fields such as hidden and deleted are automatically added to the queries. Results can be mapped to Model-classes automatically.
The results of database queries are generally represented with associative arrays. Classes like ArrayWalker allow enriching relational data such as MySQL results to enable multidimensional results and additional data. Models can also be used to modify result handling.
The codes like classes and private resources are located in the root folder of the solution, but the frontend files are located in the Public folder, aswell as the JavaScript classes for all custom HTML elements and the API integration. The domain for the projects should point to the ./Public folder.
AuthUtility provides basic security functions that can be quickly integrated.
The LoginHash consists of the login name and password. The passwords are NOT stored in the database, only the hashes. The hash is used directly to retrieve user information from the database, also as the API key for JSON access.
The rendering is done via AbstractRenderer. Devworx contains multiple types of renderers.
- The
CascadeRendererenables Cascade Syntax in templates - The
FluidRendererenables very simple string templating with placeholders. - The
JSONRendererallows direct output in JSON
The solution uses the principle of layout, template, and partial. The layout provides the outer frame that is the same for all results and renders the corresponding template of the requested action. Partials are small code snippets that can be used in templates and layouts, as well as in the actions, to generate output.
See Devworx\View class for further clearance.
A distinction is made between private and public resources. Private resources are, for example, layouts, templates, and partials. Public resources are all styles, images, icons, and scripts. All private resources are located in the Context/{Context}/Resources/Private folder. The public resources are located in the Context/{Context}/Resources/Public folder. All root paths can be configured in the Context/{Context}/Configuration/Context.json files.
Bootstrap 5.3 and Material Icons from Google are used by standard. But it is easy to change the framework's styling via the configuration files.
The solution contains its own HTML elements to handle lists and formats. These are imported via JavaScript module. See Context/Devworx/Resources/Public/Scripts.
To ensure easy implementation, the custom elements inherit from AutoRegistering(HtmlElement), that provide the tag name and the base tag of the new element. All custom elements are loaded by module in /resources/Devworx/Script/Module.js.
The solution contains javascript addons for dialogs, toggle logic, confirming, formatting and a example for providing serverside rendered templates or partials.
The Devworx\Cache\CachesCache can collect different caches inside the context by reading Devworx/Configuration/Caches.json and optionally merged with {Context}/Configuration/Caches.json.
The Devworx\Cache\ClassCache can collect namespace information for the Devworx\Autoloader by suggesting the basic folder-to-namespace structure.
The Devworx\Cache\ConfigurationCache can collect a configuration array from Context/Devworx/Configuration/Context.json and merges with Context/{Context}/Configuration/Context.json
The Devworx\Cache\HtaccessCache can collect htaccess parts from the framework Context/Devworx/Configuration/Global.htaccess and from the contexts Context/{Context}/Configuration/Context.htaccess. Finally writes to Public/.htaccess
The Devworx\Repository features automatic file caching of MySQL database schemas. This allows type usage without database queries.
All models can be refreshed by analysing the MySQL table structure, checking getters and setters and rewriting the model files. use with care!
The code is documented with PHP doc-blocks, and the developer can use doxygen for building a html help structure for the complete code structure. Just provide a path to the doxygen binarys in the Context/Documentation/Configuration/Context.json.