vukbgit/simplex

v1.1.0 2019-06-10 16:35 UTC

README

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 templates) and CSS or SCSS.

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 packages (by means of Packagist 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
  • Yarn for all the NPM packages:

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

  • Apache 2.4+ webserver: althoungh not strictly necessary for the core engine, .htaccess files are used for basic routing and domain based environment detection
  • PHP 7.1+ with the PHP gettext extension enabled (beacuse every piece of text is considered as a translation even in a mono language application)
  • ssh access to web space: on a shared hosting it's hard to use Composer (and Yarn 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 & comfort of the ssh shell I rented my own virtual machine and never turned back to shared hosting again...
  • even if not strictly required I strongly suggest to have also:
    • Yarn: to install javascript and css libraries
    • Sass 3.5.2+.: to compile css with variables, mixings and many other useful additions

Installation

Create a Composer.json in the root folder:

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

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)
  • build the folders structure for the local application with some ready draft files

For details see Folders & Files structure below

Post-Installation Jobs

  • /.htaccess:
    • set ENVIRONMENT variable:
      • using SetEnvIf directive you can set an enviromental varible name ENVIRONMENT which can be read inside PHP scripts as a constant with getenv('REDIRECT_ENVIRONMENT')

      • value is based on requested domain and the format is:

        SetEnvIf Host ^domain.ltd$ ENVIRONMENT=value

      • domain.ltd must be replaced by a valid domain name (beware the escaped dot)

      • value can be either development or production and Simplex expects to have at least one domain mapped to production

  • local composer bash script: if your system has multiple PHP versions installed it can be useful to have a shortcut to use composer with a version different from the system default one; file private\local\simplex\bin\composer.sh can be set with the path to the right PHP binary and softlinked into root folder
  • install yarn packages:
    • the public\share\package.json file contains some NPM packages for:

      • backends or enterprise web applications (ERP):
        • PatternFly 4: a "an open source design system created to enable consistency and usability across a wide range of applications and use cases", Simplex uses it for ERP and backend building in the provided drafts
        • parsleyjs: form validation
        • moment for dates and time manipulation
        • tempus dominus for date/time pickers
      • frontend
    • edit the file if needed to include/exclude packages

    • install packages: you can use the yarn.sh symlink from the root folder:

        ./yarn.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, application name...) are grouped into the LOCAL block at the top of the script
  • database configuration: in case application connects to a database edit file private\local\simplex\config\db.php; database accounts are organized by ENVIRONMENT constant values (see .htacces above), so you can have different accounts for development and production
  • languages: file private\local\simplex\config\langauges.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\langauges.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 https://www.favicon-generator.org, 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
    • remove the

      tag

Backend / ERP Development TODO

Simplex include an ERP namespace based on PatternFly 4 and uses it to build backends

  • login form route

  • methods:

    • htpasswd: create password file for example in private/local/simplex/Backend/config/.htpasswd

      htpasswd -cB -C10 .htpasswd your-username

  • patternfly compilation

Simplex Logic overview TODO

A bit of 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
  • environment: in which the current request is handled, based usually on the requested domain, takes usually the values of "development" or "production"
  • action: the specific logic associated to a route, i.e. 'list' and 'save-form', every route must set an 'action' parameter and it should be formatted as a slug

Conventions:

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

Application Flow

  • .htacces
    • 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 loading definitions from private/share/vukbgit/simplex/config/di-container.php (see file for details)
    • the DI Container instances the Dispatcher (which is another name for a request handler)
    • the dispatcher loads the middleware queue from the MIDDLEWARE_QUEUE_PATH constant value (defaults to private/share/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/vukbgit/simplex/src/errors/ file and injects it into the response
    • the Emitter is instantiated and returns the response to the browser

Folders & 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: frontend 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, to be compiled if application uses a database (see file for details)
          • 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
      • 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 through npm, Yarn, and any other third-part javascript and css asset
      • package.json: npm/Yarn configuration file, requires Bootstrap, jQuery and popper.js lates plus patternfly 4, 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
    • sets environment variables that are readable into PHP code
      • based on domain:
        • ENVIRONMENT: development | production
      • how to read them: Apache renames them prepending 'REDIRECT_' (since every route is redirected to public/index.php), so use for example getenv('REDIRECT_ENVIRONMENT')
    • redirects ALL requests for the root directory to public/index.php
  • composer.json:
    • sets vendor directory to private/share
    • 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/vukbgit/simplex/bin/sass.sh to compile Sass files, see the private/local/simplex/config/sass.config explanation above for details
  • yarn.sh: soft link to the helper script private/share/vukbgit/simplex/bin/yarn.sh to manage yarn packages into public/share folder (instead of the predefined node_modules one), call it ./yarn.sh yarn-command, i.e ./yarn.sh install foolibrary to perform the installation into local/share/foolibrary

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. 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

References