Design Patterns: How to create database object/connection only when needed?

前端 未结 10 942
野的像风
野的像风 2020-11-29 21:04

I\'ve a simple application, say it has some classes and an \"extra\" one that handles database requests. Currently i\'m creating the database object everytime the app is use

相关标签:
10条回答
  • 2020-11-29 21:43

    You could use an singleton pattern to achive this and request everytime you need the database a database object. This results in something like this

    $db = DB::instance();
    

    where DB::instance is declared something like this

    class DB {
    
        //...
    
        private static $instance;    
    
        public static function instance() {
            if (self::$instance == null) {
                self::$instance = new self();
            }
        }
    
        //...
    
    }
    
    0 讨论(0)
  • 2020-11-29 21:45

    I come from the world of Java. Java is resident in memory accross stateless HTML requests. PHP is not. That is a whole different story - and what I like about PHP.

    I simply use: $conn = @pg_connect(DBConnection);

    the DBConnection is a definition containing the information about the host etc.. The @ assures that the current connection is used or a new one is created. How can I do it more easily?

    The data how to connect to the database is stable. The connection itself might be recreated during a request. Why should I program better then the people of PHP and recreate the @? They did that for the PHP community, let's use it.

    By the way, never put heavy objects in a constructor and never let the constructor do some heavy job nor let it happen that an exception can be thrown during construction of an object. You might have an unfinished object resident in your memory. An init-method is to be preferred. I agree on that with Henrique Barcelos.

    0 讨论(0)
  • 2020-11-29 21:47

    This is approximately what I use.

    class Database {
    
        protected static $connection;
    
        // this could be public if you wanted to be able to get at the core database
        // set the class variable if it hasn't been done and return it
        protected function getConnection(){
            if (!isset(self::$connection)){
                self::$connection = new mysqli($args);
            }
            return self::$connection;
        }
        // proxy property get to contained object 
        public function __get($property){
            return $this->getConnection()->__get($property);
        }
        // proxy property set to contained object
        public function __set($property, $value){
            $this->getConnection()->__set($property, $value);
        }
    
        // proxy method calls to the contained object
        public function __call($method, $args){
            return call_user_func_array(array($this->getConnection(), $method), $args);
        }
    
        // proxy static method calls to the contained object
        public function __callStatic($method, $args){
            $connClass = get_class($this->getConnection());
            return call_user_func_array(array($connClass, $method), $args);
        }
    }
    

    Note it only works if there is a single database in play. If you wanted multiple different databases it would be possible to extend this but beware of late static binding in the getConnection method.

    0 讨论(0)
  • 2020-11-29 21:52

    Here is an example of a simple approach:

    class Database {
      public $connection = null ;
    
      public function __construct($autosetup = false){
        if ($autosetup){
          $this->setConnection() ;
        }
      }
    
      public function getProducts(){//Move it to another class if you wish
        $this->query($sql_to_get_products);
      }
    
      public function query($sql) {
        if (!$connection || !$connection->ping()){
          $this->setupConnection() ;
        }
        return $this->connection->query($sql);
      }
    
      public function setConnection(){
        $this->connection = new MySQLi($a, $b, $c, $d) ;
      }
    
      public function connectionAvailable(){
        return ($connection && $connection->ping()) ;
      }
    }
    
    0 讨论(0)
  • 2020-11-29 21:55
    interface IDatabase {
        function connect();
    }
    
    class Database implements IDatabase
    {
        private $db_type;
        private $db_host;
        private $db_name;
        private $db_user;
        private $db_pass;
        private $connection = null;
    
        public function __construct($db_type, $db_host, $db_name, $db_user, $db_pass)
        {
            $this->db_type = $db_type;
            $this->db_host = $db_host;
            $this->db_name = $db_name;
            $this->db_user = $db_user;
            $this->db_pass = $db_pass;
        }
    
        public function connect()
        {
            if ($this->connection === null) {
                try {
                    $this->connection = new PDO($this->db_type.':host='.$this->db_host.';dbname='.$this->db_name, $this->db_user, $this->db_pass);
                    $this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
                    return $this->connection;
                } catch (PDOException $e) {
                    return $e;
                }
            } else {
                return $this->connection;
            }
        }
    }
    

    How about this? In connect(), check if a connection has already been established, if yes, return it, if not, create it and return it. This will prevent you from having TOO many connections open. Let's say, in your controller action, you want to call two methods of UserRepository (that depends on the Database), getUsers() and getBlockedUsers(), if you call these methods, connect() will be called in each one of them, with this check in place it will return the already existing instance.

    0 讨论(0)
  • 2020-11-29 21:57
     <?php
    
        mysql_select_db('foo',mysql_connect('localhost','root',''))or die(mysql_error());
        session_start();
    
        function antiinjection($data)
        {
            $filter_sql = stripcslashes(strip_tags(htmlspecialchars($data,ENT_QUOTES)));
            return $filter_sql;
        }
    
        $username = antiinjection($_POST['username']);
        $password = antiinjection($_POST['password']);
    
        /* student */
            $query = "SELECT * FROM student WHERE username='$username' AND password='$password'";
            $result = mysql_query($query)or die(mysql_error());
            $row = mysql_fetch_array($result);
            $num_row = mysql_num_rows($result);
        /* teacher */
        $query_teacher = mysql_query("SELECT * FROM teacher WHERE username='$username' AND password='$password'")or die(mysql_error());
        $num_row_teacher = mysql_num_rows($query_teacher);
        $row_teahcer = mysql_fetch_array($query_teacher);
        if( $num_row > 0 ) { 
        $_SESSION['id']=$row['student_id'];
        echo 'true_student';    
        }else if ($num_row_teacher > 0){
        $_SESSION['id']=$row_teahcer['teacher_id'];
        echo 'true';
    
         }else{ 
                echo 'false';
        }   
    
        ?>
    

    and in the php file insert javascript

       <script>
                        jQuery(document).ready(function(){
                        jQuery("#login_form1").submit(function(e){
                                e.preventDefault();
                                var formData = jQuery(this).serialize();
                                $.ajax({
                                    type: "POST",
                                    url: "login.php",
                                    data: formData,
                                    success: function(html){
                                    if(html=='true')
                                    {
                                        window.location = 'folder_a/index.php';  
                                    }else if (html == 'true_student'){
                                        window.location = 'folder_b/index.php';  
                                    }else
                                    {
                                        { header: 'Login Failed' };
                                    }
                                    }
                                });
                                return false;
                            });
                        });
                        </script>
    

    another connection

        <?php
    
      class DbConnector {
    
       var $theQuery;
       var $link;
    
       function DbConnector(){
    
        // Get the main settings from the array we just loaded
        $host = 'localhost';
        $db = 'db_lms1';
        $user = 'root';
        $pass = '';
    
        // Connect to the database
        $this->link = mysql_connect($host, $user, $pass);
        mysql_select_db($db);
        register_shutdown_function(array(&$this, 'close'));
    
    }
    
        //*** Function: query, Purpose: Execute a database query ***
    function query($query) {
    
        $this->theQuery = $query;
        return mysql_query($query, $this->link);
    
    }
    
    //*** Function: fetchArray, Purpose: Get array of query results ***
    function fetchArray($result) {
    
        return mysql_fetch_array($result);
    
    }
    
    //*** Function: close, Purpose: Close the connection ***
    function close() {
    
        mysql_close($this->link);
    
    }
    
      }
    
      ?>
    
    0 讨论(0)
提交回复
热议问题