Бывает, что в проекте много классов, каждый их которых лежит в своем файле и код начинается с массы require или include.
В php давно существует несколько способов для автоматического подключения таких файлов.
Пожалуй самым известным является менеджер пакетов composer, но иногда его использование неприемлемо по той или иной причине.
Ниже приведу простой пример для решения данной задачи "своими руками".
Описание
Пример файловой структуры проекта:
/libs_1/controllers/item.php
/libs_1/controllers/items.php
/libs_1/models/item.php
/libs_1/models/items.php
/libs_1/test1.php
/libs_2/controllers/postController.php
/libs_2/controllers/postControllers.php
/libs_2/models/postModel.php
/libs_2/models/postModels.php
Пространство имен в для файлов из директорииlibs_1, в нашем примере, Oddler\Lib1 (namespace Oddler\Lib1;)
Для файлов из libs_2 - Oddler\Lib2.
Содержимое файлов одинаковое, для тестов, а разница в наименовании файлов, в первом случаи они не содержат тип в названии и именуются просто, например, item.php.
Во втором же случаи по названияю понятно, что это за файл тип файла, например, postController.php
Примеры использования
<?php
// Pre Init
error_reporting(E_ALL);
ini_set('display_errors', 'On');
// Init
require_once ('core/autoloader.php');
$oAutoloader = new soAutoloader();
// Test Lib 1 (file Name without Type)
$oAutoloader->setNamespace('Oddler\Lib1\\', 'libs_1');
$oItemController1 = new Oddler\Lib1\itemController();
echo $oItemController1->ping() . '<br />';
use Oddler\Lib1\itemModel;
$oItemModel1 = new itemModel();
echo $oItemModel1->ping() . '<br />';
$oTest1 = new Oddler\Lib1\test1();
echo $oTest1->ping() . '<br />';
// Test Lib 2 (file Name with Type)
$oAutoloader->setNamespace('Oddler\Lib2\\', 'libs_2');
$oItemController2 = new Oddler\Lib2\postController();
echo $oItemController2->ping() . '<br />';
$oItemModel2 = new Oddler\Lib2\postsModel();
echo $oItemModel2->ping() . '<br />';
Сам Autoloader
<?php
class soAutoloader {
const DS = DIRECTORY_SEPARATOR;
protected $_aTypes = [
'controller' => 'controllers',
'model' => 'models',
'view' => 'views',
'tool' => 'tools',
];
protected $_aNamespaces = [];
/**
* Register loader with SPL autoloader stack.
*
* @return void
*/
public function __construct()
{
spl_autoload_register(array($this, 'loadClass'));
}
public function setNamespace($sNamespace, $sDir)
{
$this->_aNamespaces[$sNamespace] = $sDir;
}
public function loadClass($sClass)
{
$sSubDir = '';
$sNamespaceDir = '';
$sFullClassName = '';
$sClassName = $sClass;
$pos = strrpos($sClass, '\\');
if ($pos !== false) {
$sNamespace = substr($sClass, 0, $pos + 1);
$sClassName = substr($sClass, $pos + 1);
foreach($this->_aTypes as $sType => $sTmpSubDir) {
$pos2 = strpos(strtolower($sClassName), $sType);
if ($pos2 !== false) {
$sSubDir = $sTmpSubDir;
$sFullClassName = $sClassName;
$sClassName = substr($sClassName, 0, $pos2);
break;
}
}
if (isset($this->_aNamespaces[$sNamespace])) {
$sNamespaceDir = $this->_aNamespaces[$sNamespace];
}
// echo $sNamespace .'<br />';
// echo $sClassName .'<br />';
// echo $sSubDir .'<br />';
}
// echo $sClass .'<br />';
// echo $sNamespaceDir . ' ! ' . $sSubDir . ' ! ' . $sClassName . ' ! ' . '<br />';
// echo $sNamespaceDir . ' ! ' . $sSubDir . ' ! ' . $sFullClassName . ' ! ' . '<br />';
$sBasePath = $sNamespaceDir . self::DS . $sSubDir . self::DS;
$sPath1 = $sBasePath . $sClassName . '.php';
$sPath2 = $sBasePath . $sFullClassName . '.php';
if (file_exists($sPath1)) {
require_once ($sPath1);
} elseif (file_exists($sPath2)) {
require_once ($sPath2);
}
}
}
ToDo
Пока нельзя использовать USE Oddler\Lib1\ только полное название класса Oddler\Lib1\itemModel.