This is my first serious programming effort, so I'd like some comments about what I did so far.
Project structure:
/ |--App/ |--Backend/ |--Common/ |--Configuration.php |--Route.php |--Frontend/ |--webroot/ |--assets/ |--index.php |--public_html -> link to App/webroot/ |--vendor/ |--composer.json
The files I'd like you to check out:
./composer.json:
{
"require": {
"gabrielbull/browser": "3.1.2"
},
"require-dev": {
"maximebf/debugbar": "v1.10.4"
},
"autoload" : {
"psr-4": {
"App\\Backend\\": "App/Backend/",
"App\\Common\\": "App/Common/",
"App\\Frontend\\": "App/Frontend/"
}
}
}
./App/webroot/index.php:
<?php
/**
* this file is the entry point for all of the domains.
* it is the only php file in each webroot.
*/
/**
* composer autoload
*/
require '../../vendor/autoload.php';
use App\Common;
/**
* define constants and $GLOBALS for the whole application:
* - php error reporting type
* - db details -> TO_DO
* - lang settings
*
* ENV constant affects:
* - debugbar display
*/
new Common\Configuration();
/**
* set the controller type: backend or frontend?
*/
$route = new Common\Route();
$controller_type = $route->getControllerType(); // -> TO_DO
/**
* DebugBar
*/
use DebugBar\StandardDebugBar;
if (ENV != 'prod') {
$debugbar = new StandardDebugBar();
$debugbarRenderer = $debugbar->getJavascriptRenderer();
$debugbarRenderer->setBaseUrl('assets/DebugBar');
$debugbar["messages"]->addMessage($GLOBALS['lang']);
}
?>
<html>
<head>
<?php
echo $debugbarRenderer->renderHead()
?>
</head>
<body>
<?php
echo $debugbarRenderer->render()
?>
</body>
</html>
./App/Common/Configuration.php:
<?php
namespace App\Common;
use Browser\Language;
/**
* this class is a singleton and has no property.
* the constructor only executes static methods that set constants and global variables
*
* static methods seem faster than "regular" ones
*/
class Configuration
{
public function __construct()
{
\define('TEN_YEARS', \time() + (10 * 365 * 24 * 60 * 60)); // used for cookies expiry time
/**
* static methods are called with 'ClassName::' or 'self::', NOT '$this->'
*/
self::defineEnv();
self::setGlobalsLang();
}
/**
* this method defines ENV constant accessing $_SERVER["DOCUMENT_ROOT"]
*
* ENV constant affects:
* - php error reporting
* - db details -> TO_DO
*
* @return void
*/
private static function defineEnv()
{
/* @var $document_root string */
$document_root = $_SERVER["DOCUMENT_ROOT"];
switch ($document_root) {
case (\preg_match('/^\/var\/www\/.*/', $document_root) ? true : false):
$env = 'dev';
\ini_set('error_reporting', -1);
break;
case (\preg_match('/\/test\/.*/', $document_root) ? true : false):
$env = 'test';
\ini_set('error_reporting', -1);
break;
default:
$env = 'prod';
\ini_set('display_errors', 0);
break;
}
/**
* const FOO = 'BAR';
* vs
* define('FOO', 'BAR');
*
* http://stackoverflow.com/questions/2447791/define-vs-const/3193704#3193704
* unless you need any type of conditional or expressional definition, use
* const instead of define() - simply for the sake of readability!
*/
\define('ENV', $env);
return;
}
/**
* this method sets $GLOBALS[lang] variable basing on:
* 1. lang cookie
* 2. browser language -> https://github.com/gabrielbull/php-browser
* 3. ip geolocation -> http://ip2c.org/about/
*
* @global string $GLOBALS['lang_source'] is where i got language from
* @global string $GLOBALS['lang'] is the translation abbreviation
* @return void
*/
private static function setGlobalsLang()
{
// lang cookie
$lang_cookie = \filter_input(\INPUT_COOKIE, 'lang_code');
$GLOBALS['lang']['cookie_lang'] = $lang_cookie;
if ($lang_cookie) {
$GLOBALS['lang']['source'] = 'cookie';
$GLOBALS['lang']['code'] = $lang_cookie;
return;
}
// browser language
$language = new Language;
$browser_lang = $language->getLanguage();
$GLOBALS['lang']['browser_lang'] = $browser_lang;
if ($browser_lang === 'it') {
// if the browser language is 'it' there is no need for ip geolocation
$GLOBALS['lang']['code'] = 'it';
\setcookie('lang_code', $GLOBALS['lang']['code'], TEN_YEARS);
return;
}
// ip geolocation
$client_country_code = self::ip2c();
$GLOBALS['lang']['ip2c_lang'] = $client_country_code;
if ($client_country_code === 'it') {
$GLOBALS['lang']['source'] = 'ip2c';
$GLOBALS['lang']['code'] = 'it';
\setcookie('lang_code', $GLOBALS['lang']['code'], TEN_YEARS);
return;
}
$GLOBALS['lang']['code'] = 'en';
\setcookie('lang_code', $GLOBALS['lang']['code'], TEN_YEARS);
return;
}
/**
* this method gets the country code (2 letters) of the client ip
*
* @return string
*/
private static function ip2c()
{
$country_2l_code = '';
/**
* http://stackoverflow.com/questions/3003145/how-to-get-the-client-ip-address-in-php
* @var $ip string
*/
$ip = $_SERVER['REMOTE_ADDR'];
/**
* @var string 1;IT;ITA;Italy
*/
$s = \file_get_contents('http://ip2c.org/'.$ip);
switch($s[0]) {
case '0':
// Something wrong
break;
case '1':
$reply = \explode(';', $s);
/*echo '<br>Two-letter: '.$reply[1];
echo '<br>Three-letter: '.$reply[2];
echo '<br>Full name: '.$reply[3];*/
$country_2l_code = $reply[1];
break;
case '2':
// Not found in database
break;
}
return \strtolower($country_2l_code); // it
}
}
./App/Common/Route.php:
<?php
namespace App\Common;
/*
* this class sets the proper controller type: backend or frontend?
*/
class Route
{
public function __construct()
{
}
public function getControllerType()
{
}
}
How many bad errors have I made?