TRA
User centric PHP framework

What is OTRA? What is its goal?

OTRA is a PHP framework in alpha version at the time of writing used to create websites and web applications.

Many tasks are automated but the framework is user centric, not developer centric so the performance is more important than productivity.

Want to test it right now?

composer create-project otra/skeleton --remove-vcs yourProjectFolderName


Want to contribute?

https://github.com/lperamo/otra

Why use a framework?

A framework is not mandatory but that will provide you a structure and allow you to save time by re-using generic code in order to focus on other areas. For example, no need to recreate a routing system or a MVC structure.

You can then fully focus on the business rules, the core structure being upgradeable.

When use a framework?

If you have specific needs or specific business rules, you will use a framework to be able to develop an application that suits them perfectly while still being innovative.

Otherwise, maybe a CMS (Content Management System) or a packaged professional solution (CRM, e-commerce solution, etc.) will be sufficient and you won't have to reinvent the wheel.

Main sections>Cache management

Previous section : Configuration

Cache management

Beware ! If you want to use console to generate files in the cache directory, assure you that :

  • the directory cache exists
  • the directories php, js and css in the cache directory exist

Next section : Generating everything you need

Main sections>All about database>Database fixtures

Database fixtures

Your bundle database fixtures must be in the folder bundles/bundleName/config/data/yml/fixtures.

A fixture file must look like this :

table_name: fixture_name: my_id_column: '1' my_other_column: 'Main topic' a_timestamp_column: '2010-12-31 00:00:00' unsigned_column: '1' fixture_name_bis: my_id_column: '2' my_other_column: 'Second topic' a_timestamp_column: '2010-12-32 00:10:00' unsigned_column: '2' fixture_name_ter: my_id_column: '3' my_other_column: 'Third topic' a_timestamp_column: '2010-12-33 00:20:00' unsigned_column: '3' [...]

When you want to make reference to a fixture of another table, we must put the fixture name instead of the value.

Next section : Database schema

Main sections>All about database>Database schema

Previous section : Database fixtures

Database schema

Your bundle database must be in the file bundles/bundleName/config/data/yml/schema.yml.

It must follow this kind of architecture :

table_name: columns: my_id_column: type: int(11) notnull: true auto_increment: true primary: true my_other_column: type: varchar(255) notnull: true a_timestamp_column: type: timestamp notnull: true unsigned_column: type: tinyint(1) unsigned [...] another_table_name: columns: my_foreign_id_column: type: int(11) notnull: true primary: true my_foreign_id_column_two: type: int(11) notnull: true primary: true a_column: type: int(11) notnull: true relations: other_table: local: my_foreign_id_column foreign: id constraint_name: relation_name other_table_bis: local: my_foreign_id_column_two foreign: my_id_column constraint_name: another_relation_name other_table: columns: [...] other_table_bis: columns: [...]

It remains SQL things that are not handled yet but feel free to create issues about those that are missing.

Main sections>Generating everything you need

Previous section : Cache management

Generating everything you need

Updating routes

Once you have configured your application, don't forget to do :

php console.php upConf

It will optimize your configuration by generating an aggregated minified configuration file.

Generating the class mapping

You can generate a class mapping via this command :

php console.php genClassMap

You can pass 1 as parameter to directly show the classes of the class mapping.

This command can be used via a file watcher when adding/modifying a file.

Optimizing your server code for production

You can generate optimized versions of your routes (php code mostly) like this :

php console.php genBootstrap

Generating assets for production

You can generate optimized versions of your assets ... :

php console.php genAssets

Next section : All about database

Main sections>Contributing>CSS side or SCSS side

CSS side or SCSS side

Coding style

  • Do not use uppercase in classes, the css rules and properties do not do that => consistency.
  • Use the BEM (Block Element Modifier) syntax. Documentation

Best practices

  • Use SCSS or SASS. SCSS is probably best because if one day, it becomes useless due to CSS enhancement ... SCSS has almost the same coding style so it will be simpler to adapt the code.
  • Keep the lowest specificity as possible. Some people even say never use ids but classes instead for reusability !
  • Use border: 0 and not border: none (shorter)

Next section : Generic rules

Main sections>Contributing>HTML side

Previous section : Generic rules

HTML side

  • Don’t use the attribute type="text" on input markups...it is the default.
  • No need to respect XHTML norm unless we want to use that document with XML code. We can use <input> instead of <input/> for example, it is shorter.
  • If we can, avoid to use <br> and prefer CSS classes instead.
  • Don’t forget to use ARIA. Here is the documentation.
  • Don’t forget to use structured data. Here is the documentation.
  • Don’t forget to use microdata. Here is the documentation.
  • Don't forget ... You can use this source code for a good start : HTML5 Boilerplate.

Next section : JavaScript side

Main sections>Contributing>Shell side

Previous section : PHP side

Shell side

Coding style

  • Use snake_case for unexported variables and SCREAMING_SNAKE_CASE for constants and exported variables.
Main sections>Contributing>Generic rules

Previous section : CSS side or SCSS side

Generic rules

Coding style

  • Tabulation :
    • Spaces, not tabs
    • 2 spaces => to avoid to scroll horizontally when they are much nestings
  • Curly brackets on the same column
    • more aeration
    • easy to see if there are some missing curly brackets, counting curly brackets, above all when there are far away
  • Put a blank line before and after block statements (if, for, while etc.)
  • 80 characters per line maximum in order to be able to have 2 files opened side by side on a laptop screen.
  • Use PascalCase for classesName, SCREAMING_SNAKE_CASE for constants, camelCase for the rest.
  • If the line of code of a function signature is too long, we have to put the parameters under, one parameter by line.

Example :

public final function renderView( string $file, array $variables = [], bool $ajax = false, bool $viewPath = true ) : string

Next section : HTML side

Main sections>Contributing>JavaScript side

Previous section : HTML side

JavaScript side

Best practices

  • Use TypeScript, it provides types, annotations, object oriented code and so more. So type every variable, put return types …
  • Use the use strict statement in order to have a clean code
  • Use border: 0 and not border: none (shorter).
  • When you want to use jQuery, learn how jQuery do it and then use vanilla js instead. To help you : You might not need jQuery.

Next section : PHP side

Main sections>Contributing>PHP side

Previous section : Javascript side

PHP side

Coding style

  • Organize use statements particularly when they share path e.g. :

    use config\{All_Config, Routes};

Best practices

  • Use const instead of define when possible. See this Stack Overflow post
  • Use a class only when you cannot do it procedurally or when you need a scope.
  • Always put a PHP documentation block unless the meaning is obvious. Ex :

    public function getFirstName() : string { return $this->firstName; }

    Here, there is no need for documentation.

  • Always type the variables and put a return type
  • Do not calculate the length of an array in the condition statement of a loop.

    Put it on the assignment statement. This allows us to not calculate length at each loop.

    Wrong :

    for ($i=0; $i < count($myArray); ++$i) { [...] }

    Good :

    for ($i=0, $myArrayLength = count($myArray); $i < $myArrayLength; ++$i) { [...] }
  • Always use === instead of == unless we cannot do otherwise. == can do conversions so === performs better.

Next section : Shell side

Main sections>Installation

Installation

You can install OTRA via Composer.

OTRA has its own system to load classes so we can skip autoloader generation.

At the time of writing, we cannot do this with the require command so we first disable the update and then we use the update command with the --no-autoloader parameter.

composer create-project otra/skeleton --remove-vcs yourProjectFolderName

If you want to use the latest version of OTRA in development, you can put in your composer.json this line :

"otra/otra": "dev-develop as ^1.0.0-dev"

Next section : Configuration

Main sections>A few last tips

Previous section : HTTP headers

A few last tips

To know all the commands simply type :

php console.php

As specified in this help, you can have more detailed help on a command :

php console.php help myCommand

To avoid that Composer adds autoloader files which are useless with OTRA, you should not pass by PHPStorm (until we can add the option --no-autoloader) to update Composer packages.

Next section : Troubleshooting

Main sections>HTTP headers

Previous section : All about database

HTTP headers

You can configure the Content Security Policy and the Feature Policy in your actions.

Feature Policies have default values for the development environment, not for the production one.

You can override default values for development environment like so :

MasterController::$featurePolicy['dev']['sync-script'] = "'self'";

... and defining production Feature Policy like so :

MasterController::$featurePolicy['prod'] = [ 'accelerometer' => "'none'", 'ambient-light-sensor' => "'none'", 'autoplay' => "'none'", 'battery' => "'none'", 'camera' => "'none'" ];

The configurations will be overwritten.

You can define CSPs almost the same way :

MasterController::$csp['dev'] = MasterController::$csp['prod'] = [ 'connect-src' => '\'self\' https://api.ssllabs.com https://hstspreload.org https://http-observatory.security.mozilla.org https://securityheaders.com https://sshscan.rubidus.com https://tls.imirhil.fr https://tls-observatory.services.mozilla.com https://www.immuniweb.com' ];

The configurations will be merged.

Next section : A few last tips

Main sections>Configuration>Project configuration>Watching files

Previous section : Tips for faster synchronization

Watching files

On unix systems

You can initiate a watcher to listening for class mapping, typescript files, scss files and route configuration updates by typing this command :

php console.php genWatcher

This command only work on unix systems because it uses the inotify command.

Do not hesitate to look the following section to improve synchronization speed if needed.

As usual, you can filter what you want to watch with parameters, see the command help for more information.

On Windows

If you use PHPStorm, I have put some things to help you to configure file watchers in the folder ideConfiguration like scopes and file watchers presets.

For the scopes, you need to copy the folder scopes in your related .idea folder.

For the file watchers, you can import them via File > Settings > Tools > File Watchers > Import.

Main sections>Configuration>Project configuration>Main configuration files

Main configuration files

Do not touch bundles/config/Config.php, it is a generated file. This file can be moved in a later version of the framework.

The main configuration file is config/AllConfig.php. It contains generic configuration that will work for development and production environments.

Values that can be modified in this file :

  • CACHE_PATH : location of the generated files, especially the productions files for now
  • VERSION : used for dynamic caching of CSS/JS resources
  • RESOURCE_FILE_MIN_SIZE : aimed to load CSS/JS resources directly into the templates if their size is under this size.

The related environment specific configuration files are in config/dev/AllConfig.php and config/prod/AllConfig.php respectively.

Beware, in this file, the driver name must match with the related class name in OTRA (e.g. : Pdomysql).

You must, even empty (for the time being), have a file bundles/App/config/Config.php where App is the name of ... your application.

It will contains additional configuration that you want to pass like paths for example.

In the file config/AdditionalClassFiles.php, must contains the paths of OTRA classes that are included dynamically via require(_once)/include(_once) directives. Most of the time, you do not have to touch this file.

Next section : Routes configuration file

Main sections>Configuration>Project configuration>Routes configuration file

Previous section : Main configuration files

Routes configuration file

The file can be as simple as this one.

<?php return [ 'index' => [ 'chunks' => ['/', 'App', 'frontend', 'index', 'IndexAction'], 'resources' => [ 'template' => true ] ] ]; ?>
  • index is the name of the route.
  • chunks contains many parameters :
  • the url;
  • the app name;
  • the bundle name;
  • the controller name;
  • the action name. Always specify this name in PascalCase.
  • resources contains informations on client side.
  • template at true, it will tells that it is a static page.
    It allows performance improvement by caching the generated page.
  • bundle_css must be an array that contains all the css file names (without the extension) that are related to the bundle
  • bundle_js must be an array that contains all the js file names (without the extension) that are related to the bundle
  • _css must be an array that contains all the css file names (without the extension) that are related to the controller
  • _js must be an array that contains all the js file names (without the extension) that are related to the controller
  • core_css must be an array that css files from the framework's core
  • core_js must be an array that js files from the framework's core
  • bootstrap must be an array that contains TO COMPLETE
  • post must be an array that contains default POST parameters
  • get must be an array that contains default GET parameters
  • session must be an array that contains default SESSION parameters

The route order is important so be sure to put the most generic ones at the end.

When we specify resources files, we can order them by telling their loading position like that :

'resources' => [ '_css' => ['users'], 'bundle_css' => ['backendUsers'], 'core_css' => ['lightbox'], '_js' => ['_5'=>'users'], 'bundle_js' => ['base', 'backend', 'form', 'notifications'], 'core_js' => ['_4' => 'lightbox'] ]

lightbox.js will be loaded before users.js.

Next section : Tips for faster synchronization

Main sections>Configuration>Project configuration>Tips for faster synchronization

Previous section : Routes configuration file

Tips for faster synchronization

If your editor does not synchronize fast enough with external modifications (in the case of file watchers for example), you can check this :

cat /proc/sys/fs/inotify/max_user_watches

If this shows a lower number than 524288 then edit the file /etc/sysctl.conf and adds this line :

fs.inotify.max_user_watches = 524288

Once you have done that, you must apply this change by doing :

sudo sysctl -p --system

Don't forget to restart your IDE after that operation.

In the case of PHPStorm, you also can go to :

Settings > Appearance & Behavior > System settings > Synchronization

Here you can put Save files automatically if application is idle for to 1 second.

This way, you will see much faster your JavaScript files generated by TypeScript for example.

Next section : Watching files

Main sections>Configuration>Server configuration>Nginx configuration

Previous section : PHP requirements

Nginx configuration

There is no .htaccess for Nginx, see Apache section for that.

Now we will edit the configuration file /etc/nginx/sites-available/environment.yourdomain.com.

You can now generate a server configuration file with this command :

otra genServerConfig /etc/nginx/sites-available/dev.yourdomain.com dev

You will need to use this configuration file or something similar according to your architecture...

In this file, the penultimate location block indicates the entry point of the framework.

The second one handles the php parsing via PHP-FPM.

It also specifies the kind of environment you want like development or production (dev or prod) like so ...

fastcgi_param APP_ENV dev;

and the database test ids ...

fastcgi_param TEST_LOGIN root; fastcgi_param TEST_PASSWORD '';

For your own database, you can use the same system.

/!\ Of course, change those ids to something more secure !

Do not hesitate to look at the Nginx boilerplate for further informations on how to complete your configuration.

Once it is done, create a symbolic link to activate your site :

sudo ln -s /etc/nginx/sites-available/yourdomain.com /etc/nginx/sites-enabled/

You can disable your site later with the unlink command.

Create the logs folder if you did not do it yet :

sudo mkdir /var/log/nginx/yourdomain

Verify that nothing already listens on port 80 and, of course, (re)start PHP-FPM and Nginx :

sudo service php7.3-fpm start && sudo service nginx start

Main sections>Configuration>Server configuration>PHP requirements

Previous section : Configuring hosts

PHP requirements

You also need to activate the library inotify.

Inotify is a PECL extension that will allow OTRA to create file watchers.

To install inotify, you will need PEAR and some development dependencies like phpsize (phpize) :

sudo apt update sudo apt install php-pear php7.3-dev sudo pecl install inotify echo "extension=inotify" > /etc/php/7.3/mods-available/inotify.ini sudo phpenmod inotify

If php looks in wrong folders for inotify configurations, you may have not clean old php installation.

For example, for a PHP 7.2 installation remove it that way :

apt purge php7.2 php7.2-common

Next section : Nginx configuration

Main sections>Configuration>Server configuration>Command line requirements

Previous section : Apache configuration

Command line requirements

On *nix systems

You also have to set environment variables in your shell configuration to use the command line in good conditions.

It may be ~/.bashrc, ~/.zshrc or another location depending on your environment.

export TEST_LOGIN root; export TEST_PASSWORD '';

On Windows

TODO

Next section : Configuring hosts

Main sections>Configuration>Server configuration>Apache configuration

Apache configuration

I recommend to not use .htaccess file when possible, it allows to deactivate the functionality that searches for this kind of files. You can then put :

AllowOverride None

In the future, you will be able to generate a server configuration file with this command :

otra genServerConfig /etc/nginx/sites-available/dev.yourdomain.com dev apache

...but it only works for Nginx as we speak.

Next section : Command line requirements

Main sections>Troubleshooting

Previous section : A few last tips

Troubleshooting

Be sure to put an ending PHP tag in your PHP files as the OTRA PHP rewriting system needs them to work correctly.

If you use $_SERVER['HTTP_HOST'] in your website, don't forget to specify in your terminal, via your IDE or not, this environment variable in order to make the console tasks work correctly.

Next section : Contributing

Retour

New OTRA version : 1.0.0-alpha.2.3.0

By Lionel Péramo from Wexample Labs, the

Description of the transition from the version 1.0.0-alpha.2.2.0 to the version 1.0.0-alpha.2.3.0 :

  • The Content Security Policy (CSP) is now dynamically handled via OTRA. Nonces can now be generated for the attributes nonce with the function parent::getRandomNonceForCSP() in the templates. You will be able to use the policy script-src 'strict-dynamic'.
  • A security directive has been added in the server configuration generation task to hide sensible informations about your server like the Nginx version for example. The sources maps are now also handled in the referrer conditions.
  • The related directives to the "Feature Policy" are now handled and have default values for the development environment. Those directives and the CSP are defined in the OTRA Master Controller and are available at any moment.
  • If a file is named sw.js or serviceWorker.js then they will be automatically moved in the /web folder when generated by the otra buildDev task.
  • The OTRA global constants that should not be modified are now centralized and generated by the task otra createGlobalConstants.
  • The "dump" functions are now different if we come from the command line or from a web page.
  • Management of the internal PHP server task reviewed and improved.
  • Many bug fixes.

Retour

Blog arrival and a new OTRA version : 1.0.0-alpha.2.2.0

By Lionel Péramo from Wexample Labs, the

Here is finally the brand new blog which informs you about the new features, evolutions and bug fixes of the PHP OTRA framework.

Description of the transition from the version 1.0.0-alpha.2.1.0 to the version 1.0.0-alpha.2.2.0 :

  • Updates the debug bar positioning in order to always see it whatever the CSS of the project.
  • Reorganization of OTRA controllers and templates.
  • The deploy task is now operational on unix systems.
  • The parameter cookie_samesite has been added with strict value for session cookies for more security.
  • Default values for SQL table properties can now be set in the file schema.yml.
  • The library lightbox.scss can now be used in projects that are not part of the OTRA framework itself.
  • We can now generate the web manifest in its gzipped minified version.
  • The clearCache task has been reviewed to clean more different things in the cache folder like CSS files, JS files, templates, etc.
  • The handling of the protection via HTTP_REFERRER have to be handled in server configuration now and assets will not be loaded via PHP anymore.
  • A new task named genServerConfig allows to generate server configurations. It only handles Nginx for now.
  • A new task named genSitemap allows to generate basic sitemaps for SEO purposes.
  • The sourcemaps generation is now configurable via the AllConfig.php files.
  • Automated tests have been added for the architecture tasks.
  • The database model creation task can now be launched in non interactive mode.
  • A function has been added in the traduction tools file in order to handle preferred languages via HTTP_ACCEPT_LANGUAGE.
  • Many bug fixes.

Do not forget to modify your namespaces by replacing src by otra when needed.