【问题标题】:PHP 5, Classes and variable/method scope with static/private, $this and self::PHP 5,具有静态/私有、$this 和 self:: 的类和变量/方法范围
【发布时间】:2012-12-12 11:21:03
【问题描述】:

我有这个:

class Database{    
    private $name = '';
    private $user = '';
    private $password = '';   
    private $host = 'localhost';
    private $prefix = '';   
    private $connection_handle = null;

    private function Connect(){
        $this->connection_handle = mysql_connect($this->host, $this->user, $this->password); 

        if( !$this->connection_handle ){
            die( 'Could not connect: ' . mysql_error() );
        }else{
            mysql_select_db( $this->name, $this->connection_handle );
        }
    }

    private function Close(){
        mysql_close( $this->connection_handle );
    } 

    public static function Query( $query ){
        $this->Connect();   
            $result = mysql_query( $query, $this->connection_handle );
            if( !$result ){
                die( 'Error: ' . mysql_error() );
            }else{
                $DatabaseQuery = new DatabaseQuery();
                    $DatabaseQuery->result = $result;       
                    $DatabaseQuery->mysql_num_rows = mysql_num_rows($result);

                return $DatabaseQuery;
            }
        $this->Close();
    } 
}

我已将 Query 设为静态,因为它将被称为“Database::Query” 其他函数不需要任何其他类访问,所以我将它们设为私有......

从查询函数访问连接函数时出现此错误。

“不在对象上下文中使用 $this”

考虑到 private 使这些变量对此类私有但对其中的所有方法都可用,我在获取函数范围时遇到了问题...

我可以做 self::Connect() 但我对它的理解还不够充分,无法保证使用它...

你能解释一下 self:: 和 %this 的区别吗->

我也无法访问我的私有变量,而且它们真的不需要在这个类之外访问,因为这个我再次将它们设为私有......但是 $this->connection_handle 没有变量的范围.

我真的需要将它们全部公开吗?必须有一种方法使它们仅可用于此类及其扩展?

----------------------EDIT:///

我最终将所有变量设为私有静态。 这是一种可接受的方式吗?

----------------------EDIT:///

我现在得到了这个代码:

class Database{    
    private static $name = '';
    private static $user = '';
    private static $password = '';   
    private static $host = 'localhost';
    private static $prefix = '';   
    private static $connection_handle = null;

    private static function Connect(){
        self::$connection_handle = mysql_connect(self::$host, self::$user, self::$password); 

        if( !self::$connection_handle ){
            die( 'Could not connect: ' . mysql_error() );
        }else{
            mysql_select_db( self::$name, self::$connection_handle );
        }
    }

    private static function Close(){
        mysql_close( self::$connection_handle );
    } 

    public static function Query( $query ){
        self::Connect();   
            $result = mysql_query( $query, self::$connection_handle );
            if( !$result ){
                die( 'Error: ' . mysql_error() );
            }else{
                $DatabaseQuery = new DatabaseQuery();
                    $DatabaseQuery->$result = $result;       
                    $DatabaseQuery->$mysql_num_rows = mysql_num_rows($result);

                return &$DatabaseQuery;
            }
        self::Close();
    } 
}

但是返回指针引用不起作用?我实际上对 PHP 指针不是很了解,有人知道我在这里做错了什么吗?

这是因为我在函数中声明了 DatabaseQuery 类的新实例,不是吗。 帮助:)

编辑://////

我已经完成了我的课程,它看起来像这样:

class DatabaseQuery{
    public $result;
    public $mysql_num_rows;        
}

class Database{    
    private static $name = '';
    private static $user = '';
    private static $password = '';   
    private static $host = 'localhost';
    private static $prefix = '';   
    private static $connection_handle = null;

    protected function Connect(){
        self::$connection_handle = mysql_connect(self::$host, self::$user, self::$password); 

        if( !self::$connection_handle ){
            die( 'Could not connect: ' . mysql_error() );
        }else{
            mysql_select_db( self::$name, self::$connection_handle );
        }
    }

    protected function Close(){
        mysql_close( self::$connection_handle );
    } 

    public static function FetchQueries( &$queries ){
        $db_query = array();
            self::Connect();   
                foreach( $queries as $key => $query ){
                    $result = mysql_query( $query, self::$connection_handle );
                    if( !$result ){
                        die( 'Error: ' . mysql_error() );
                    }else{
                        $DatabaseQuery = new DatabaseQuery();
                            $DatabaseQuery->result = $result;       
                            $DatabaseQuery->mysql_num_rows = mysql_num_rows($result);  
                            $db_query[ $key ] = $DatabaseQuery; 
                    }
                }
            self::Close();
        return $db_query;
    } 
}

现在您可以以模型视图控件 (MVC) 的方式调用它,因为您在顶部(或在单独的文件中)定义所有数据

$queries = array(
    "bottoms" => "SELECT * FROM bottoms", 
    "users" => "SELECT * FROM users"           
);            
$dbr = Database::FetchQueries( $queries );


//display some users
while( $row = mysql_fetch_object( $dbr["apps"]->result ) ){
    echo $row->title; 
}    

//display some bottoms
while( $row = mysql_fetch_object( $dbr["bottoms"]->result ) ){
    echo $row->title; 
}

您能告诉我您对这种 MVC 方法的看法吗?

【问题讨论】:

  • 一些更灵活的代码和示例,请参见:stackoverflow.com/a/11580420/367456 - 也可以考虑直接使用 PDO 或 Mysqli,它们已经提供了预制对象,您可以节省整个代码。跨度>

标签: php class scope


【解决方案1】:

您应该使您的 Database 类可实例化。现在,您正在为每个查询打开一个新连接,这具有糟糕的性能(非常糟糕)。您可以将此类设为单例(实际上通常是这样做的,因为通常只有一个与 DB 的连接是有意义的)。

所以你的代码(非常简化)应该是这样的:

class Database
{
  private static $instance;

  protected function __construct() {
    self::$instance = mysql_connect(...);
    // do some error checking!
  }

  protected function __clone() {}

  public static function getInstance() {
    if (!isset(self::$instance)) {
      self::$instance = new Database();
    }
    return self::$instance;
  }

  public function query($sql) {
    do mysql_query(...) and error checking, return $result or your own DatabaseQuery()
  }
}

这样你不能直接调用静态函数进行查询,但是你可以在这个类中添加另一个函数:

public static function makeQuery($sql) {
  $db = self::getInstance();
  return $db->query($sql);
}

要在实例中使用这个类,你应该调用$db = Database::getInstance();,$db 是一个数据库对象,你可以正常调用它的公共方法。如果您只想继续进行静态调用以进行查询,只需调用$result = Database::makeQuery($sql)。无论哪种方式,都可以保证您只有一个与数据库的连接(这就是单例所做的),因此您没有当前为每个查询启动新连接的开销。

ALSO 考虑使用mysqlipdo-mysql 代替旧的和已弃用mysql_* 函数(请参阅mysql_connect 顶部的警告)。有关每个 API 的更多信息和优势,请参阅Choosing a MySQL API

【讨论】:

  • 受保护与私有静态相同?
  • 我打算让 $query 成为一个可以在页面开头执行的查询数组,以便尝试维护 MVC 类型的布局。
  • 我在我的帖子中添加了一个新的编辑,非常感谢您查看并了解您的想法?你能看到我可能遇到的任何问题吗?
  • @JamesT protected 是 publicprivate 的混合体。您可以从子类访问protected 属性/方法,但不能从外部访问。它与static 无关,但您可以根据需要拥有protected static 属性/方法。
  • @JamesT 你的新编辑应该可以工作,但我真的不认为这是一个好的设计。如果您扩展您的框架,您可能会发现您需要在应用程序的其他部分执行查询(考虑使用观察者模式或插件系统:您需要在插件处理程序中执行查询)
猜你喜欢
  • 2017-02-25
  • 1970-01-01
  • 2014-03-23
  • 2011-03-22
  • 1970-01-01
  • 2019-06-08
  • 2012-02-03
  • 2017-05-23
  • 2010-09-24
相关资源
最近更新 更多