使用名称空间,而不是分别要求每个类

时间:2018-10-22 11:08:49

标签: php oop architecture namespaces

这是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 

如您所见,我正在重新获取我的所有class文件,这是一种不好的做法。 经过小型研究,我发现有一个函数可以在每次调用时自动加载类:

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

我无法使用它,因为我的课程不在一个文件夹中,也不容易导航到。

我继续研究,found out I can use a composer command 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 :(得分:1)

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来生成作曲家使用的类映射。