我正在创建一个网站,我正在使用Apache作为我的网络服务器。
我创建了一个不使用类的网站。我的所有函数都位于一个文件中,我只是在每个需要使用某些函数的页面上包含此文件。
我现在想要换成OOP方法,但我无法理解如何自动加载我的类。我已经通过了一些相关的页面,如; 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;
}
}
所以......
如何使用 spl_autoload_register()的一些实现将这些类加载到另一个 .php 文件中,以便我可以使用它们来创建对象?例如,在名为“ Testing.php ”
以前我会在我的文件夹根目录之外解析一个 .ini 文件以获取数据库连接的详细信息,我是否应该使用我的新方法来获取连接详细信息class DbConfig ?
答案 0 :(得分: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类,只要你的代码知道如何找到它(无论这是硬编码路径还是其他方式),它在哪里都无关紧要。
答案 1 :(得分: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来处理依赖项/类的自动加载,并允许使用PRS-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最常见)。
答案 2 :(得分: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);
如果您的项目不够大,建议不要使用命名空间,只需使用目录和文件名来执行此操作