PHPackages                             vukbgit/simplex - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. vukbgit/simplex

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

vukbgit/simplex
===============

Simplex

v3.15.37(1y ago)1929MITPHPPHP &gt;=8.2

Since May 17Pushed 1y ago1 watchersCompare

[ Source](https://github.com/vukbgit/simplex)[ Packagist](https://packagist.org/packages/vukbgit/simplex)[ RSS](/packages/vukbgit-simplex/feed)WikiDiscussions development Synced 3d ago

READMEChangelog (5)Dependencies (28)Versions (353)Used By (0)

Simplex
=======

[](#simplex)

A tool for web developers

### Table of Contents

[](#table-of-contents)

- [Introduction](#introduction)
- [Requirements](#requirements)
- [Terminology](#terminology)
- [Pre-Installation - Upgrade Jobs](#pre-installation---upgrade-jobs)
- [Installation](#installation)
- [Upgrade](#upgrade)
- [Post-Installation Jobs](#post-installation-jobs)
- [Area set up](#area-set-up)
    - [Backend / ERP](#backend--erp)
- [Subject set up](#subject-set-up)
- [Debugging](#debugging)
- [Internazionalization](#internazionalization)
- [Emails](#Emails)
- [Icon Fonts](#Icon-Fonts)
- [Development to Production](#development-to-production)
- [Simplex Logic overview](#simplex-logic-overview)
    - [Logical Structure](#logical-structure)
    - [Application Flow](#application-flow)
- [Folders and Files Structure](#folders-and-files-structure)
- [Migration from v1 to v2](#migration-from-v1-to-v2)
- [Considerations](#considerations)
- [API Documentation](#api-documentation)
- [References](#references)

Introduction
------------

[](#introduction)

Simplex is a tool for developing PHP/HTML/CSS web applications. In short, it sets up a handy environment so you hopefully only have to code files specific to the project business logic: PHP (classes and some configuration file), HTML ([Twig](https://twig.symfony.com/doc/2.x/) templates) and CSS or [SCSS](https://sass-lang.com/).

The goal of Simplex is to provide:

- the structure for a PHP web application that is a compromise between:
    - simplicity
    - the latest standards and practices (as far as I know)
- a quick and easy way to get started developing code for the application

To do so Simplex relies on:

- [Composer](https://getComposer.org) packages (by means of [Packagist](https://packagist.org/) packages):
    - Simplex itself is a Composer package that:
        - takes care of installing the required libraries (for at least the minimum functionalities)
        - creates the basic starting structure for the application with some draft files almost ready to be used but that can be deleted, modified and integrated at need
    - other selected Composer packages are integrated to create the application core engine
- [NPM](https://npmjs.com) for Javascript and CSS packages
- [Bootstrap](https://getbootstrap.com/) as CSS framework
- [Fontello](http://fontello.com/) for icons

*NOTE ON THIS DOCUMENT*: I will try to be clear and write down all the details to understand and use Simplex, for future-me, any possible colleague and anyone else interested benefit

Requirements
------------

[](#requirements)

- server on Linux OS (mainly tested on Debian 10/11)
- webserver: Simplex has always used [Apache 2.4+](http://httpd.apache.org/), .htaccess files are used for basic routing; I guess it *could* be used also [Nginx](https://nginx.org/) also but it has ever been tested
- [PHP 8.2+](https://www.php.net/downloads.php) with the PHP [gettext](http://www.php.net/gettext) bcmath extensions enabled
- ssh access to web space: on a shared hosting it's hard to use Composer (and Npm and Sass), you have to develop locally and commit, but I really suggest to find a provider who can give you ssh access; once I tried the power &amp; comfort of the ssh shell I rented my own virtual machine and never turned back to shared hosting again...
- [Composer](https://getComposer.org) aliased (globally or locally) as `composer` command
- a frontend package manager: Simplex suggests [npm](https://www.npmjs.com/) installed globally:
- [Sass](https://sass-lang.com/) (I currently use version 1.56.1 compiled with dart2js 2.18.4): to compile css with variables, mixings and many other useful additions and customize bootstrap

Terminology
-----------

[](#terminology)

- **root**: the top folder of the Simplex installation, usually the top folder in the web accessible part of the site web space
- **application**: the customized installation of Simplex for the specific project/domain
- **private**: area of the application hidden from browsers
- **public**: area of the application open to browsers
- **share**: area of the application where third part libraries and files are store, mainly *private/share* for [Packagist](https://packagist.org/) PHP libraries and *public/share/node\_modules* for [npm](https://www.npmjs.com/) frontend packages
- **environment**: in which the current request is handled, Simplex assumes the values of "development" and "production" but it's possible to define other variants on a per installation basis
- **area**: a part of the application matching a set of routes having properties, requirements and behaviours in common, i.e "Backend", "Frontend", "Cron", every route must set an 'area' parameter and it should be formatted as a [slug](https://en.wikipedia.org/wiki/Clean_URL#Slug)
- **subject**: into an ERP area, a subject is the name of the system formed by:
    - a controller
    - a set of routes handled by the controller
    - the set of actions corresponding to these routes
    - the controller methods corresponding to these actions
    - the model each of this actions operate on
- **action**: the specific logic associated to a route, i.e. 'list' or 'save-form', every route must set an 'action' parameter and it should be formatted as a [slug](https://en.wikipedia.org/wiki/Clean_URL#Slug)

Conventions:

- in the following explanation files and paths are written in *italic*
- for each file is always given the path from the root, without leading slash

Pre-Installation - Upgrade Jobs
-------------------------------

[](#pre-installation---upgrade-jobs)

Before installing from scratch or upgrading from 2.x:

- download [ini config file draft](https://github.com/vukbgit/simplex/blob/development/installation/config.draft.ini)
- save it into web space **outside** root folder as *config.ini*
- edit and set at least mandatory values following comments
- set permanently the PATH\_TO\_INI\_CONFIG environment variable to the absolute path to the file, adding to system user .bashrc file (usually something like *home/user-name/.bashrc* ) the file

    ```
      export PATH_TO_INI_CONFIG=absolute/path/to/config.ini

    ```
- if logged into same console where installation/upgrade will be executed, log-out to make $PATH\_TO\_INI\_CONFIG available to scripts

Installation
------------

[](#installation)

Create a composer.json in the root folder:

```
{
  "type": "project",
  "name": "vuk/simplex",
  "description": "Simplex app",
  "license": "MIT",
  "require": {
    "vukbgit/simplex": "^3.0"
  },
  "config": {
    "vendor-dir": "private/share/packagist",
    "bin-dir": "./"
  },
  "autoload": {
    "psr-4": {
      "Simplex\\Local\\": "private/local/simplex"
    }
  },
  "scripts": {
    "post-create-project-cmd": [
      "SlowProg\\CopyFile\\ScriptHandler::copy"
    ],
    "pre-update-cmd": [
      "Simplex\\Refactor::preRefactoring"
    ],
    "post-update-cmd": [
      "Simplex\\Refactor::postRefactoring"
    ]
  },
  "extra": {
    "copy-file": {
      "private/share/packagist/vukbgit/simplex/installation/": "."
    }
  }
}

```

Notes: for version constraint (^3.0) check last tag on github repository or non-develop version number on packagist.

Create the Composer project running on command line in the root folder:

```
    composer create-project

```

Simplex will:

- install itself and the other required Composer libraries
- copy in the root directory some files
- make symlinks in the root directory to some shell scripts ([Composer vendor binaries](https://getcomposer.org/doc/articles/vendor-binaries.md))
- build the folders structure for the local application with some ready draft files

For details see [Folders and Files Structure](#Folders-and-Files-Structure) below

Upgrade
-------

[](#upgrade)

### From 2.x version

[](#from-2x-version)

- follow [Pre-Installation - Upgrade Jobs](#Pre-Installation---Upgrade-Jobs)
- add into composer.json to the "scripts" array the post update refactoring script:

    ```
    "post-update-cmd": [
      "Simplex\\Refactor::postRefactoring"
    ]

    ```
- run the `composer upgrade` command
- look into output for any message that requires an action
- eventually examine the refactoring logs saved into *private/local/log*
- add into composer.json to the "scripts" array the pre update refactoring script:

    ```
    "pre-update-cmd": [
      "Simplex\\Refactor::preRefactoring"
    ]

    ```
- if necessary add to .gitignore `private/local/simplex/log/`

### From a 3.x version less than 3.13

[](#from-a-3x-version-less-than-313)

- take note of current version, i.e. `./composer.sh show vukbgit/simplex`
- update composer packages: `./composer.sh update`
- call refactor.php for PRE stage with old version, i.e.: `php8.2 private/share/packagist/vukbgit/simplex/bin/refactor.php pre 3.4.0`
- call refactor.php for POST stage, i.e.: `php8.2 private/share/packagist/vukbgit/simplex/bin/refactor.php post`
- look into output and logs for any message that requires an action
- add into composer.json to the "scripts" array the pre and post update refactoring script:

    ```
    "pre-update-cmd": [
      "Simplex\\Refactor::preRefactoring"
    ],
    "post-update-cmd": [
      "Simplex\\Refactor::postRefactoring"
    ]

    ```
- if necessary add to .gitignore `private/local/simplex/log/`

Post-Installation Jobs
----------------------

[](#post-installation-jobs)

- *config.ini*:
    - should be already in place (see [Pre-Installation - Upgrade Jobs](#Pre-Installation---Upgrade-Jobs)) with minimal configuration (otherwise nothing works...)
    - use this file to store any local information that must be as secret as possible like database credentials, passwords, secret API keys, etc.
    - simplex bash scripts all include *private/share/packagist/vukbgit/simplex/bin/bootstrap.sh* which needs to include *config.ini* so path (absolute or relative to the top level called script) must be provide as:
        - the PATH\_TO\_INI\_CONFIG environment variable, which you can export as `export PATH_TO_INI_CONFIG=path/to/config.ini`:
            - temporarily into ssh session
            - permanently into *home/user-name/.bashrc* (or equivalent, which you shold already done before installation)
        - or passing to the called script the -i option followed by the absolute/relative path to the ini config file, i.e. `simplex-script.sh -i path/to/config.ini`
- */.htaccess*:
    - set default redirections, i.e */backend* to */backend/sign-in-form*; in any case either you're going to define a route for the plain domain request or you redirect domain request to a default route (i.e. `RewriteRule ^/?$ /my-default-route [R,L]`); for routes definitiosn see below
- **index.php**: set `$pathToIniConfig` to the absolute o relative path to ini config file
- install **public** packages:
    - the *public\\share\\package.json* file contains some NPM packages for:
        - the whole application:
            - [bootstrap 5](https://getbootstrap.com)
            - [jquery latest](http://jquery.com/)
            - [js-cookie](https://github.com/js-cookie/js-cookie): javascript library to handle cookies
            - [mjml](https://www.npmjs.com/package/mjml): for responsive emails creation
            - [fontello-cli](https://www.npmjs.com/package/fontello-cli): to download Fontello icons
        - backends or enterprise web applications (ERP) mostly (even if they can be useful also in frontend development):
            - [bootstrap-fileinput](https://plugins.krajee.com/file-input): for asyncronous file upload. NOTE: as for 2019-11-12 version is frozen to 5.0.4 due to a bug in auto upload
            - [flatpickr](https://github.com/flatpickr/flatpickr): for date time picker
            - [jodit](https://github.com/xdan/jodit): for richtext input
            - [select2](https://select2.org): for richselect input with autocomplete, with [select2-theme-bootstrap5](https://github.com/angel-vladov/select2-theme-bootstrap5) for skinning
            - [hamburgers](https://github.com/jonsuh/hamburgers): CSS hamburger animated icons
            - [fullcalendar](https://github.com/fullcalendar/fullcalendar): full-sized event calendar
        - frontend
            - [jquery.safemail](https://github.com/leftclickcomau/jquery.safemail): for obfuscating email
            - [flag-icon-css](https://github.com/lipis/flag-icon-css): SVG country flags
    - edit the file if needed to include/exclude packages
    - install packages: Simplex is prearranged to use npm by means of the script *private/share/packagist/vukbgit/simplex/bin/npm.sh* symlinked into root folder:
        - `./npm.sh install`
    - packages are installed under *\\public\\share\\node\_modules*
- local **configuration**: file *private\\local\\simplex\\config\\constants.php* defines some PHP constants, most of them regard paths and it should not be necessary to modify them unless you plan to change the filesystem structure Simplex relies on; informations to be set for the local application (tech email, brand name...) are grouped into the *LOCAL* block at the top of the script
- **languages**:
    - file *private\\local\\simplex\\config\\languages.json* defines used languages, contains by default definitions for English and Italian, add as many as required; language selection works this way:
        - if current route contains a 'lang' parameter (tipically a part of the route itself for multilanguage sites) that language is used
        - otherwise the first language defined into *private\\local\\simplex\\config\\languages.json* is used, so if you only need one language you can put its definition in first position
- set up application *template*: a Twig template to be used for the whole application is provided in *private/local/templates/application.twig*:
    - it includes a Twig macro to display favicon generated by , if you want to use it go to website, generate icons images, upload them (i.e. to *public/local/corporate/favicon*) and set path as argument to the favicon() macro
- set up *routes*:
    - as seen above in the *.htaccess* section, when browser points to your-domain.ltd there are two options:
        - an empty route is defined
        - .htacces redirects requests for plain domain to a default route
    - routes are set up into route.php files, which are stored into *config* folders
    - as explained into the *terminology* section above, Simplex logic is to divide application into logical areas, corresponding to folders; Simplex is shipped with a *private/local/simplex/Backend* folder as a draft for building a backend for the application, it contains a *config/routes.php* where 3 routes are defined for the login operation (display the login form, perform login authentication and logout)
    - Backend folder can be renamed to something else to suit application logic but some adjustments must be made (area variable value in *routes.php* and *templates/backend.twig* file name)
    - there is also a *private/local/simplex/SubjectGroup* folder which is a draft for the development of a subject
- compile *SASS* files to CSS:
    - Simplex encourages compilation of SASS source files (.scss) to CSS files (.css).
    - *private/local/simplex/config/sass.config* contains a map of SASS to CSS files, each couple marked by an id (see file for explanations)
    - *sass.sh* is the soft link to a shell script that is used to compile css files, into root folder:

        ```
          ./sass.sh id-of-sass-file-to-be-compiled

        ```
    - Simplex need the compilation of at least these files:

        - application (*private/local/simplex/sass/application.scss*): style for the whole application (included into *private/local/simplex/templates/application.twig*):
            - it includes:
                - *share/vukbgit/simplex/src/sass/simplex.scss* the Simplex style, cannot (should not...) be customized
                - *private/local/simplex/sass/variable.scss* which contains sass variables for the whole application, can/should be customized and extended
            - compile with: `./sass.sh app`
        - bootstrap: different application areas might need different Bootstrap components, so there is not a predefined SCSS but a couple of drafts:
            - minimal (\_private/local/simplex/sass/bootstrap.scss): `./sass.sh bs`
            - backend (\_private/local/simplex/Backend/sass/bootstrap.scss): all the components needed by the Simplex backend templates: `./sass.sh bsb`

Area set up
-----------

[](#area-set-up)

- every route must be associated to an area (see "Terminology")
- an area needs at least some configuration files and probably a template and a css file
- Simplex provides two starting areas, Backend and Frontend, to be tweaked and used as-is or as drafts for other areas

### Backend / ERP

[](#backend--erp)

Simplex is shipped with an ERP namespace draft and uses it to build backends and ERP applications. Here we assume the area name is "Backend" but it can be changed to anything else, you just need to rename Backend folder accordingly and substitute the "backend" word (minding letters case) accordingly. Besides the common operations discussed above, here are the steps to configure the provided Backend area :

- *.htaccess*: set redirection of */backend* route to */backend/sign-in-form*
- check and set up *variables* into *private/local/simplex/Backend/config/variables.php*, at least *$successfulSignInRoute* (defaults to backend/dashboard), the other default values should be ok out of the box
- set up *authentication* methods into *private/local/simplex/Backend/config/routes.php* :
    - *htpasswd*: (enabled by default)

        - points to a htpasswd file that must be set manually, cd into desired folder (defaults to *private/local/simplex/Backend/config*):

            ```
              htpasswd -c .htpasswd your-username

            ```
        - every user defined in this file must be given a role into *private/local/simplex/Backend/config/users-roles.php*
    - *database*: (commented by default) uses a table or view, specifies fields names and conditions (like a boolean field which stores whether user is active)
- set up *logoPath* into *private/local/simplex/Backend/templates/sign-in-form.twig* to point to a logo image to be displayted into login form
- set up *logoPath* into *private/local/simplex/Backend/templates/backend.twig* to point to a logo image to be displayted into masthead, navbar height defaults to 48px, it can be twiked into *private/local/simplex/sass/variables.scss*
- customize Area style (*private/local/simplex/Backend/sass/backend.scss*) that just include ERP style and related variables (*private/local/simplex/Backend/sass/variables.scss*)
- compile the SASS files:
    - sign-in: `./sass.sh si`
    - backedn: `./sass.sh be`
- set up the *subject* called by the $successfulSignInRoute route (see "Subject set-up below"):
- to integrate jodit uploader:
    - into root folder run `./composer.sh  create-project --no-dev jodit/connector public/share/jodit`
    - add to any rich text input the (built by a displayRichTextEditor macro) configuration to display upload related Jodit buttons (i.e. image) and uploader path:

        ```
                ...
                options: {
                  buttons: 'bold, italic, underline, strikethrough | ul, ol | cut, copy, paste | indent, outdent, left, right, center, justify | link | image | undo, redo | source,fullsize, preview | about',
                  uploader: {
                    url: '/public/share/jodit/index.php?action=fileUpload',
                  }
                }
                ...

        ```
    - into *public/share/jodit/Application.php* remove the exception from *checkAuthentication* method and add eventual authentication logic
    - copy *public/share/jodit/default.config.php* as *public/share/jodit/config.php*
    - create a folder for uploaded images into public path, i.e. *public/local/simplex/richTextUploads*
    - if using a cvs system

        - include jodit in commit, edit *public/share/jodit/.gitignore.php*:

            ```
                  composer.lock
                  .idea/

                  tests/_data/
                  tests/_output/
                  tests/_support/
                  tests/acceptance/
                  tests/files/

            ```
        - exclude folder from commits, i.e. for Git:

            - create a *public/local/simplex/richTextUploads/.gitignore* file
            - paste into file:

                ```
                    # Ignore everything in this directory
                    *
                    !.gitignore

                ```
    - edit *public/share/jodit/config.php* and:

        - set up sources folders, i.e.

            ```
                  $basePath = '/public/local/simplex/';
                  $richTextUploadFolder = $basePath . 'Foo/richTextUploads';

                  $config = [
                      'sources' => [
                        'default' => [
                          'root' => $_SERVER['DOCUMENT_ROOT'] . $richTextUploadFolder,
                          'baseurl' => ((isset($_SERVER['HTTPS']) and $_SERVER['HTTPS']) ? 'https://' : 'http://') . $_SERVER['HTTP_HOST'] . $richTextUploadFolder . '/',
                          'extensions' => [
                            'jpg',
                            'png',
                          ]
                        ],
                      ],
                  ]

            ```

            - edit other options such as access control

This is the Backend folder structure:

- *private/local/simplex*
    - *Backend*
        - *config*
            - *constants.php*:
                - AREA\_NAVIGATION\_PATH: path to file with navigation menu definition, dfefaults to *private/local/simplex/Backend/config/navigation.php*
            - *di-container.php*: DI container definitions, shipped with just the authentication controller definition, it should not be necessary to modifiy or add definitions here, unless you have a class to be used across the whole area
            - *navigation.php*: navigation menus definition, return an array with one ore more menus definitions to be shared among area's pages, see file for format details
            - *premissions-roles*: map between permissions keys and area users roles (as defined into the authentication system), only necessary if you want to restrict access to some actions to some roles
            - *route.php*: definitions for area routes not related to some specific subject (i.e. sign in form)m shipped with default sign in form, sign in and sign out routes; contains some hard coded paths to authentication realted files that should not be necessary to change
            - *users-roles*: map between users names and roles, it is decoupled from authentication system (and user retrival data) to be as flexible as possible
            - *variables*: area level variables (such as slugged area name and default authentication object to be used in area routes), included into subjects di-container.php and routes.php specific file
        - *sass*:
            - *bootstrap.scss*: Bootstrap 4 components to be included in Bootstrap area style sheet, preset for minimal standard functionalities (menu, form, tables...), customize and recompile at need
        - *templates*: sign-in form and area shared template, used mainly to store translations and logo path, to be customized
    - *SubjectGroup*: subjects namespace can be organized into levels, useful when there are more the ten subjects at play
        - *Subject*: sdubjec level files, every type of file regarding the subject should be stored into its folder
            - *config*:
                - *crudl.php*: definitions for CRUDL functionalities, such as input filters to be used to grab fields values from save form or whether to use field to filter displayed table records
                - *di-container.php*: DI container definitions, shipped with just the controller and model definitions, it should be enough for standard subjects
                - *model-php*: model configuration (table. view. pruimary key)
                - *navigation.php*: definition for navigation associated to subject actions, shipped with default CRUDL actions (list, insert, update and delete), it should be enough for standard subjects
                - *routes.php*: definition for routes associated to subject actions, shipped with one definition that covers default CRUDL actions (list, insert, update and delete), and any action identified by one slugged action key and an optional primary key value, it should be enough for standard subjects
                - *variables*: subject level variables (such as subject namespace and slugged subject name )
            - *templates*: subject related templates, shape up subject UI and provide translations
                - *crudl-form.twig*: HTML for subject insert, update and delete forms by using macros defined into *private/share/packagist/vukbgit/simplex/src/templates/form/macros.twig* or by writing HTML code directly
                - *list.twig*: template for subject records list, defaults to table, it's necessary to set up table headers and cells
                - *subject.twig*: contains subject labels
            - *Controller.php*: base subject controller class, extends *Simplex\\Erp\\ControllerAbstract*, correct namespace must be set but already inherits all of the methods needed by CRUDL operations, to be extended for additional actions (with protected methods named after the PSR1 form of the slugged action name)
            - *Model.php*: base subject model class, extends *Simplex\\Model\\ModelAbstract*, correct namespace must be set but already inherits all of the methods needed by CRUDL operations, to be extended for additional actions (with protected methods named after the PSR1 form of the slugged action name)
    - *bin*: shell scripts, it can be useful to soft link them into web root
        - *composer.sh*: to use composer with a PHP versione different from the system default one
    - *config*: application configuration files
        - *constants.php*: application brand label and tech email (to be showed into exceltions) must be set, other values are meinly paths that should not be necessary to change
        - *db.php*: database account settings (takes data from *config.ini*)
        - *languages.json*: languages available to application, first one is used as default, shipped with Italian (default for most of my applications) and English, customize at need
        - *sass.config*: used by the web root *sass.sh* bash script to speed up SASS files compilation, shipped with some ready to use common paths, see file for details on format
    - *sql*: this folder might contain useful text files with SQL commands and snippets
        - *views.sql*: databases views definition, I usually keep them here since I find it more handy for editing
    - *sass*: application level SASS files
        - *application.scss*: rules to be applied to the whole applications
        - *bootstrap-variables.scss*: to override Bootstrap variables, included into bootstrap.scss BEFORE the Bootstrap own variables file
        - *bootstrap.css*: this file can be used to compile an application level bootstrap file if there is no need to have area level ones
        - *functions.scss*: SASS functions
        - *variables.scss*: application specific SASS variables i.e. colors or some specific ERP settings (navbars dimensions)
    - *templates*:
        - *application.twig*: ready to use top level application template
- *public*
    - *local*: folder for application files accessible by browsers, will be filled at least by compiled CSS files and probabily by much more application assets
    - *share*
        - *package.json*: default NPM packages
        - *npm.sh*: symlinked into web root to handle npm commands
    - *.htaccess*: Apache configuration file, grants access to real files (CSS, Javascript, imagess, etc) and redirects every other request to index.php

Subject set up
--------------

[](#subject-set-up)

The following steps show how to set up an ERP subject, that is a subject which implies a database model and the related CRUD UI, as the major part of a backend's subjects should be; it is also possible to use into a backend other kind of subjects (a dasboard for example), in this case see the frontend explanation below

- set up subject *database architecture*: besides a main table, in order to deal with internazionalization and file upload, Simplex relies over two accessory table, here is the complete overview of the possible subject architecture:
    - the main *table* holds language-indipendent data, at least the primary key; it should be named after the model key, usually snake case even if it can be any name as long as it is set into *config/crudl.php*
    - *internazionalization*: Simplex aims to be localization ready, so there should be a table for any language-dependent information, named *main-table-name\_locales* (with the mandatory \_locales suffix), with the following structure (naming convention is to be sctrictly followed for Simplex to handle correctly data saving):

        - a primary key (integer autoincrement) named *this-table-name\_id* (with the mandatory \_id suffix)
        - a *language\_code* (char 2) field, which hold the languages codes used as key into *config/languages.json* (the ISO-639-1 codes)
        - a *foreign key* field targeted to the main table primary key with a CASCADE delete setting
        - any custom field (text or varchar) for localized pieces of information as needed by subject
    - in case subject needs *files upload*, define a table named *main-table-name\_uploads* (with the mandatory \_uploads suffix)

        - this is the table structure:
            - a primary key (integer autoincrement) named *this-table-name\_id*
            - a *foreign key* field targeted to the main table primary key with a CASCADE delete setting
            - a field named *upload\_key* (varchar 64 should be enough) to store the record type of upload (the "field" used as key into the "uploads" array defined into */config/model.php*)
            - a field named *file\_name* (varchar 256) to store the record type of upload (the "field" used as key into the "uploads" array defined into */config/model.php*)
        - uploads information need to be manually added to the view (see below)
    - the *view*:

        - a basic view should be created and set up into *config/model.php*
        - in case of *uploads* the view should be joined over the uplods table:
            - for each upload field defined into *config/model.php* add a left join to the uploads table on the primary key and the *upload\_key* field (with the value of the field key)
            - extract *file\_name* field values with the name of the upload key; if field allows multiple uploads, group values, order them by primary key (so that order can by set by dragging files in the GUI) and join tem with a pipe: `,GROUP_CONCAT(DISTINCT join-table.file_name ORDER BY join-table.primary-key SEPARATOR '|') AS upload-key`
            - group by primary key in case of upload fields that allow multiple uploads in the UI
        - in case of a localized subject a localized view named *main-table-name\_locales* is mandatory: it must join main table over the locales one and expose primary keys fields, *language\_code* field (besides localized informations of course)
        - example:
            - table "foo" defined as

                ```
                  CREATE TABLE `foo` (
                      `foo_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
                      `non_localized_string` varchar(48) NOT NULL,
                      `date` date,
                      PRIMARY KEY (`foo_id`)
                  )

                ```
            - uploads definiton into subject *config/model.php*:

                ```
                  ...
                  'uploads' => [
                      'pdf_file' => [
                          'raw' => (object) []
                      ],
                      'single_image' => [
                          'thumb' => (object) [
                              'handler' => ['\Simplex\Local\SUBJECT\NAMESPACE\Controller','resizeImage'],
                              'parameters' => [100,100]
                          ],
                          'full' => (object) [
                              'handler' => ['\Simplex\Local\SUBJECT\NAMESPACE\Controller','resizeImage'],
                              'parameters' => [800,600]
                          ]
                      ],
                      'multiple_image' => [
                          'thumb' => (object) [
                              'handler' => ['\Simplex\Local\SUBJECT\NAMESPACE\Controller','resizeImage'],
                              'parameters' => [100,100]
                          ],
                          'full' => (object) [
                              'handler' => ['\Simplex\Local\SUBJECT\NAMESPACE\Controller','resizeImage'],
                              'parameters' => [800,600]
                          ]
                      ]
                  ],
                  ...

                ```
            - the uploads table:

                ```
                  CREATE TABLE `foo_uploads` (
                  `foo_uploads_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
                  `foo_id` int(10) unsigned NOT NULL,
                  `upload_key` varchar(64) NOT NULL,
                  `file_name` varchar(256) NOT NULL,
                  PRIMARY KEY (`foo_uploads_id`),
                  KEY `foo_id` (`foo_id`),
                  CONSTRAINT `foo_uploads_ibfk_1` FOREIGN KEY (`foo_id`) REFERENCES `foo` (`foo_id`) ON DELETE CASCADE
                  )

                ```
            - basic view:

                ```
                  CREATE VIEW v_foo AS SELECT
                  f.*
                  ,fusi.file_name AS single_image
                  ,GROUP_CONCAT(DISTINCT fumi.file_name ORDER BY fumi.foo_uploads_id SEPARATOR '|') AS multiple_image
                  FROM foo AS f
                  LEFT JOIN foo_uploads AS fusi
                  ON f.foo_id = fusi.foo_id
                  AND fusi.upload_key = 'single_image'
                  LEFT JOIN foo_uploads AS fumi
                  ON f.foo_id = fumi.foo_id
                  AND fumi.upload_key = 'multiple_image'
                  GROUP BY f.foo_id

                ```
            - the internationalization table:

                ```
                  CREATE TABLE `foo_locales` (
                  `foo_locales_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
                  `language_code` char(2) NOT NULL,
                  `foo_id` int(10) unsigned NOT NULL,
                  `title` varchar(256) NOT NULL,
                  `content` text NOT NULL,
                  PRIMARY KEY (`foo_locales_id`),
                  KEY `foo_id` (`foo_id`),
                  CONSTRAINT `foo_locales_ibfk_1` FOREIGN KEY (`foo_id`) REFERENCES `foo` (`foo_id`) ON DELETE CASCADE
                  )

                ```
            - the internationalization view:

                ```
                  CREATE VIEW v_foo_locales AS SELECT
                  f.*
                  ,fl.language_code
                  ,fl.title
                  ,fl.content
                  FROM v_foo AS f
                  LEFT JOIN foo_locales AS fl
                  ON f.foo_id = fl.foo_id

                ```
    - Simplex is shipped with a convenient *private/local/simplex/docs/views.sql* text file where views definition can be written; often database manager SQL editor are not handy, storing views definition into a plain SQL/text file, editing through an editor with synthax highlighting and copy and paste into the db application can be a solution and provides also a backup
- each subject files are contained into a folder named after the subject
- ponder the position of the subject into application architecture:
    - it can be used application wide, so its folder should reside into *private/local/simplex*
    - it can be used only inside ont specific area, so it should reside into *private/local/simplex/area-name*
    - it can share some business logic with other subjects, so it should reside into *private/local/simplex/\[area-name\]/subjects-group-name*; in case application uses more than a few subjects I usually try to group them
- use *private/local/simplex/SubjectGroup/Subject* folders as a draft, copy them and customize files; or even better use an already configured subject folder and edit just the files formatted below in ***bold italic***. Working into subject folder:
    - ***config/variables.php***: set up subject namespace and slug form, namespace must reflect subject folder position (i.e. *Simplex\\Local\\Backend\\Subject-Group-Name\\Subject-Name*)
    - ***config/model.php***: set up subject model definition
    - rename *config/routes.draft.php* to *config/routes.php*, default configure dynamic route should cover at least the basic CRUD operations (list, inser form, insert operation, update form, update operation, delete form, delete operation)
    - rename *config/di-container.draft.php* to *config/di-container.php*
    - edit ***Controller.php*** and ***Model.php*** and correct namespace to the same value used into *config/routes.variables.php*
    - edit ***config/crudl.php*** and set up:
        - table localization (localized property, boolean), whether model table uses an accessory table for localization (see "set up *database architecture*" above)
        - table fields filters to be used to retrieve fields values passed by save form
    - *config/navigation.php* contains rules to display the UI navigation for basic CRUD actions, it can be customized to remove some of them or add more actions, for permissions logic see *subject permission* below
- set up subject *template labels* in ***templates/labels.twig***, at least subject label is required but fields labels are used int list and save form templates
- edit ***templates/list.twig*** to set up fields displayed into records table, there is a tableheader block for headers and a records loop for table cells with fields values
- edit ***templates/crudl-form.twig*** to set up fields displayed into insert/update and delete forms; any valid html can be inserted into modelInputs block but a bunch of useful Twig macros are defined into */private/share/packagist/vukbgit/simplex/src/templates/form/macros.twig* which is included by default; use macros whose name end by 'group' di build a Bootsrap field form complete with label
- set up *subject permission* for roles into ***private/local/simplex/Backend/config/permissions-roles.php***:; by default into *private/local/simplex/Backend/config/navigation.php* permission *manage-SUBJECT-KEY* is required for the user to use global (list and insert) and record actions (update and delete), so permission *manage-SUBJECT-KEY* must be added and user's role must be included into permission's allowed roles array
- include subject into area navigation into ***private/local/simplex/Backend/config/navigation.php***
- set up subject *navigation label* in ***private/local/simplex/Backend/templates/backend.twig***, into the *areaNavigationLabels* hash
- perform sign-out/sign-in to reload permissions

Debugging
---------

[](#debugging)

- PHP layer: Simplex uses [Whoops](https://filp.github.io/whoops/) for printing exceptions in development environment and [Kint](https://kint-php.github.io/kint/) for dumping variables; in particular Kint is available as two functions:
    - 'x($var)': dumps a variable to HTML aoutput
    - 'xx($var)': dumps a variable and exits the scripts immediately
- Twig templates: the dump function is available as a wrapper for Kint dump function, i.e. '{{ dump(my-variable-of-any-type) }}'

Internazionalization
--------------------

[](#internazionalization)

- **PHP/Twig templates**:
    - Simplex uses [gettext](https://www.gnu.org/software/gettext/) and is shipped with a set of English and Italian translations for the messages contained into the provided UI
    - translations can be inserted into:

        - *PHP* files using the gettext() function or the \_() alias (see [PHP gettext documentation](https://www.php.net/gettext))
        - *Twig templates* using the trans block and filter from the (included by default) i18n extension (see [documentation](https://twig-extensions.readthedocs.io/en/latest/i18n.html))
    - *private/share/packagist/vukbgit/simplex/bin/translations.php* script can be used to extract translations
    - folder where translations files are stored is specified by the *TRANSLATIONS\_DIR* constant and defaults to *private/local/simplex/locales*
    - this is the translations workflow:

        - after installation, into *TRANSLATIONS\_DIR* English and Italian translations for Simplex core messages are stored
        - translations extraction from relies on Twig templates cache; if your local templates use any user defined Twig filter or function templates cache building will be broken, so you need to:

            - put the Twig filters/functions definitions into a public method of some of your local classes
            - create one or more files under *private/local/simplex* named *templates-helpers.php*: if this file exists it sill be automatically included by the translation script (there is a draft file *private/local/simplex/bin/templates-helpers.draft.php*)
            - into the *templates-helpers.php* file call all of the template helpers builder methods
        - when local translations are added run script to update local messages, .po and .mo files are saved into *TRANSLATIONS\_DIR* for every language defined into *private/local/simplex/config/languages.json*:

            ```
              php private/share/packagist/vukbgit/simplex/bin/translations.php update local

            ```
        - download .po files, translate with [Poedit](https://poedit.net/) or other similar software
        - upload resulting .po and .mo files back to *TRANSLATIONS\_DIR*
    - in case site uses a PHP version different from system one if must be specified the complete path to PHP binary, i.e.

        ```
          /opt/php-7.3.5/bin/php private/share/packagist/vukbgit/simplex/bin/translations.php update local

        ```
    - at installation time it is also created in the root folder the script *translations.sh* that can be used to shortcut translation process, call it from root folder this way:

        ```
              ./translations.sh update local

        ```
- **database**: Simplex encourages a localization ready database architecture, even when site uses just one language (see [Subject set up](#Subject-set-up) &gt; *database architecture*)

Emails
------

[](#emails)

Simplex uses [mjml](https://www.npmjs.com/package/mjml) integrated into Twig templates by means of [mjml-php](https://github.com/qferr/mjml-php) to build responsive emails. A starting templates is provided into *private/local/simplex/templates/emails/base.twig*

Icon Fonts
----------

[](#icon-fonts)

Simplex uses [Fontello](http://fontello.com/) for icons and it breaks icons into logical groups, each with its Fontello folder, so far:

- *public/share/simplex/form/Fontello* for form related icons (100 reserved unicode values, from 0100 to 0164)
- *public/share/simplex/Erp/Fontello* for ERP (Backend) related icons (100 reserved unicode values, from 0165 to 01C9)
- *public/share/brands/Fontello* for brands related icons, i.e. social media or file types (20 reserved unicode values, from 01CA to 01DE)

Unicode codes are assigned so that, if icons are used into css (setting CSS properties *content* to unicode code and *font-family* to "fontello") icons do not overlap, if other application specific icons are added they should take unicode codes from 02BC (included) onward. Note: when using unicode codes into CSS remember to check text-transform (lowercase or uppercase) because each icon corresponds to a unicode charachter with a specific case and, if element inherits case from context, it could display the wrong gliph.

Development to Production
-------------------------

[](#development-to-production)

If you keep separate development and production environment and manage pubblication through a git repository you can use some bash scripts soft linked into web root at installation time:

- development environment:
    - *git-setup-dev.sh*: interactive script that asks for repository URL, git user email and git user name, sets up the repository, makes first significative commit and pushes it to repository
    - *git-push-all.sh*: push all changes made since last commit, it adds all content of root folder and subfolders, so any folder/file to be excluded from commits must be added to *.gitignore*; if you need to push only some changes you must add, commit and push manually
- production environment:
    - copy *composer.json* file from development environment
    - run `composer create-project`
    - run *git-setup-prod.sh*, interactive script that asks for repository URL and sets up repository for pulling
    - run *update-all.sh* which:
        - cleans DI container and templates cache, beware of tmp folder path, (see *[Post-Installation Jobs](#Post-Installation-Jobs) &gt; bash scripts settings*
        - updates Composer packages
        - updates NPM packages through npm

Simplex Logic overview
----------------------

[](#simplex-logic-overview)

### Logical Structure

[](#logical-structure)

- **Simplex\\ControllerAbstract**: basic controller for a route that does not display a page
    - has DI container and response object as injected dipendencies
    - route MUST pass 'action' (in slug form) and 'area' parameters
    - stores request and its parameters parameters
    - sets language
    - executes the method named after the PSR1 translation of the action parameter slug
- **Simplex\\ControllerWithTemplateAbstract**: controller for a route that displays a page
    - extends Simplex\\ControllerAbstract so inherits its properties and functionalities plus the following
    - has template engine and cookies manager as injected dipendencies
    - builds some template helpers
    - passes to template some constants and variables as parameters
- **Simplex\\Erp\\ControllerAbstract**: controller for a route into an ERP area of the application
    - extends Simplex\\ControllerWithTemplateAbstract so inherits its properties and functionalities plus the following
    - identifies the current **subject** (see "Terminology" above):
        - all the files relative to a subject MUST be in the same folder, inside the \_Simplex\\Local \_ namespace
        - the subject name is the name of the folder files are into (which is the name of the last part of the subject's files namespace) turned from PSR1 format to slug (with every upper case letter prepended by hypen and turned to lower case, i.e. 'NewsCategories' &gt; 'news-categories')
        - stores the subject under *$this-&gt;subject*
    - instances and injects the mandatory **model**:
        - there MUST be a class defined into subject namespace that:
            - is named 'Model'
            - must extend Simplex\\Model\\ModelAbstract
            - must have git a configuration file under *subject-namespace\\config\\model.php*
        - stores the model under *$this-&gt;model*
    - loads CRUDL config which is mandatory for ERP and contains informations for the CRUDL interface to be exposed (such as the input filters to be used with each model field) and must be saved into a *subject-namespace\\config\\crudl.php*
    - gets users options for the subject from cookies (options are set into cookie from the UI) and stores them into *$this-&gt;userOptions*
    - loads navigations:
        - load area navigations (side bar menu) from the file *area-namespace\\config\\navigation.php*
        - load subject navigations (globa actions tabs, table record action links) from the file *subject-namespace\\config\\navigation.php*
        - each route contained into navigations voices is tested against current URL to check whether it's the currently selected one
    - builds some ERP specific template helpers
    - passes to template some ERP specific constants and variables as parameters

### Application Flow

[](#application-flow)

- *.htaccess*
    - sets a PHP environment variable base on the domain to decide the current environment
    - intercepts every request and redirects to *index.php*
- *index.php*:
    - requires Composer autoload
    - searches for files named *constants.php* under folder *private/local/simplex*, during installation *private/local/simplex/config/constants.php* is created (see file for details)
    - set up the **Error Handler** based on the environment
    - instances a **[Dipendency Injector Container](https://github.com/php-fig/container)** loading definitions from *private/share/packagist/vukbgit/simplex/config/di-container.php* (see file for details)
    - the **DI Container** instances the **Dispatcher** (which is another name for a [request handler](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-15-request-handlers.md#21-psrhttpserverrequesthandlerinterface))
    - the dispatcher loads the **middleware queue** from the MIDDLEWARE\_QUEUE\_PATH constant value (defaults to *private/share/packagist/vukbgit/simplex/config/middleware.php*), Simplex default queue is composed by:
        - the **Router** which loads routes definitions from any file named "routes.php" stored under the *private/local/simplex* folder (even in subdirectories); the route definition must contain an "action" parameter (*private/local/simplex/config/route.php* contains more details about routes definitions)
        - the Simplex **Authentication** middleware that:
            - fires conditionally if an "authentication" parameter is found inside the current route definition
            - if fired checks whether the user is currently authenticated, otherwise redirects to a configured url
        - the **Request Handler** (no, not the **Dispatcher** from above, there is a bit of naming confusion on this matter...), which is responsible for processing the current route, invokes the **Route Handler** (a local class) specified into the route definition which must inherit from one of the Simplex\\Controller abstract classes
        - the **Route Handler**:
            - stores all of the request parameters and the response object into class properties
            - calls a method named after the "action" route parameter
            - this method performs all the tasks needed by the action and usually renders a template injecting HTML code into the response
        - the **Dispatcher** returns the response to the *index.php* scope
    - the HTTP status code of the response is checked and if different from 200 (which means "everything went fine") gets the appropriate HTML code from a *private/share/packagist/vukbgit/simplex/src/errors/* file and injects it into the response
    - the **Emitter** is instantiated and returns the response to the browser

Folders and Files Structure
---------------------------

[](#folders-and-files-structure)

Simplex extends the classes namespace logic to every file in the application;: the **local namespace** starts from the folder defined into *private/local/simplex/config/constants.php* LOCAL\_DIR constant (defaults to *private/local/simplex*) and is named by default *Simplex\\Local*.

Into this folder the classes are arranged as the typical application, by business domain logic (i.e. the *News* folder for all classes related to news, the *Customer* folder, etc). But also every other file with different purpose (configuration files, html templates, SASS files...) should follow this logic; so there is no grouping by function first (a top *config* folder, a top *views* folder, etc.), but instead by namespace/business logic first (so */News/config* and *News/templates* folders).

This is because typically application development proceeds by domain logic: adding the News functionality means adding at least a News class, some News configuration (routes and DI container definitions) and some News views (HTML templates for backend and frontend); if all of these files are scattered through local folder subfolders I find it harder to develope, mantain and "clone" functionalities to be used as draft for new ones

So here are folders and files as installed from Simplex, from the installation root folder:

- **private**: all files that CANNOT be directly accessed by browser
    - **local**: files developed for the application
        - **simplex**: top level namespace folder for application files, every class defined inside has base namespace *Simplex\\Local*
            - **Backend**: backend namespace draft folder
            - **Frontend**: frontend namespace draft folder
            - **bin**: created at installation time for useful bash scripts
                - **composer.sh**: allows to use composer with a PHP version different from the system default one used by the PHP CLI application, useful on a system with multiple PHP versions installed; it's a good idea to soft link it into root
            - **config**: configuration files for whole application to be customized
                - **constants.php**: environment constants, quite self explanatory, some of them should be set right after installation; NOTE: most of the regards paths Simplex uses for inclusions, it shouldn't be necessary to change them; if so beware that a pair of paths are hard coded into *index.php* prior to including this file and should be changed manually
                - **db.php**: database configuration, returns a PHP object, gets configuration from *config.ini*
                - **di-container.php**: definition to be used by the DI Container to instantiate the classes used by the application; it integrates **private/local/share/vukbgit/simplex/src/config/di-container.php/** which stores the definitions for classes used by the Simplex engine
                - **languages.json**: languages used by the application, indexed by a custom key (the one proposed is the ISO-639-1 two letters code); if the route passes a "language" parameter, language is searched for otherwise first one defined (defaults to English) it's used
                - **sass.config**: custom format file to speed up Sass files compilation using the *sass.sh* script: you can define for each file to be compiled a custom id (any string) and source and destination paths, so you you ca use the shell and call from the root folder `sass file-id` to compile the minified CSS version
            - **sass**: some scss empty drafts to help compile Bootstrap and some application css
                - **application.scss**: rules for the whole application
                - **bootstrap-variables.scss**: it is included BEFORE the file with the *variables.scss* shipped with Bootstrap to override Bootstrap built-in variables
                - **bootstrap.scss**: main file to compile Bootstrap css, includes only the most commonly used components, uncomment lines to include other functionalities; *private/local/simplex/config/sass.config* already contains configuration to compile this file by means of the root *sass.sh* file, just executing in the shell './sass.sh bs'
                - **functions.scss**: definitions for some useful Sass functions
                - **variables.scss**: Sass variables to be used by the application
            - **templates**: some ready to use and customize Twig templates
    - **share**: files installed through Composer and possibly other third-part libraries from other sources
        - **packagist**: libraries installed by means of [Packagist](https://packagist.org)
            - **vukbgit**
                - **simplex**: shared Simplex modules used by application, some explanations about the less obvious ones:
                    - **bin**: bash scripts, some of the soft linked into root at installation composer project creation time
                    - **installation**: folders and files copied at installation time ready to be used and/or to be customized
                    - **src**: classes and other files used by Simplex at runtime
                        - **config**: configuration files
                            - **di-container.php**: definition to be used by the DI Container to instantiate the classes used by the Simplex engine; it is integrated by ANY file with the same name found under the **private/local/simplex** folder
                            - **middleware.php**: middleware queue to be processed by the Dispatcher, can be overridden setting *MIDDLEWARE\_QUEUE\_PATH* value into *private\\local\\simplex\\config\\constants.php*
                        - **errors**: HTML files to be displayed in case of HTTP errors raised by the request
                        - **templates**: ready to use Twig templates for backend areas with CRUDL functionalities
            - all the other Composer libraries used by the application
- **public**: all files that CAN be accessed by browser
    - **local**: files developed for the application such as compiled css files and javascript files
    - **share**: libraries installed from npm and any other third-part frontend javascript and css asset
        - **package.json**: npm configuration file, requires Bootstrap and jQuery latest plus other useful libraries, customize at need
    - **.htaccess**: redirects ALL requests beginning with "public/" to *index.php* except the ones for files really existing into filesystem (css, js, etc.)
- **.gitignore**: in a development/production flow I commit file to a private repository form the development site and pull them into the production one; this .gitignore file excludes some Simplex folders/files from commit
- **.htaccess**: root Apache directives
    - redirects ALL requests for the root directory to public/index.php
- **composer.json**:
    - sets vendor directory to *private/share/packagist*
    - sets bin directory to *./* so that symlinks are created into root for some shell scripts
    - sets autoload application directory to *private/local/simplex* mapping this path to *Simplex\\Local* namespace
    - requires the Simplex package (which takes care of requiring the other needed packages)
- **index.php**: application bootstrap file, since it is stored into site root all PHP includes in every file work with absolute path form site root, see "Application Flow" above for details
- **sass.sh**: soft link to the helper script *private/share/packagist/vukbgit/simplex/bin/sass.sh* to compile Sass files, see the *private/local/simplex/config/sass.config* explanation above for details
- **npm.sh**: soft link to the helper script *public/share/npm.sh* to manage npm packages into *public/share* folder, call it `./npm.sh npm-command`, i.e `./npm.sh install foolibrary` to perform the installation into *local/share/node\_modules/foolibrary*

Migration from v2 to v3
-----------------------

[](#migration-from-v2-to-v3)

- index.php: Zend -&gt; Laminas
- FILTER\_SANITIZE\_STRING -&gt; FILTER\_SANITIZE\_SPECIAL\_CHARS:
- grep -rl FILTER\_SANITIZE\_STRING private/local/simplex | xargs sed -i 's/FILTER\_SANITIZE\_STRING/FILTER\_SANITIZE\_SPECIAL\_CHARS/'
- ERP:
    - list:{% block rows %} {% for record in records %} {{ tableMacros.displayRowBegin(\_context, loop, record) }} {{ record.FIELD }} {{ tableMacros.displayRowEnd(\_context, loop, record) }} {% endfor %}{% endblock %}
    - crudl-form:
        - dateTimePickers bound for a date range now unified
    - css:
        - ERP style no more directly included but integrated into area (i.e. Backend) scss file:
            - create area scc file (copy from installation folder), i.e. *private/local/simplex/Backend/sass/backend.css*
            - compile it, i.e. `./sass.sh be`
            - include into area template, i.e. *private/local/simplex/Backend/templates/backend.twig*
- FORMS:
    - alla captchas dependencies and functionalities removed, implement honey trap technique
    - update (copy from installation folder) calendar dates format for languages into *private/local/simplex/config/languages.json*
- TWIG:
    - move if conditions out of for loops, regular expression to search for them: `grep -rE "{%\s+for\s+[a-zA-Z ,]+\s+in\s+[a-zA-Z\.]+\s+if" private/local`
- SASS:
    - enclose arithmetic operations into `calc()` function
- BOOTSTRAP 5:
    - .ml-\* and .mr-\* -&gt; .ms-\* and .me-\*.
    - .sr-only -&gt; .visually-hidden
    - form grid: form-row -&gt; row
    - .form-inline: use grid row &gt; col / col-md-auto
    - all af *data-\** attributes in collapse (i.e. menu voices), carousels, etc become *data-bs-\**
    - text-alignment: -left -&gt; -start; right-&gt;end
    - remove input-group-append / prepend
    - close buttons (modal, alert...):
        - class close -&gt; btn-close
        - data-dismiss -&gt; data-bs-dismiss
        - remove inner span
- SPREADSHEET READER/WRITER: reader moved to phpoffice/phpspreadsheet should be fine, **writer implementation currently still broken!**

Considerations
--------------

[](#considerations)

- I choose not to use any framework because I want to be 100% in control of the flow inside the application
- Simplex uses third party classes for almost every specialized task (DI container, routing, dispatching, emitting...)
- I coded some components into Simplex only when I couldn't find an external library to accomplish some task the way I needed: for example I wrote the nikic/fastroute middleware to be able to pass custom route parameters
- design choices: I tried to search documentation, mostly seeking "no framework" suggestions (see references below), and taking a look to existing frameworks (although I am no expert in this field because I started structuring my code for re-use since 2000); I want Simplex to be up-to-date but also to be, well, simple and there is no agreement on every topic, for example [the use of a DI Container](https://hackernoon.com/you-dont-need-a-dependency-injection-container-10a5d4a5f878). Therefore I made my (very questionable) choices, keeping **always** in mind the I needed a tool to build web applications in the fastest and most flexible way
- So I ended up with a framework myself?! Honestly I do not know

API Documentation
-----------------

[](#api-documentation)

API dcoumentation generated with phpDocumentor can be found at \[\]

References
----------

[](#references)

- \[\]
- \[\]

###  Health Score

42

—

FairBetter than 90% of packages

Maintenance35

Infrequent updates — may be unmaintained

Popularity15

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity91

Battle-tested with a long release history

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~5 days

Total

351

Last Release

603d ago

Major Versions

0.1.0.x-dev → 1.0.0.x-dev2019-06-10

v1.2.0 → v2.0.12022-06-18

v1.2.2 → v2.2.682023-04-16

v2.2.100 → v3.0.02023-06-08

1.1.2.x-dev → v3.9.72023-09-05

PHP version history (2 changes)v2.0.38PHP &gt;=8.0

v3.0.0PHP &gt;=8.2

### Community

Maintainers

![](https://www.gravatar.com/avatar/2f9f22ea5c6a917786c6b88349285bd980af48ef3685a2a7ea0d2a1d0074dae9?d=identicon)[vukbgit](/maintainers/vukbgit)

---

Top Contributors

[![vukbgit](https://avatars.githubusercontent.com/u/7385327?v=4)](https://github.com/vukbgit "vukbgit (1329 commits)")

---

Tags

no-frameworkphpphp81simplex

### Embed Badge

![Health badge](/badges/vukbgit-simplex/health.svg)

```
[![Health](https://phpackages.com/badges/vukbgit-simplex/health.svg)](https://phpackages.com/packages/vukbgit-simplex)
```

###  Alternatives

[flarum/core

Delightfully simple forum software.

211.3M1.9k](/packages/flarum-core)[elgg/elgg

Elgg is an award-winning social networking engine, delivering the building blocks that enable businesses, schools, universities and associations to create their own fully-featured social networks and applications.

1.7k15.7k5](/packages/elgg-elgg)[shopware/core

Shopware platform is the core for all Shopware ecommerce products.

595.2M386](/packages/shopware-core)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
