Использование пространств имен вместо того, чтобы требовать каждый класс отдельно - PullRequest
0 голосов
/ 22 октября 2018

Это мой init.php файл, необходимый для index.php файла:

<?php 

/** 
*
*   Initialization file: Will require all components we need. 
*
**/


/* Set session */
session_start();                                                // Start session

/* Helpers */
require_once 'helpers/Sanitize.php';                            // Sanatizing (escaping) strings 
require_once 'helpers/Token.php';                               // Generate tokens 
require_once 'helpers/Hash.php';                                // Hash class
require_once 'helpers/Input.php';                               // Inputs manipulations
require_once 'helpers/Validation.php';                          // Validation class
require_once 'helpers/Redirect.php';                            // Redirect helper 
require_once 'helpers/Session.php';                             // Session manipulations 
require_once 'helpers/Cookie.php';                              // Cookies manipulations 


/* Core */
require_once 'core/Config.php';                                 // Default global vairables 
require_once 'core/App.php';                                    // Load App class from CORE
require_once 'core/Controller.php';                             // Load Controller class from CORE 
require_once 'core/Database.php';                               // Load Database class 


/* Models */
require_once '/www/myapp/models/System_user.model.php';     // System User Model
require_once '/www/myapp/models/user/User.model.php';           // User Model
require_once '/www/myapp/models/exec/something_usage.model.php';            // something model
require_once '/www/myapp/models/abc/abc.model.php';         // A class for handling trees 
require_once '/www/myapp/models/Group.model.php';           // Group Model
require_once '/www/myapp/models/banana.model.php';          // A class for handling trees 
// require_once '/www/myapp/models/Tree_db.php';            // A class for handling trees 

Как вы можете видеть, я перезагружаю все мои файлы классов, что является плохой практикой.После небольшого исследования я обнаружил, что есть функция, которая автоматически загружает классы всякий раз, когда она вызывается:

// /* Autoload classes from directory */
// spl_autoload_register(function($class) {
//  require_once 'classes/' . $class . '.php';  // No such directory
// });

Я не мог ее использовать, поскольку мои классы не находятся в одной папке, и к ним нелегко перемещаться.,

Я продолжил свое исследование и обнаружил, что могу использовать команду композитора composer dump-autoload -o, которая может потребовать мой код, объявив namespaces в верхней части каждого класса (следуя структуре папок)и use при использовании определенного класса и требовании autoload.php вместо списка, упомянутого выше:

/* Composer */
require_once '../vendor/autoload.php';  // Loading composer components

Я применил это изменение ко всем моим классам - файлам классов контроллеров, файлам классов моделей (и подпапкамфайлы классов), базовые классы и базы данных классов.

Пример: имея папку /www/app/models/system_users.model.php Я добавил пространство имен App\Models; (и имя класса System_users), и если этот объект класса создается в другом классе, я использую use App\Modal\System_uses; вначало файла.

Но я получаю сообщение об ошибке:

[22-Oct-2018 12:27:31] PHP Fatal error:  Uncaught Error: Class 'Config' not found in /www/app/views/login/pages-login.php:14
Stack trace:
#0 /www/app/core/Controller.php(51): require_once()
#1 /www/app/controllers/login.php(27): app\Core\Controller->view('login/pages-log...')
#2 [internal function]: app\Controllers\Login->index()
#3 /www/app/core/App.php(51): call_user_func_array(Array, Array)
#4 /www/public/index.php(15): app\Core\App->__construct()
#5 {main}
  thrown in /www/app/views/login/pages-login.php on line 14
[22-Oct-2018 12:27:31] PHP Fatal error:  Class 'Controller' not found in /www/app/controllers/Error_404.php on line 7
[22-Oct-2018 12:27:31] PHP Stack trace:
[22-Oct-2018 12:27:31] PHP   1. {main}() /www/public/index.php:0
[22-Oct-2018 12:27:31] PHP   2. app\Core\App->__construct() /www/public/index.php:15
[22-Oct-2018 12:27:31] PHP   3. require_once() /www/app/core/App.php:31

Возможно, потому что мне не требуется мой класс Config в представлениях.Но до сих пор с использованием requre once все работало нормально, и мне действительно надоело использовать use App\Core\Config; в верхней части каждого представления.

Как правильно обращаться с подобной ситуацией с пространствами имен?

РЕДАКТИРОВАТЬ:

Я добавляю свою структуру кода:

/ www / public / index.php

<?php 
use MyApp\Core\App;


/** 
*
*   Index: First page a user visits. 
*
**/

# Reuiring init.php: Responsible for initializing classes we want to use.
require_once '../myapp/init.php'; 

# Initialize App class
$app = new App();

/www / myapp / core / controller.php

<?php 
namespace MyApp\Core;
use MyApp\Models\System_user;
use MyApp\Core\Config;

/**
 *
 *  Controller instance: 
 *
 */
class Controller
{

/*=================================
=            Variables            =
=================================*/

    # System User 
    protected $system_user;



/*===============================
=            Methods            =
================================*/


    /**
     *
     *  Model Class: Loads a requested model
     *  @param  $model      String      Gets a model name
     *  
     */
    protected function model($model)
    {
        require_once '../myapp/models/' . $model . '.php';
        return new $model();
    }


    /**
     *
     *  View Class: Loads a requested view
     *  @param  $view       String      Gets a view name 
     *  @param  $data       Array       (optional) Gets an array of variables to pass to the view
     *  @throws                         Plain view 
     *
     */
    protected function view($view, $data=[])
    {
        require_once '../myapp/views/' . $view . '.php';
    } 


    /**
     *
     *  Check if a user is logged in
     *
     */
    protected function is_loggedin()
    {   

        ... 
    }

/ www / myapp / core / app.php

<?php 
namespace MyApp\Core;
// use MyApp\Core\Controller;
use MyApp\Controllers;
/**
 *
 *  App instance: Handles controlles (specifically gets routs data)
 *
 */
class App 
{

    protected $controller   = 'Error_404';
    protected $method       = 'index';
    protected $parameters   = array();
    protected $contollerNamespace;

    public function __construct() 
    {
        # Get parsed URL
        $url    = $this->parseUrl();

        # Check if contorller via input-url exists in the controller folder
        if (file_exists('../myapp/controllers/' . $url[0] . '.php')){
            $this->controller = $url[0];    // Replace current 'home' controller with the new one
            $this->contollerNamespace = 'MyApp\\Controllers\\'.$url[0];
            unset($url[0]);                 // Remove controller name from the array. 
        }

        # Require the controllers class via controllers folder
        require_once '../myapp/controllers/' . $this->controller . '.php';

        # Create a new obect of the controller (by its name)
        $this->controller = new $this->contollerNamespace; // ex: new Home() -- or: new Login() 

        # Chech if method is passed
        if ( isset($url[1]) ) {

            # Check if method exists in class
            if ( method_exists($this->controller, $url[1]) ) {
                # Set new method variable
                $this->method = $url[1];
                unset($url[1]);
            }
        }

        # Set parameters (if any).
        $this->parameters = $url ? array_values($url) : [];

        # Summon controller with the relevant method and variables.
        call_user_func_array([$this->controller, $this->method], $this->parameters);

    }


    /**
     *
     *  Parses the url - Gets the $_GET input via .htaccess definition. 
     *
     */ 
    public function parseUrl()
    {
        if ( isset($_GET['url']) ) {

            return $url = explode('/', filter_var(rtrim($_GET['url'], '/'), FILTER_SANITIZE_URL));

        }
    }

}

/ www / myapp / controllers / login.php

<?php 
namespace MyApp\Controllers;
use MyApp\Core\Controller;
use MyApp\Models\System_user;
use MyApp\Core\Config;

/**
 * Login Class
 */
class Login extends Controller
{


    /**
     *
     * Login Main login Form
     *
     */
    public function index($name ='')
    {   
        // Create a new system user
        $system_user = new System_user();
        // If user is logged in - Redirect to dashboard
        if ( $system_user->check_logged_in() )
            Redirect::to('dashboard');          // Redirect to login form
        else
            $this->view('login/pages-login');   // Redirect to login form
    }


    /**
     *
     *  User login: Creates the user login. 
     *
     */
    public function user_login()
    {
        ...

    }

}

1 Ответ

0 голосов
/ 22 октября 2018

Composer работает по стандарту автозагрузки PSR-4.

https://www.php -fig.org / psr / psr-4 /

В вашем composer.json, добавьте пространство имен автозагрузчика для ваших классов.Например, в моем пакете формы это выглядит следующим образом:

"autoload": {
    "psr-4": {
      "Del\\Form\\": "src/",
      "DelTesting\\Form\\": "tests/unit/Del/Form/"
    }
},

Что это говорит?По сути, все классы в src/ будут иметь пространство имен Del\Form.

Так, например, src/Form.php будет выглядеть так:

<?php

namespace Del\Form;

class Form 
{
    // code
}

Обратите внимание, имя класса должно соответствоватьимя файла, то есть класс Form должен называться Form.php.

Теперь, если вы создаете папки в src, они добавляются в пространство имен.Другой пример, src/Field/Text.php будет выглядеть так:

<?php

namespace Del\Form\Field;

class Text
{
    // code
}

Если вы будете придерживаться этих соглашений, все будет загружаться автоматически.

После редактирования composer.json для добавления пространства имен выполните composer dumpautoload, чтобы сгенерировать карты классов, которые использует композитор.

...