때때로 데이터베이스 연결에 관한 질문을 봅니다.
대부분의 대답은 내가하는 방식이 아니거나 정확하게 대답을 얻지 못할 수도 있습니다. 어쨌든; 내가하는 방식이 나를 위해 일하기 때문에 나는 그것에 대해 생각해 본 적이 없습니다.
그러나 여기에 미친 생각이 있습니다. 아마도 내가이 모든 일을 잘못하고있을 수도 있고, 만약 그렇다면; 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 속성을 재정의 하고 사이트에 대한 다른 전역 구성을 수행합니다.
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를 배우고 mysql 대신 PDO를 사용하기 시작한 이후로 엄청난 개선의 여지가 있다고 생각합니다.
그래서 저는 몇 가지 초보자 튜토리얼을 따라했고 다른 것들을 시도했습니다 …
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
– 클래스 , extends
내 connect_pdo
– 클래스 , I라는 공용 함수가 getAreaName
내 데이터베이스에 대한 요청을 처리합니다.
꽤 깔끔한 것 같아요.
매력처럼 작동
합니다. 그래서 기본적으로 제가하는 방식입니다.
또한 클래스 내에서 DB에서 무언가를 가져와야 할 때마다 다음과 비슷한 작업을 수행합니다.
$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 내부의 변수에 연결을 넣었으므로 참조 만했고 갈 수 있습니다. 효과가있다. 예상되는 결과를 얻습니다 …
그러나 그것에 관계없이; 내가 여기서 멀리 떨어져 있는지 말해 주실 수 있다면 정말 감사하겠습니다. 대신해야 할 일, 개선을 위해 변경할 수 있거나 변경해야하는 영역 등 …
배우고 싶어요 …
답변
목표
내가보기에이 경우의 목표는 두 가지입니다.
- 데이터베이스 당 단일 / 재사용 가능한 연결 생성 및 유지
- 연결이 제대로 설정되었는지 확인
해결책
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 );
}
}
이렇게하면 중앙 집중식 구조를 갖게되어 필요할 때만 연결이 만들어집니다. 또한 단위 테스트 및 유지 관리 프로세스가 훨씬 쉬워집니다.
이 경우 공급자는 부트 스트랩 단계 어딘가에서 찾을 수 있습니다. 이 접근 방식은 또한 DB에 연결하는 데 사용하는 구성을 정의 할 명확한 위치를 제공합니다.
이것은 매우 단순화 된 예 입니다. 다음 두 동영상을 시청하면 도움이 될 수도 있습니다.
또한 PDO 사용에 대한 적절한 자습서를 읽을 것을 강력히 권장합니다 (온라인에는 나쁜 자습서 로그가 있습니다).
답변
$_SESSION
전 세계적으로 DB 연결에 액세스 하는 데 사용하지 않는 것이 좋습니다 .
몇 가지 작업 중 하나를 수행 할 수 있습니다 ( 최악에서 모범 사례 순으로 ).
- 함수 및 클래스 내부를
$dbh
사용하여 액세스global $dbh
-
단일 레지스트리를 사용하고 다음과 같이 전역 적으로 액세스합니다.
$registry = MyRegistry::getInstance(); $dbh = $registry->getDbh();
-
다음과 같이 데이터베이스 핸들러를 필요한 클래스에 삽입합니다.
class MyClass { public function __construct($dbh) { /* ... */ } }
나는 마지막 것을 적극 추천합니다. DI (의존성 주입), IoC (Inversion of Control) 또는 단순히 Hollywood 원칙 (전화하지 마십시오. 전화하겠습니다)으로 알려져 있습니다.
그러나 조금 더 발전된 것이며 프레임 워크없이 더 많은 “배선”이 필요합니다. 따라서 종속성 주입이 너무 복잡하다면 여러 전역 변수 대신 단일 레지스트리를 사용하십시오.
답변
최근 저도 비슷한 답변 / 질문을 받았습니다. 누군가가 관심이있는 경우를 대비하여 이것이 내가 한 일입니다.
<?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 인스턴스로 취급하고, 전달하고, 동일한 작업을 수행하는 등의 작업을 수행 할 수 있습니다.
답변
$dsn = 'mysql:host=your_host_name;dbname=your_db_name_here'; // define host name and database name
$username = 'you'; // define the username
$pwd='your_password'; // password
try {
$db = new PDO($dsn, $username, $pwd);
}
catch (PDOException $e) {
$error_message = $e->getMessage();
echo "this is displayed because an error was found";
exit();
}
답변
