2016-02-22 3 views
4

Я создаю сайт, и я использую Apache в качестве своего веб-сервера.PHP: проблема с автозагрузкой

Я создал сайт без использования классов. Все мои функции расположены в одном файле, и я просто включаю этот файл на каждую страницу, где мне нужно использовать некоторые из функций.

Теперь я хочу перейти на подход ООП, но у меня возникли проблемы с пониманием того, как автоматически загружать мои классы. Я прошел через ряд связанных страниц, например; PSR-4 Example, spl_autoload_register(), Related Question, и я просто не могу об этом подумать.

Итак, поскольку я использую Apache, путь для корня моего веб-сайта: C: \ Apache \ htdocs.

Мои каталоги выглядят следующим образом;

+ htdocs 
    + Lib 
     + Base 
      - User.php 
      - Device.php 
      - Company.php 
      - Database.php 
     + Services 
      - UserService.php 
      - DeviceService.php 
      - CompanyServer.php 
     + Config 
      - DbConfig.php 

В качестве примера, так что вы можете помочь мне получить мою голову вокруг этого, мы будем просто говорить о двух классах DBCONFIG и базы данных.

DbConfig.php (с соединительные детали опущены)

<?PHP 
namespace Lib\Config; 

class DbConfig 
{ 
    protected $serverName; 
    protected $userName; 
    protected $password; 
    protected $dbName; 

    public function __construct() 
    { 
     $this->serverName = 'not my server name'; 
     $this->userName = 'not my username'; 
     $this->passCode = 'not my password'; 
     $this->dbName = 'not my database'; 
    } 
} 

database.php (Очень просто, пока я не могу реально использовать его - в этот момент я добавлю его функциональность)

<?PHP 
namespace Lib\Base; 

use Lib\Config\DbConfig; 

class Database extends DbConfig 
{ 
    protected $connection; 
    private $dataSet; 
    private $sqlQuery; 

    public function __construct() 
    { 
     parent::__construct();  
     $this->connection = null; 
     $this->dataSet = null; 
     $this->sqlQuery = null; 
    } 
} 

Так ..

  1. Как загрузить эти классы, используя некоторую реализацию spl_autoload_register(), в другой файл .php, чтобы я мог использовать их для создания объектов? например, в файле с именем «Testing.php»

  2. Раньше я бы разобрать .ini файл вне корня моей папки, чтобы получить подробную информацию соединения с базой данных, я должен сделать это с моим новым подходом наличия деталей соединения в классе DbConfig?

+2

spl_autoload_register (функция ($ класс) { включать «классы /». $ Класса. '.class.php'; }); 1. Используйте эту функцию для своего .php-файла, который должен всегда загружаться. 2. Имя класса и имя файла должны совпадать, иначе автозагрузка не найдет класс. Например, Testing.php имеет тестирование имени класса. :) –

+0

хорошо сформулированный и структурированный php-вопрос +1 – birdspider

+0

Если вы пытаетесь выполнить PSR-4, почему бы не использовать автозагрузчик [composer] (https://getcomposer.org/)? –

ответ

1

Согласно стандарту PSR-4,

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

Ваши классы, похоже, не имеют этого. Чтобы добавить его, измените namespace Lib\Config; на, например, namespace AskMeOnce\Lib\Config;. Вам нужно будет добавить этот префикс для всех ваших классов.

Затем, используя PSR-4 автозагрузчика вы ссылается, изменить $prefix = 'Foo\\Bar\\'; к $prefix = 'AskMeOnce\\'; и $base_dir = __DIR__ . '/src/'; к $base_dir = 'C:\Apache\htdocs';. Поместите эту функцию в файл с именем autoload.php и потребуйте его в любом файле, который должен знать, как выполнить автозагрузку.

Как только вы require, что автозагрузчик, PHP будет знать, для поиска любого класса, который начинается с пространства имен AskMeOnce в указанном базовом каталоге. После удаления этого префикса из пространства имен пространство имен представляет остальную часть пути. Например, AskMeOnce\Lib\Config\DbConfig Будем искать на <basedir>/Lib/Config/DbConfig.php.

Чтобы ответить на ваши вопросы конкретно, (1) Просто поместите функцию в autoload.php с изменениями, упомянутыми выше. И (2), поскольку ini-файл не является классом PHP, не имеет значения, где он до тех пор, пока ваш код знает, как его найти (будь то жестко закодированный путь или иначе).

+0

Я думал, что мое имя пространства имен верхнего уровня было Lib, поскольку именно там я сохраняю все свои классы ... То есть это означает, что «пространство имен поставщиков» на самом деле не является репрезентативным для самой папки ? Если это так, вы заставили меня понять. – AskMeOnce

+0

Ах. Ваше пространство имен верхнего уровня может быть 'Lib', но это, вероятно, не очень хорошее пространство имен верхнего уровня (потому что это так общее). Если вы все равно хотите это сделать, просто установите '$ prefix = 'Lib \\';'. Как насчет этого? Создайте пространство имен верхнего уровня 'AskMeOnce'. Замените 'Lib \ Config' на' AskMeOnce \ Config'. Создайте свой базовый каталог 'C: \ Apache \ htdocs \ Lib \ AskMeOnce' (добавьте папку AskMeOnce). Таким образом, вы можете включить другие libs в папку lib, если хотите. И «пространство имен поставщиков» является представителем «basedir». Он не превращается в путь к папке, как это делает остальная часть пространства имен. – mkasberg

+0

И это будет означать, что все, что мне нужно, это ** autoloader.php ** на странице, в которой мне нужно было использовать классы (скажем _Testing.php_), которые будут расположены в ** C: \ Apache \ htdocs **? – AskMeOnce

1

Вот краткий пример, который я сколоченный:

Создайте файл с именем autoloader.php. Этот пример был взят от PSR-4 Examples. Измените Acme на название вашего проекта.

Это позволит вам использовать пространства имен, если они хранятся под Lib/, и вы добавляете пространства имен в каждый файл (как вы уже делаете).

<?php 
/** 
* An example of a project-specific implementation. 
* @param string $class The fully-qualified class name. 
* @return void 
*/ 
spl_autoload_register(function ($class) { 

    // project-specific namespace prefix 
    $prefix = 'Acme\\'; 

    // base directory for the namespace prefix 
    $base_dir = __DIR__ . '/Lib/'; 

    // does the class use the namespace prefix? 
    $len = strlen($prefix); 
    if (strncmp($prefix, $class, $len) !== 0) { 
     // no, move to the next registered autoloader 
     return; 
    } 

    // get the relative class name 
    $relative_class = substr($class, $len); 

    // replace the namespace prefix with the base directory, replace namespace 
    // separators with directory separators in the relative class name, append 
    // with .php 
    $file = $base_dir . str_replace('\\', '/', $relative_class) . '.php'; 
    print $file; 
    // if the file exists, require it 
    if (file_exists($file)) { 
     require $file; 
    } 
}); 

Это использует spl_autoload_register для обработки автозагрузку зависимостей/классов, а также позволяет для использования ПРС-4 пространств имен.

Далее, ваш класс Database будет храниться в Lib/Base/Database.php.

<?php 

namespace Acme\Base; 

class Database 
{ 
    private $db; 

    public function __construct(\PDO $db) 
    { 
     $this->db = $db; 
    } 

    public function allUsers() 
    { 
     /* 
     * Query to fetch all users from the database 
     */ 

     return [ 
      [ 
       'username' => 'Bob', 
       'role' => 'member' 
      ], 
      [ 
       'username' => 'Joe', 
       'role' => 'admin' 
      ] 
     ]; 
    } 
} 

И, наконец, ваша страница индекс включает autoloader.php скрипт, который ухаживает автоматически включаются классы.

<?php 

require_once 'autoloader.php'; 

$config = require 'config.php'; 

try { 
    $dbc = new PDO("mysql:dbname={$config['MYSQL']['DATABASE']};host={$config['MYSQL']['HOST']}", 
        $config['MYSQL']['USERNAME'], $config['MYSQL']['PASSWORD']); 
} catch (PDOException $e) { 
    die('Could not connect to database ' . $e->getMessage()); 
} 

$db = new \Acme\Database($dbc); 
print_r($db->allUsers()); 

И, наконец, вы спрашивали о файлах конфигурации. Я использую конфигурационный файл, как так:

<?php 

return [ 
    'MYSQL' => [ 
     'USERNAME' => 'root', 
     'PASSWORD' => '', 
     'DATABASE' => 'test', 
     'HOST' => 'localhost' 
    ] 
]; 

, которая позволяет включать в конфигурационный файл с простым:

$config = require 'config.php'; 

И доступ, как так:

$config['MYSQL']['USERNAME']; 

Я прохожу \PDO соединение с базой данных как зависимость от класса Database. Это называется Dependency Injection.

Другой пример: Lib/Services/UserService.php:

<?php 

namespace Acme\Services; 

class UserService 
{ 
    ... 
} 

Теперь Вы можете назвать это в коде (при условии, что автозагрузчик включена) следующим образом:

$userService = new \Acme\Services\UserService; 

Я также рекомендую проверить Composer. Супер полезно, если вы хотите использовать общедоступные пакеты от Packagist, и его очень легко создать. Поддерживает также автозагрузку PSR- * (наиболее распространенный PSR4).

+0

Это не сработает, если он не переместит все свои классы в папку под названием «classes», что, вероятно, не то, что он хочет сделать. – mkasberg

+0

@mkasberg обновлен. – BugHunterUK

0

зарегистрировать функцию автозагрузки:

добавить код в любом файле может быть включен, прежде чем использовать другие библиотеки классов PHP, например, в файле ввод проекта.

defined('ROOT') or define('ROOT', 'C:/Apache/htdocs'); 
// define root directory 
// or `defined('ROOT') or define('ROOT', __DIR__)` if 
// the file is in the root directory 

spl_autoload_register(function($name) { 
    $file = ROOT . "/{$name}.php"; 
    if(!is_file($file)) { 
     return false; 
    } else { 
     return include $file; 
    } 
}, false, true); 

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

+0

Это не будет работать с его структурой каталогов выше. Не все классы находятся в папке htdocs. – mkasberg

+0

если это так, вы можете попробовать каталоги в своей функции автозагрузки – kcats