2
\$\begingroup\$

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?

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.