如何自动加载文件名与 class 名称不同的 classes?
How do I autoload classes that have a file name different from the class name?
我看过这些,
How to autoload class with a different filename? PHP
Load a class with a different name than the one passed to the autoloader as argument
我可以更改,但在我的 MV* 结构中我有:
/models
customer.class.php
order.class.php
/controllers
customer.controller.php
order.controller.php
/views
...
实际上class他们是,
class CustomerController {}
class OrderController{}
class CustomerModel{}
class OrderModel{}
我试图与名称保持一致。如果我不放 class 名称后缀 (Controller, Model),我无法加载 class 因为那是重新声明。
如果我保留 classes 的名称,自动加载会失败,因为它会查找名为
的 class 文件
CustomerController
当文件名真的是,
customer.controller.php
我唯一的方法是(无顺序):
- 使用create_alias
- 重命名我的文件(customer.model.php 到 customermodel.php)
- 重命名我的 classes
- 使用正则表达式
- 对包含的文件使用 bootstrap(
include
,
require_once
, 等)
?
示例代码,
function model_autoloader($class) {
include MODEL_PATH . $class . '.model.php';
}
spl_autoload_register('model_autoloader');
看来我得重命名文件了,
http://www.php-fig.org/psr/psr-4/
"The terminating class name corresponds to a file name ending in .php. The file name MUST match the case of the terminating class name."
在我看来,这可以通过一些基本的字符串操作和一些约定来处理。
define('CLASS_PATH_ROOT', '/');
function splitCamelCase($str) {
return preg_split('/(?<=\w)(?=[A-Z])/', $str);
}
function makeFileName($segments) {
if(count($segments) === 1) { // a "model"
return CLASS_PATH_ROOT . 'models/' . strtolower($segments[0]) . '.php';
}
// else get type/folder name from last segment
$type = strtolower(array_pop($segments));
if($type === 'controller') {
$folderName = 'controllers';
}
else {
$folderName = $type;
}
$fileName = strtolower(join($segments, '.'));
return CLASS_PATH_ROOT . $folderName . '/' . $fileName . '.' . $type . '.php';
}
$classNames = array('Customer', 'CustomerController');
foreach($classNames as $className) {
$parts = splitCamelCase($className);
$fileName = makeFileName($parts);
echo $className . ' -> '. $fileName . PHP_EOL;
}
输出为
Customer -> /models/customer.php
CustomerController -> /controllers/customer.controller.php
您现在需要在自动加载器函数中使用 makeFileName
。
我本人是强烈反对这种东西的。我会使用反映命名空间和 class 名称的命名空间和文件名。我也会使用 Composer.
(我找到了 splitCamelCase
here。)
我看过这些,
How to autoload class with a different filename? PHP
Load a class with a different name than the one passed to the autoloader as argument
我可以更改,但在我的 MV* 结构中我有:
/models
customer.class.php
order.class.php
/controllers
customer.controller.php
order.controller.php
/views
...
实际上class他们是,
class CustomerController {}
class OrderController{}
class CustomerModel{}
class OrderModel{}
我试图与名称保持一致。如果我不放 class 名称后缀 (Controller, Model),我无法加载 class 因为那是重新声明。
如果我保留 classes 的名称,自动加载会失败,因为它会查找名为
的 class 文件CustomerController
当文件名真的是,
customer.controller.php
我唯一的方法是(无顺序):
- 使用create_alias
- 重命名我的文件(customer.model.php 到 customermodel.php)
- 重命名我的 classes
- 使用正则表达式
- 对包含的文件使用 bootstrap(
include
,require_once
, 等)
?
示例代码,
function model_autoloader($class) {
include MODEL_PATH . $class . '.model.php';
}
spl_autoload_register('model_autoloader');
看来我得重命名文件了,
http://www.php-fig.org/psr/psr-4/
"The terminating class name corresponds to a file name ending in .php. The file name MUST match the case of the terminating class name."
在我看来,这可以通过一些基本的字符串操作和一些约定来处理。
define('CLASS_PATH_ROOT', '/');
function splitCamelCase($str) {
return preg_split('/(?<=\w)(?=[A-Z])/', $str);
}
function makeFileName($segments) {
if(count($segments) === 1) { // a "model"
return CLASS_PATH_ROOT . 'models/' . strtolower($segments[0]) . '.php';
}
// else get type/folder name from last segment
$type = strtolower(array_pop($segments));
if($type === 'controller') {
$folderName = 'controllers';
}
else {
$folderName = $type;
}
$fileName = strtolower(join($segments, '.'));
return CLASS_PATH_ROOT . $folderName . '/' . $fileName . '.' . $type . '.php';
}
$classNames = array('Customer', 'CustomerController');
foreach($classNames as $className) {
$parts = splitCamelCase($className);
$fileName = makeFileName($parts);
echo $className . ' -> '. $fileName . PHP_EOL;
}
输出为
Customer -> /models/customer.php
CustomerController -> /controllers/customer.controller.php
您现在需要在自动加载器函数中使用 makeFileName
。
我本人是强烈反对这种东西的。我会使用反映命名空间和 class 名称的命名空间和文件名。我也会使用 Composer.
(我找到了 splitCamelCase
here。)