पीडीओ कनेक्शन को ठीक से कैसे स्थापित किया जाए


92

मैं समय-समय पर डेटाबेस से जुड़ने से संबंधित प्रश्न देखता हूं।
अधिकांश उत्तर मैं ऐसा करने का तरीका नहीं है, या हो सकता है कि मुझे सही उत्तर न मिले हों। वैसे भी, मैंने इसके बारे में कभी नहीं सोचा क्योंकि मैं जिस तरह से करता हूं वह मेरे लिए काम करता है।

लेकिन यहाँ एक पागल विचार है; शायद मैं यह सब गलत कर रहा हूँ, और अगर ऐसा है; मैं वास्तव में जानना चाहूंगा कि 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 सीखना शुरू किया था, और 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- वर्ग , मैं एक सार्वजनिक समारोह कहा जाता है 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 के अंदर एक वेरिएबल में कनेक्शन डाला है , मुझे सिर्फ इसका जिक्र करना है और मैं जाने के लिए अच्छा हूँ। यह काम करता हैं। मुझे मेरे अपेक्षित परिणाम मिले ...

लेकिन इसकी परवाह किए बिना; मैं वास्तव में सराहना करूंगा यदि आप लोग मुझे बता सकते हैं कि क्या मैं यहां से दूर हूं। इसके बजाय मुझे क्या करना चाहिए, जिन क्षेत्रों में सुधार के लिए मुझे बदलाव करना चाहिए या बदलना चाहिए ...

मैं सीखने के लिए उत्सुक हूं ...


9
आपको एक बार में अपने आवेदन में हर एक फाइल को शामिल करने के बजाय एक ऑटोलैडर का उपयोग करना चाहिए ।
लूसिटानियन

जवाबों:


105

लक्ष्य

जैसा कि मैंने इसे देखा, इस मामले में आपका उद्देश्य दो गुना है:

  • प्रति डेटाबेस एकल / पुन: प्रयोज्य कनेक्शन बनाएं और बनाए रखें
  • सुनिश्चित करें कि कनेक्शन ठीक से सेट किया गया है

उपाय

मैं पीडीओ कनेक्शन से निपटने के लिए अनाम फ़ंक्शन और फ़ैक्टरी पैटर्न दोनों का उपयोग करने की सलाह दूंगा। इसका उपयोग इस तरह दिखेगा:

$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 );
    }

}

इस तरह से आपके पास एक केंद्रीकृत संरचना होगी, जो यह सुनिश्चित करती है कि कनेक्शन केवल तभी बनाया जाता है जब आवश्यक हो। यह इकाई-परीक्षण और रखरखाव की प्रक्रिया को बहुत आसान बना देगा।

इस मामले में प्रदाता बूटस्ट्रैप अवस्था में कहीं पाया जाएगा। यह दृष्टिकोण एक स्पष्ट स्थान भी देगा जहां कॉन्फ़िगरेशन को परिभाषित करने के लिए, जिसे आप डीबी से कनेक्ट करने के लिए उपयोग करते हैं।

ध्यान रखें कि यह एक बहुत ही सरल उदाहरण है । आपको निम्नलिखित दो वीडियो देखने से भी लाभ हो सकता है:

इसके अलावा, मैं दृढ़ता से पीडीओ के उपयोग के बारे में एक उचित ट्यूटोरियल पढ़ने की सलाह दूंगा (ऑनलाइन खराब ट्यूटोरियल का एक लॉग है)।


3
चूंकि PHP5.3 भी EOL के पास है। पुराने PHP संस्करणों वाली अधिकांश साइटें वास्तव में Wordpress के लिए सस्ती होस्टिंग हैं। पेशेवर विकास पर पूर्व 5.3 वातावरण का प्रभाव (वे थोड़े इस तरह से स्निपेट्स से लाभान्वित होंगे) मेरे अनुमान में, नगण्य है।
tereško

5
@thelolcat मैं आपसे सहमत हूँ। यह है और अधिक या कम एक ही जवाब। यदि आप इस तथ्य को नहीं देखते हैं कि यह पूरी तरह से अलग है।
PeeHaa

1
@thelolcat, तो आपको सीखना चाहिए कि निर्भरता इंजेक्शन क्या है। खुद को शर्मिंदा करने के बजाय जारी रखें। मजेदार रूप से पर्याप्त है, ऊपर की पोस्ट में दूसरा वीडियो (शीर्षक: " डोन्ट लुक फॉर थिंग्स" ) वास्तव में समझाया गया था कि DI क्या है और इसका उपयोग कैसे करना है ... लेकिन निश्चित रूप से आप ऐसी तुच्छ चीजों के लिए बहुत उन्नत हैं।
tereško

2
यह एक पुराना उत्तर है, लेकिन एक अच्छा है - और अंत में मैसूरल्डो के लिए एक बढ़िया लिंक
स्ट्रॉबेरी

1
@ कम से कम आपको पहले सीखना चाहिए कि पीडीओ का उपयोग कैसे करें। मैं इस ट्यूटोरियल की सिफारिश करूंगा : wiki.hashphp.org/PDO_Tutorial_for_MySQL_Developers , क्योंकि यह उन लोगों के लिए सटीक रूप से बनाया गया है जो mysql_*पीडीओ से माइग्रेट करना चाहते हैं । फिर आप वापस आ सकते हैं और इस समाधान को देख सकते हैं, जिसका उद्देश्य लोगों पर है, जो पहले से ही पीडीओ का उपयोग करते हैं, लेकिन कई वर्गों के बीच DB कनेक्शन को साझा करने के लिए एक तरीका चाहिए।
tereško

24

मैं आपको $_SESSIONविश्व स्तर पर अपने DB कनेक्शन का उपयोग न करने का सुझाव दूंगा।

आप कुछ चीजों में से एक कर सकते हैं ( सर्वोत्तम प्रथाओं के लिए सबसे खराब क्रम में ):

  • पहुँच $dbhका उपयोग कर global $dbhअपने कार्यों और वर्गों के अंदर
  • एक सिंगलटन रजिस्ट्री का उपयोग करें, और विश्व स्तर पर पहुंचें, जैसे:

    $registry = MyRegistry::getInstance();
    $dbh = $registry->getDbh();
  • डेटाबेस हैंडलर को उन वर्गों में इंजेक्ट करें जिन्हें इसकी आवश्यकता है, जैसे:

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

मैं पिछले एक की अत्यधिक सिफारिश करूंगा। यह निर्भरता इंजेक्शन (DI), नियंत्रण के व्युत्क्रम (IoC), या बस हॉलीवुड सिद्धांत के रूप में जाना जाता है (हमें कॉल न करें, हम आपको कॉल करेंगे)।

हालांकि, यह थोड़ा अधिक उन्नत है और एक रूपरेखा के बिना अधिक "वायरिंग" की आवश्यकता है। इसलिए, यदि निर्भरता इंजेक्शन आपके लिए बहुत जटिल है, तो वैश्विक चर के एक समूह के बजाय एक सिंगलटन रजिस्ट्री का उपयोग करें।


इसलिए जब मैं sqlQueryइसका विस्तार करता हूं तो मैं अपने डीबी कनेक्शन को वैश्विक स्तर पर एक्सेस करता हूं, क्योंकि मैं सत्र में प्रवेश करता हूं connect_pdo?
थॉमसके

7

मैं हाल ही में एक ऐसे ही उत्तर / प्रश्न पर आया था। यह वही है जो मैंने किया है, अगर किसी को दिलचस्पी है:

<?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();

हालांकि यह सामान्य पीडीओ की तरह लग सकता है (यह \Library\केवल उसी के द्वारा बदलता है ), यह वास्तव में ऑब्जेक्ट को तब तक इनिशियलाइज़ नहीं करता है जब तक आप पहली विधि को नहीं कहते, जो भी हो। यह इसे और अधिक अनुकूलित बनाता है, क्योंकि पीडीओ ऑब्जेक्ट निर्माण थोड़ा महंगा है। यह एक पारदर्शी वर्ग है, या इसे एक भूत कहा जाता है , जो आलसी लोडिंग का एक रूप है । आप $ DB को एक सामान्य पीडीओ उदाहरण के रूप में मान सकते हैं, इसे पास कर सकते हैं, समान संचालन कर सकते हैं, आदि।


इसे "डेकोरेटर पैटर्न" कहा जाता है
यांग

0
$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();
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.