我不时地看到有关连接到数据库的问题。
大多数答案都不是我这样做的,或者我可能就是得不到正确的答案。不管怎样,我从来没有想过它,因为我做它的方式对我来说是有效的。
但这里有一个疯狂的想法;也许我做错了,如果是这样的话;我真的很想知道如何使用PHP和PDO正确地连接到MySQL数据库,并使其易于访问。
我是这样做的:
首先,这是我的文件结构(精简)
public_html/
* index.php
* initialize/
-- load.initialize.php
-- configure.php
-- sessions.php
index.php
在最上面,我有require('initialize/load.initialize.php');
。
load.initialize.php
# site configurations
require('configure.php');
# connect to database
require('root/somewhere/connect.php'); // this file is placed outside of public_html for better security.
# include classes
foreach (glob('assets/classes/*.class.php') as $class_filename){
include($class_filename);
}
# include functions
foreach (glob('assets/functions/*.func.php') as $func_filename){
include($func_filename);
}
# handle sessions
require('sessions.php');
我知道有一种更好的,或者更正确的方法来包含类,但我不记得是什么了。我还没有时间去研究它,但我认为这与autoload
__有关。诸如此类的事情。
configure.php
在这里,我基本上只覆盖了一些php.ini-properties,并为站点做了一些其他的全局配置
connect.php
我已经将连接放到了一个类上,这样其他类就可以扩展这个类……
class connect_pdo
{
protected $dbh;
public function __construct()
{
try {
$db_host = ' '; // hostname
$db_name = ' '; // databasename
$db_user = ' '; // username
$user_pw = ' '; // password
$con = new PDO('mysql:host='.$db_host.'; dbname='.$db_name, $db_user, $user_pw);
$con->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$con->exec("SET CHARACTER SET utf8"); // return all sql requests as UTF-8
}
catch (PDOException $err) {
echo "harmless error message if the connection fails";
$err->getMessage() . "<br/>";
file_put_contents('PDOErrors.txt',$err, FILE_APPEND); // write some details to an error-log outside public_html
die(); // terminate connection
}
}
public function dbh()
{
return $this->dbh;
}
}
# put database handler into a var for easier access
$con = new connect_pdo();
$con = $con->dbh();
//
在这里,我相信还有很大的改进空间,因为我最近开始学习OOP,并使用PDO而不是mysql。
所以我只是遵循了一些初学者的教程,并尝试了不同的东西……
sessions.php
除了处理常规会话,我还将一些类初始化为会话,如下所示:
if (!isset($_SESSION['sqlQuery'])){
session_start();
$_SESSION['sqlQuery'] = new sqlQuery();
}
这样,这个类就可以在任何地方使用了。这可能不是好的做法(?)...
无论如何,这就是这种方法允许我从任何地方做的事情:
echo $_SESSION['sqlQuery']->getAreaName('county',9); // outputs: Aust-Agder (the county name with that id in the database)
在我的sqlQuery
-class ( extends
我的connect_pdo
-class )中,我有一个名为getAreaName
的公共函数,它处理对数据库的请求。
我觉得很整洁。
的工作方式就像魅力
所以我基本上就是这么做的。
此外,每当我需要从数据库中获取不在类中的东西时,我只需执行类似的操作:
$id = 123;
$sql = 'SELECT whatever FROM MyTable WHERE id = :id';
$qry = $con->prepare($sql);
$qry -> bindParam(':id', $id, PDO::PARAM_INT);
$qry -> execute();
$get = $qry->fetch(PDO::FETCH_ASSOC);
因为我将连接放到了connect_pdo.php中的一个变量中,所以我只需要引用它就可以了。它起作用了。我得到了我想要的结果...
但不管怎样,如果你们能告诉我我是不是离得太远了,我将不胜感激。我应该做什么,我可以或应该改变的地方,以改善等…
我渴望学习...
发布于 2012-07-07 05:09:31
目标
在我看来,你在这种情况下的目的有两个:
解决方案
我建议同时使用匿名函数和工厂模式来处理PDO连接。它的用法如下所示:
$provider = function()
{
$instance = new PDO('mysql:......;charset=utf8', 'username', 'password');
$instance->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$instance->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
return $instance;
};
$factory = new StructureFactory( $provider );
然后在不同的文件中,或者在同一文件中更低的位置:
$something = $factory->create('Something');
$foobar = $factory->create('Foobar');
工厂本身应该看起来像这样:
class StructureFactory
{
protected $provider = null;
protected $connection = null;
public function __construct( callable $provider )
{
$this->provider = $provider;
}
public function create( $name)
{
if ( $this->connection === null )
{
$this->connection = call_user_func( $this->provider );
}
return new $name( $this->connection );
}
}
这种方式将使您拥有一个集中式结构,从而确保仅在需要时才创建连接。它还将使单元测试和维护的过程变得更加容易。
在这种情况下,提供程序将在引导阶段的某个位置找到。这种方法还会给出一个明确的位置来定义配置,用于连接到数据库。
请记住,这是一个极其简化的示例。您还可以从观看以下两个视频中获益:
此外,我强烈建议阅读a proper tutorial关于PDO的使用(有一个糟糕的在线教程日志)。
发布于 2012-07-07 04:48:50
我建议不要使用$_SESSION
来全局访问您的数据库连接。
您可以执行以下几项操作之一(从最差到最好的实践):
$dbh
在函数和类中使用global $dbh
$registry = MyRegistry::getInstance();$dbh =将数据库处理程序$registry->getDbh();
类MyClass {公共函数__construct($dbh) { /* ... */ } }
我强烈推荐最后一个。它被称为依赖注入(DI),控制反转(IoC),或者简称为好莱坞原则(不要打电话给我们,我们会打电话给你)。
然而,它更高级一些,需要更多的“连接”而不需要框架。所以,如果依赖注入对你来说太复杂了,那就使用一个单独的注册表,而不是一堆全局变量。
发布于 2014-01-12 08:21:17
最近,我自己也得到了类似的答案/问题。这就是我所做的,如果有人感兴趣的话:
<?php
namespace Library;
// Wrapper for \PDO. It only creates the rather expensive instance when needed.
// Use it exactly as you'd use the normal PDO object, except for the creation.
// In that case simply do "new \Library\PDO($args);" with the normal args
class PDO
{
// The actual instance of PDO
private $db;
public function __construct() {
$this->args = func_get_args();
}
public function __call($method, $args)
{
if (empty($this->db))
{
$Ref = new \ReflectionClass('\PDO');
$this->db = $Ref->newInstanceArgs($this->args);
}
return call_user_func_array(array($this->db, $method), $args);
}
}
要调用它,您只需修改此行:
$DB = new \Library\PDO(/* normal arguments */);
以及类型提示,如果您使用它(\Library\PDO $DB)。
它与公认的答案和你的答案都很相似;但是它有一个显着的优势。考虑下面的代码:
$DB = new \Library\PDO( /* args */ );
$STH = $DB->prepare("SELECT * FROM users WHERE user = ?");
$STH->execute(array(25));
$User = $STH->fetch();
虽然它看起来像普通的PDO (它只受该\Library\
的影响),但实际上直到您调用第一个方法(无论是哪一个方法)时,它才会初始化对象。这使得它更加优化,因为创建PDO对象的开销稍微大一些。它是一个透明的类,或者叫做Ghost,是Lazy Loading的一种形式。您可以将$DB视为一个普通的PDO实例,传递它,执行相同的操作,等等。
https://stackoverflow.com/questions/11369360
复制相似问题