PHP类和包括

时间:2018-02-01 21:19:16

标签: php pdo

这是我的困境,我正在尝试将我的php迁移到更多基于对象的代码与旧样式以及从mysqli到pdo。但是当我这样做时,我开始遇到一些特别针对类和依赖的问题。

例如,我有一个名为pdo_connection.php的文件,它保存了我的数据库连接信息。

<?php
define("DSN", "mysql:host=localhost;dbname=user_info");
define("USERNAME", "root");  
define("PASSWORD", "password");  
$options = array(PDO::ATTR_PERSISTENT => TRUE);

try {
    $conn = new PDO(DSN,USERNAME,PASSWORD , $options);
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);  
} catch (Exception $ex) {
    Echo "Folowing Problem: ".$ex->getMessage();
    exit();
}

现在我有一个名为pdo_user的文件,它将保存一个类和函数来处理实际的mysql查询。

//    include_once 'pdo_connection.php';
class data_user
{
    public function __construct() 
    {
        include_once 'pdo_connection.php';
    }       
    // Validate User Login        
    public function val_login($user, $passwd) 
    {
        //include_once 'pdo_connection.php';
        $sel = "CALL `user_info`.`sp_user_login`('$user', '$passwd')";
        $res = $conn->query($sel);
        while ($row = $res->fetch(PDO::FETCH_ASSOC))
        {
            return($row);
        }
    }
}

当我调用该函数时,如果include_once'pdo_connection.php'不在公共函数val_login中,则会立即收到错误。 我尝试将它放入__construct或一直在顶部,它总是抱怨Undefined variable: conn in /var/www/html/mysql_pdo/pdo_user.php on line 27

简单的解决方法是将它放在公共函数val_login中,但我可以看到这是每次调用函数时必须加载的最佳方式。

所以希望有人可以告诉我我错过了什么以及如何加载像conn这样的东西,所有功能都可以访问。

2 个答案:

答案 0 :(得分:3)

您的问题是由于variable scoping

让我们单独查看您的函数,并将pdo_connection.php的内容移到__construct方法中,因为它会更好地突出显示问题:

public function __construct() 
{
    define("DSN", "mysql:host=localhost;dbname=user_info");
    define("USERNAME", "root");  
    define("PASSWORD", "password");  
    $options = array(PDO::ATTR_PERSISTENT => TRUE);

    try {
        $conn = new PDO(DSN,USERNAME,PASSWORD , $options);
        $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);  
    } catch (Exception $ex) {
        Echo "Folowing Problem: ".$ex->getMessage();
        exit();
    }
}       

public function val_login($user, $passwd) 
{
    $sel = "CALL `user_info`.`sp_user_login`('$user', '$passwd')";
    $res = $conn->query($sel);
    while ($row = $res->fetch(PDO::FETCH_ASSOC))
    {
        return($row);
    }
}

在构造函数中,您将创建名为$conn local 变量。构造函数方法完成后,控制返回到调用上下文,$conn变量消失。其范围仅在__construct方法中有效。

如果您希望该连接变量具有更长的生命周期,那么您拥有的唯一真正好的选项(因为构造函数不能返回值)是将该变量存储为class property。一旦这样做,该属性的生命周期将与类实例本身的生命周期相同:

class data_user
{
    // This just defines the property
    protected $conn;

    public function __construct() 
    {
        define("DSN", "mysql:host=localhost;dbname=user_info");
        define("USERNAME", "root");  
        define("PASSWORD", "password");  
        $options = array(PDO::ATTR_PERSISTENT => TRUE);

        try {
            // This is setting the property
            $this->conn = new PDO(DSN,USERNAME,PASSWORD , $options);
            $this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);  
        } catch (Exception $ex) {
            Echo "Folowing Problem: ".$ex->getMessage();
            exit();
        }
    }       

    public function val_login($user, $passwd) 
    {
        $sel = "CALL `user_info`.`sp_user_login`('$user', '$passwd')";
        // This is now accessing the class property and not a local variable
        // that is undefined.
        $res = $this->conn->query($sel);
        while ($row = $res->fetch(PDO::FETCH_ASSOC))
        {
            return($row);
        }
    }
}

我还明确建议在类构造函数中包含其他文件。请考虑这种用法:

define("DSN", "mysql:host=localhost;dbname=user_info");
define("USERNAME", "root");  
define("PASSWORD", "password");  
$options = array(PDO::ATTR_PERSISTENT => TRUE);

try {
    $conn = new PDO(DSN,USERNAME,PASSWORD , $options);
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);  
} catch (Exception $ex) {
    Echo "Folowing Problem: ".$ex->getMessage();
    exit();
}

$data_user = new data_user($conn);
$another_object = new another_object($conn);

这会将您的data_user构造函数更改为:

public function __construct($conn) 
{
    $this->conn = $conn;
}

哪个更简单,允许您在可能需要数据库连接的其他对象之间重用相同的$conn对象,并避免在对象构造函数中使用doing work。它还data_user来自 hdbsql -i 00 -u DDIC -p <password> hdbsql -i 00 -u SYSTEM -p <password> 类,因此在概念上它更容易,因为该类没有真正的理由知道如何连接到您的数据库。它只需要知道连接本身。

答案 1 :(得分:2)

您可能会遇到一些问题。我试图提供几种解决方案。

首先,您可能需要查看PSR4自动加载和命名空间。文件类是自动的&#39;从给定命名结构的目录加载。一旦我发现了自动加载功能,我就感到惊讶。此外,您可以在PHP(http://php.net/manual/en/function.spl-autoload-register.php)中注册自己的自定义自动加载器。这个想法是,如果可以解析一个类的名称来引用该类的文件,那么它可以被自动加载。没有更多include_once,require_once ...

其次,您可能想要了解依赖注入。对象(在这种情况下是依赖关系)被注入到其他对象中,通常在它们的__construct()方法中。

简单来说,我会改变你的课程:

cmd.CommandText = "sp_addserver";
cmd.Parameters.Clear();
cmd.Parameters.Add(new SqlParameter("@server", "MYNEWSERVER"));
cmd.ExecuteNonQuery();

然后你可以像这样使用它:

<?php

namespace Data;

class User
{
    /**
     * The PDO connection
     */
    private $conn;

    /**
     * This receives the connection using dependency injection.
     * @param \PDO $conn     The connection.
     * @return null
     */
    public function __construct(\PDO $conn) 
    {
        $this -> conn = $conn;
    }

    // Validate User Login        
    public function valLogin($user, $passwd) 
    {
        $sel = "CALL `user_info`.`sp_user_login`('$user', '$passwd')";
        $res = $this -> conn ->query($sel);
        while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
            return($row);
        }
    }
}

希望这有帮助吗?如果您有更多问题,请回复。

另一种选择是使$ conn全局化,这不是一种推荐的方法。

另一个选择是创建一个接收$ connection并设置静态属性的类。这不是最好的方法,但比全局$ conn变量更好。

<?php
define("DSN", "mysql:host=localhost;dbname=user_info");
define("USERNAME", "root");  
define("PASSWORD", "password");  
$options = array(PDO::ATTR_PERSISTENT => TRUE);

try {
    $conn = new PDO(DSN,USERNAME,PASSWORD , $options);
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (Exception $ex) {
    Echo "Folowing Problem: ".$ex->getMessage();
    exit();
}

// The connection is injected into the constructor.
$dataUser = new Data\User($conn);
$userRow = $dataUser -> valLogin($user, $passwd);

然后你的val_login方法如下所示:

class Connection
{
    public static $connection;

    public function __construct(\PDO $conn)
    {
        self::$connection = $conn;
    }
}