1

我们应该将 pdo 设置function __constructprivateorpublic吗?如果我将它设置为 ,它会成为漏洞的主题public吗?

这是我的数据库类,

class pdo_connection
{
    public $connection; // handle of the db connexion


    public function __construct($dsn = 'mysql:host=localhost;dbname=xxx_2013',$username = 'root',$password = 'xxx')
    {   
    $this->dsn = $dsn;
        $this->username = $username;
        $this->password = $password;
        $this->connection();
    }


    private function connection()
    {
        try
        {
            $this->connection = new PDO($this->dsn, $this->username, $this->password, array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
            $this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
        }
        catch (PDOException $e) 
        {
            # call the get_error function
            $this->get_error($e);
        }
        // return $this->connection;
    }
...
}

编辑:

class database extends common
{
    /**
     * Set the class property.
     */
    protected $connection = null;
    protected $dsn,$username,$password;

    /**
     * Set the class contructor.
     * @reference: http://us.php.net/manual/en/language.oop5.magic.php#object.sleep
     */
    public function __construct($dsn,$username,$password)
    {
        $this->dsn = $dsn;
        $this->username = $username;
        $this->password = $password;
        //$this->connect();


    }

    /**
     * make the pdo connection.
     * @return object $connection
     */
    public function connect()
    {
        try
        {
            # MySQL with PDO_MYSQL  
            # To deal with special characters and Chinese character, add charset=UTF-8 in $dsn and array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8").

            $this->connection = new PDO($this->dsn, $this->username, $this->password, array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
            $this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
        }
        catch (PDOException $e) 
        {
            # call the get_error function
            $this->get_error($e);
        }
    }

    /**
     * get the number of rows in a result as a value string.
     * @param string $query
     * @param array $params
     * @return number
     */
    public function num_rows($query, $params = array())
    {
        try 
        {
            # create a prepared statement
            $stmt = $this->connection->prepare($query);

            # if $params is not an array, let's make it array with one value of former $params
            if (!is_array($params)) $params = array($params);

            # execute the query
            $stmt->execute($params);

            # return the result
            return $stmt->rowCount();
        } 
        catch (PDOException $e) 
        {
            # call the get_error function
            $this->get_error($e);
        }
    }

    /**
     * fetch a single row of result as an array ( =  one dimensional array).
     * @param string $query
     * @param array $params
     * @param boolean $array_to_object
     * @return object/ array
     */
    public function fetch_assoc($query, $params = array(), $array_to_object = true)
    {
        try
        {
            # prepare the query
            $stmt = $this->connection->prepare($query);

            # if $params is not an array, let's make it array with one value of former $params
            if (!is_array($params)) $params = array($params);

            # the line
            //$params = is_array($params) ? $params : array($params);
            # is simply checking if the $params variable is an array, and if so, it creates an array with the original $params value as its only element, and assigns the array to $params.

            # This would allow you to provide a single variable to the query method, or an array of variables if the query has multiple placeholders.

            # The reason it doesn't use bindParam is because the values are being passed to the execute() method. With PDO you have multiple methods available for binding data to placeholders:

            # bindParam
            # bindValue
            # execute($values)

            # The big advantage for the bindParam method is if you are looping over an array of data, you can call bindParam once, to bind the placeholder to a specific variable name (even if that variable isn't defined yet) and it will get the current value of the specified variable each time the statement is executed.

            # execute the query
            $stmt->execute($params);

            # return the result
            if($array_to_object) return parent::array_to_object($stmt->fetch());
                else return $stmt->fetch();
        }
        catch (PDOException $e) 
        {
            # call the get_error function.
            $this->get_error($e);
        }

        /*
        or,

        catch (Exception $e)
        {
            // Echo the error or Re-throw it to catch it higher up where you have more
            // information on where it occurred in your program.
            // e.g echo 'Error: ' . $e->getMessage(); 

            throw new Exception(
                __METHOD__ . 'Exception Raised for sql: ' . var_export($sql, true) .
                ' Params: ' . var_export($params, true) .
                ' Error_Info: ' . var_export($this->errorInfo(), true),
                0,
                $e);
        }
        */
    }

    /**
     * fetch a multiple rows of result as a nested array ( = multi-dimensional array).
     * @param string $query
     * @param array $params
     * @param boolean $array_to_object
     * @return object/ array
     */
    public function fetch_all($query, $params = array(), $array_to_object = true)
    {
        try
        {
            # prepare the query
            $stmt = $this->connection->prepare($query);

            # if $params is not an array, let's make it array with one value of former $params
            if (!is_array($params)) $params = array($params);

            # when passing an array of params to execute for a PDO statement, all values are treated as PDO::PARAM_STR.
            # use bindParam to tell PDO that you're using INTs
            # wrap the bindParam function in a foreach that scan your parameters array
            # it's $key + 1 because arrays in PHP are zero-indexed, but bindParam wants the 1st parameter to be 1, not 0 (and so on).
            /*
            foreach($params as $key => $param)
            {
              if(is_int($param))
                {
                    $stmt->bindParam($key + 1, $param, PDO::PARAM_INT);
                }
              else
                {
                    $stmt->bindParam($key + 1, $param, PDO::PARAM_STR);
                }
            }

            # execute the query
            $stmt->execute();
            */

            # execute the query
            $stmt->execute($params);

            # return the result
            if($array_to_object) return parent::array_to_object($stmt->fetchAll(PDO::FETCH_ASSOC));
                else return $stmt->fetchAll(PDO::FETCH_ASSOC);
        }
        catch (PDOException $e) 
        {
            # call the get_error function
            $this->get_error($e);
        }
    }

    /**
     * return the current row of a result set as an object.
     * @param string $query
     * @param array $params
     * @return object
     */
    public function fetch_object($query, $params = array())
    {
        try
        {
            # prepare the query
            $stmt = $this->connection->prepare($query);

            # if $params is not an array, let's make it array with one value of former $params
            if (!is_array($params)) $params = array($params);

            # execute the query
            $stmt->execute($params);

            # return the result
            return $stmt->fetchObject();
            //return $stmt->fetch(PDO::FETCH_OBJ);
        }
        catch (PDOException $e) 
        {
            # call the get_error function
            $this->get_error($e);
        }
    }

    /**
     * insert or update data.
     * @param string $query
     * @param array $params
     * @return boolean - true.
     */
    public function run_query($query, $params = array())
    {
        try
        {
            $stmt = $this->connection->prepare($query);
            $params = is_array($params) ? $params : array($params);
            $stmt->execute($params);
            return true;
        }
        catch (PDOException $e) 
        {
            # call the get_error function
            $this->get_error($e);
        }
    }

    /**
     * with __sleep, you return an array of properties you want to serialize. the point is to be able to exclude properties that are not serializable. eg: your connection property.
     * @return array
     */
    public function __sleep()
    {
        return array('dsn', 'username', 'password');
    }

    /**
     * the intended use of __wakeup() is to reestablish any database connections that may have been lost during serialization and perform other reinitialization tasks.
     */
    public function __wakeup()
    {
        $this->connect();
        //$this->connection =  new PDO($this->dsn, $this->username, $this->password, array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
        //$this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    }

    /**
     * display error.
     * @return string
     */
    public function get_error($e) 
    {
        $this->connection = null;
        die($e->getMessage());
    }

    /**
     * close the database connection when object is destroyed.
     */
    public function __destruct()
    {
        # set the handler to NULL closes the connection propperly
        $this->connection = null;
    }
}

用法:

$database = new database(DSN,DB_USER,DB_PASS);
$connection = $database->connect();
var_dump($connection);

结果,

null

它应该是,

object(database)[1]
  protected 'connection' => 
    object(PDO)[2]
  protected 'dsn' => string 'mysql:host=localhost;dbname=xxx_2013' (length=42)
  protected 'username' => string 'xxx' (length=4)
  protected 'password' => string 'xxx' (length=5)
4

1 回答 1

7

不,你想错了。您的公共方法是您提供给使用您的类的其他开发人员的 API。

在编写课程结束时,假设您正在将您的文档交给另一个开发人员。您将列出其他开发人员可以使用的“端点”。目前有:

  • __construct()
  • connection()

显然,您想要connection()更多的东西,connect()因为对于其他开发人员查看您的代码以了解它的作用更有意义。甚至makeConnection()更好。

单身人士很糟糕

将构造函数设置为私有通常是出于以下原因:单例。你想避免全局状态、单例等——它们是不好的做法,使测试变得困难等等。

在对象存在于共享内存中的语言中,可以使用单例来保持低内存使用率。您无需创建两个对象,而是从全局共享的应用程序内存中引用现有实例。在 PHP 中没有这样的应用程序内存。在一个 Request 中创建的 Singleton 正是针对该请求而存在的。在同时完成的另一个 Request 中创建的 Singleton 仍然是一个完全不同的实例。因此,单例的两个主要目的之一在这里不适用。

阅读这篇文章,以更深入地了解为什么单例只是愚蠢的。如果您不想要多个连接实例,请不要创建一个. 如果您忍不住要创建一个,那么您需要重新考虑您的架构(这应该不会太糟糕,因为处理数据库的东西通常处于您正在做的任何事情的早期阶段)。

最后,您的构造函数需要是public。为什么?因此,使用它的开发人员(将自己想象成另一个开发人员)可以将其用于预期目的。


额外说明:

  1. 您的用户名/密码不应该被硬编码到类构造函数中,您应该在创建对象时传递这些。

  2. 不要$this->connection()从你的构造函数调用。如果你这样做,你不妨把它全部推到那里。相反,请致电:

    $db = new pdo_connection($username, $password, $etc);
    $db->connection();

这意味着您可以随心所欲地传递您的对象,但您只在运行该connection()方法时使用资源(创建连接)。

于 2013-08-05T10:40:52.847 回答