在PHP中,将数据库连接/对象导入函数的最佳方法是什么?
以下是几个选项:在PHP中,将数据库连接/对象导入函数的最佳方法是什么?,php,database,Php,Database,以下是几个选项: $connection = {my db connection/object}; function PassedIn($connection) { ... } function PassedByReference(&$connection) { ... } function UsingGlobal() { global $connection; ... } 因此,传入、通过引用传递或使用全局。我在考虑只在一个只有一个数据库连接的项目中使用的函数。
$connection = {my db connection/object};
function PassedIn($connection) { ... }
function PassedByReference(&$connection) { ... }
function UsingGlobal() {
global $connection;
...
}
因此,传入、通过引用传递或使用全局。我在考虑只在一个只有一个数据库连接的项目中使用的函数。如果有多个连接,则必须传入或通过引用传递
我认为当您在PHP5中使用对象时,不需要通过引用传递,因此传入或使用全局是两种可能性
我问这个问题的原因是因为我厌倦了总是在函数参数中加入$connection。以上都没有
所有的
mysql
函数都可以选择使用数据库连接参数。如果不使用该参数,则假定mysql_connect()的最后一个连接。我的建议是在大部分代码中避免使用全局连接-这很危险,很难跟踪,并且会咬到你
我这样做的方法是使用一个名为getDB()的函数,该函数可以通过构造函数注入在类级别,也可以是公共类中的静态函数
因此,代码变为
class SomeClass {
protected $dbc;
public function __construct($db) {
$this->dbc = $db;
}
public function getDB() {
return $this->dbc;
}
function read_something() {
$db = getDB();
$db->query();
}
}
或者使用公共共享类
function read_something() {
$db = System::getDB();
$db->query();
}
无论您做了多少优雅的系统设计,总有一些项目在范围内必须是全局的(比如DB、Session、Config),我更喜欢将它们作为静态方法保留在我的系统类中
让每个类都需要通过构造函数进行连接是实现这一点的最佳方式,我所说的最佳方式是最可靠和隔离的
但是,请注意,使用公共共享类执行此操作可能会影响使用它完全隔离对象的能力,以及对这些对象执行单元测试的能力。尝试以面向对象的方式设计代码。使用数据库的方法应分组在一个类中,类实例应包含数据库连接作为类变量。这样,数据库连接就可以用于需要它的函数,但它不是全局的
class MyClass {
protected $_db;
public function __construct($db)
{
$this->_db = $db;
}
public function doSomething()
{
$this->_db->query(...);
}
}
这样,静态$connectionObject在getConnection调用之间被保留。我使用Singleton ResourceManager类通过整个应用程序处理DB连接和配置设置之类的内容:
class ResourceManager {
private static $DB;
private static $Config;
public static function get($resource, $options = false) {
if (property_exists('ResourceManager', $resource)) {
if (empty(self::$$resource)) {
self::_init_resource($resource, $options);
}
if (!empty(self::$$resource)) {
return self::$$resource;
}
}
return null;
}
private static function _init_resource($resource, $options = null) {
if ($resource == 'DB') {
$dsn = 'mysql:host=localhost';
$username = 'my_username';
$password = 'p4ssw0rd';
try {
self::$DB = new PDO($dsn, $username, $password);
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
} elseif (class_exists($resource) && property_exists('ResourceManager', $resource)) {
self::$$resource = new $resource($options);
}
}
}
然后在函数/对象/任何地方:
function doDBThingy() {
$db = ResourceManager::get('DB');
if ($db) {
$stmt = $db->prepare('SELECT * FROM `table`');
etc...
}
}
我使用它来存储消息、错误消息和警告,以及全局变量。关于何时实际使用这种类型的类,有一个有趣的问题。我看到很多人都建议使用某种静态变量 从本质上讲,全局变量和静态变量之间的差别很小。除了语法,它们有完全相同的特征。因此,通过用静态变量替换全局变量,您将一无所获。在大多数示例中,存在一定程度的解耦,静态变量不是直接引用的,而是通过静态方法(例如单例或静态注册表)引用的。虽然稍好一些,但这仍然存在全球性的问题。如果您需要在应用程序中使用多个数据库连接,那么您就完蛋了。如果您想知道代码的哪些部分有副作用,您需要手动检查实现。这并不是决定应用程序成败的因素,但它会使应用程序更难维护 我建议您在以下两项中选择一项:
- 将实例作为参数传递给需要它的函数。这是迄今为止最简单的,它具有范围狭窄的所有优点,但它可能变得相当笨拙。它也是引入依赖关系的来源,因为代码的某些部分可能最终成为中间人。如果发生这种情况,请继续
- 将实例放在对象的范围内,对象具有所需的方法。例如,如果方法
需要数据库连接,则将其传递到Foo->doStuff()
的构造函数中,并将其设置为Foo
上的受保护实例变量。您仍然可能会遇到传递方法的一些问题,但与方法相比,使用笨拙的构造函数通常不是什么问题。如果您的应用程序变得足够大,您可以使用依赖项注入容器来实现自动化Foo
function doDBThingy() {
$db = ResourceManager::get('DB');
if ($db) {
$stmt = $db->prepare('SELECT * FROM `table`');
etc...
}
}