source

PDO 연결을 올바르게 설정하는 방법

factcode 2022. 12. 5. 21:15
반응형

PDO 연결을 올바르게 설정하는 방법

데이터베이스 접속에 관한 질문이 가끔 보입니다.
대부분의 답변은 제가 하는 방식이 아닙니다. 그렇지 않으면 제가 정답을 정확하게 얻지 못할 수도 있습니다.어쨌든, 나는 그것에 대해 생각해 본 적이 없다. 왜냐하면 내가 하는 방식이 나에게 맞기 때문이다.

하지만 제가 이 모든 것을 잘못하고 있는지도 모릅니다. 만약 그렇다면 PHP와 PDO를 사용하여 MySQL 데이터베이스에 올바르게 연결하여 쉽게 액세스할 수 있도록 하는 방법을 알고 싶습니다.

방법은 다음과 같습니다.

먼저 파일 구조(아래로 스트라이프)를 나타냅니다.

public_html/

* index.php  

* initialize/  
  -- load.initialize.php  
  -- configure.php  
  -- sessions.php   

index.index.aces index index.
위에는 맨에가 at at at at at at at at at at at 。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★★★★★★★★★★★★...

.phppp
여기서는 기본적으로 몇 가지 php.ini 속성을 덮어쓰고 사이트에 대해 다른 글로벌 구성을 수행합니다.

.phppp
다른 클래스가 이 클래스를 확장할 수 있도록 클래스에 연결을 설정했습니다.

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를 사용하기 시작한 이래 크게 개선될 여지가 있다고 생각합니다.
그래서 저는 몇 가지 초보자용 튜토리얼을 따라 여러 가지 시도를 해봤습니다.

§
세션의 다음과 합니다.

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-수업, 난 '공적인 직무'가 있어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 사용에 대한 적절한 튜토리얼을 읽을 것을 강력히 권장합니다(온라인에 잘못된 튜토리얼 로그가 있습니다).

저는 사용하지 않는 .$_SESSIONDB를 사용합니다.

몇 가지 작업 중 하나를 수행할 수 있습니다(최악의 작업부터 베스트 프랙티스까지 순서대로).

  • ★★$dbh를 사용합니다.global $dbh 및 내부( and class)
  • 싱글톤 레지스트리를 사용하여 다음과 같이 글로벌하게 액세스합니다.

    $registry = MyRegistry::getInstance();
    $dbh = $registry->getDbh();
    
  • 다음과 같이 데이터베이스 핸들러를 필요한 클래스에 삽입합니다.

    class MyClass {
        public function __construct($dbh) { /* ... */ }
    }
    

저는 마지막 것을 강력히 추천합니다.이는 의존성 주입(DI), 제어 반전(IoC), 또는 할리우드 원칙(전화하지 마십시오. 전화하겠습니다)으로 알려져 있습니다.

그러나, 이것은 조금 더 발전했고 프레임워크 없이 더 많은 "배선"이 필요합니다.따라서 의존관계 주입이 너무 복잡할 경우 여러 글로벌 변수 대신 싱글톤 레지스트리를 사용합니다.

최근에 나 스스로 비슷한 대답/질문에 도달했다.관심 있는 사람을 대비해서 이렇게 했어요.

<?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 오브젝트 작성에는 다소 비용이 많이 들기 때문에 더욱 최적화됩니다.투명 클래스 또는 고스트라고 불리는 레이지 로딩의 한 형태입니다.$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();
}

설정에는 몇 가지 기본적인 결함이 있습니다.

  1. configure.php파일이 웹 서버의 문서 루트에 있으면 안 됩니다. 서버가 잘못 구성되면 인증 정보가 일반에 노출될 수 있습니다.당신은 그런 일이 일어나지 않을 거라고 생각할지도 모르지만, 그것은 당신이 감수할 필요가 없는 위험입니다.수업도 거기 있으면 안 돼중요한 건 아니지만 공개하지 않아도 되는 건 공개하면 안 돼요
  2. 특히 대규모 프로젝트를 취급하고 있지 않는 한, 「초기화」디렉토리는 사용할 수 없습니다.하나의 큰 파일을 로드하는 것이 동일한 내용을 가진 10개의 작은 파일을 로드하는 것보다 약 10배 빠릅니다.이것은 프로젝트가 성장함에 따라 실제로 증가하는 경향이 있으며 PHP 사이트의 속도를 크게 저하시킬 수 있습니다.
  3. 실제로 필요한 경우가 아니면 짐을 싣지 않도록 하세요.예를 들어 실제로 필요한 경우가 아니면 PDO와 연결하지 마십시오.session_start()실제로 세션에 읽기/쓰기 할 수 있습니다.클래스의 인스턴스를 만들지 않는 한 클래스 정의 파일을 포함하지 마십시오.접속 수에 제한이 있습니다.또한 세션과 같은 API는 동일한 리소스를 사용하는 다른 사용자의 코드 실행을 일시 중지할 수 있는 "잠금"을 설정합니다.
  4. 내가 아는 한, 당신은 Composer를 사용하지 않는군요.사용하시는 것이 좋습니다.자신의 코드와 서드파티의 의존관계 모두에 있어서, 생활이 매우 용이하게 됩니다.

중간 규모 프로젝트에서 사용하는 것과 유사한 디렉토리 구조를 제안합니다.

init.php                Replaces public_html/initialize. Your PDO connection details
                        are held here.
classes/                Replaces public_html/classes
vendor/autoload.php     Your class autoload script generated using the
                        industry standard Composer command line tool
composer.json           The file where you describe how autoload.php
                        operates among other things. For example if you
                        don't use namespaces (maybe you should) it might be:
                        {"autoload": {"psr-4": { "": "classes/" }}}
public_html/index.php   Your landing page
public_html/other.php   Some other page
public_html/css/foobar.css ...and so on for all static resources

init.php을 사용하다

date_default_timezone_set('Etc/UTC');

require 'vendor/autoload.php';

$pdoConnect = function() {
  static $pdo = false;
  if (!$pdo) {
    $pdo = new PDO('mysql:dbname=db;host=localhost', 'user', 'password');
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
  }
  return $pdo;
};

// similar anonymous functions for session_start(), etc.

index.php음음음같 뭇매하다

require '../init.php';

$pdo = $pdoConnect();

// go from there

other.php는 비슷할 수 있지만 데이터베이스에 연결되지 않을 수 있으므로 $pdoConnect는 실행되지 않습니다.

가능한 한 코드의 대부분을 클래스 디렉토리에 기입해 주세요.index.php,other.php 한 한 달콤한 것 입니다.

언급URL : https://stackoverflow.com/questions/11369360/how-to-properly-set-up-a-pdo-connection

반응형