2011-01-06 48 views
8

我刚开始使用OOP PHP并遇到问题。我已经成立了一个通用的MySQL类,允许我连接到一个数据库,并具有一定的功能,从表中获得记录:PHP OOP:如何在其他类中使用通用MySQL类

class mysql{ 
    //some lines to connect, followed by: 
    public function get_record($sql) 
    { 
     $result = mysql_result(mysql_query($sql)); 
     return $result; 
     //obiously it's a bit more advanced, but you get the picture. 

    } 
} 

接下来,我有一个类来获得用户的详细信息:

class user{ 
    __construct($id) 
    { 
     $this->id = $id 
    } 
    public function get_username($id) 
    { 
     $username = get_record("SELECT name FROM users WHERE id = '".$this->id."'"); 
     return $username; 
    } 
} 

我试过这个,但得到了函数get_record未知的错误。我通过添加$ mysql = new mysql()来解决这个问题。到用户类。

但是,为每个使用我的数据库方法的类实例化mysql对象感觉效率很低(几乎所有这些方法都是这样)。

是否有办法让所有其他类都可以访问mysql类及其方法,而无需在每个方法中调用mysql类?

+1

请不要创建MySQL的类。即使PHP已经内置了这样的东西,也有太多的人在使用。它被称为PDO(PHP数据库对象)。 PDO可以转让给其他开发人员,同时必须一次又一次找出其他人的MySQL级别感觉毫无意义。 – kander 2011-01-06 21:25:24

回答

1

您应该将mysql对象传递给每个用户对象。因此,它应该是这样的:

$mysql = new mysql(); 
$user = new user($mysql, $id); 
$name = $user->get_username(); 

class user { 
    public function __construct($mysql, $id) { 
     $this->mysql = $mysql; 
     $this->id = $id; 
    } 
    public function get_username() { 
     $username = $this->mysql->get_record("SELECT name FROM users WHERE id = '".$this->id."'"); 
     return $username; 
    } 
} 
1

设计你的mysql类被静态调用:

$username = Mysql::get_record("SELECT name FROM users WHERE id = '".$this->id."'"); 

http://php.net/manual/en/language.oop5.static.php

+0

我宁愿把它叫做Mysql :: get_record(“SELECT name FROM users WHERE id =%d”,$ this-> id);` – 2011-01-06 19:23:24

+0

OP的确可以做很多改进。我的回答涉及避免不断实例化的狭义问题。 – webbiedave 2011-01-06 19:38:15

0

使用全局变量,尽管这可能不是最好的选择。

$mysql = new mysql(); 

function someFunction() { 
    global $mysql; 
    $mysql->get_record(...) 
} 

或你的mysql类的静态方法(见Singleton

class mysql { 
    public static $theInstance = new mysql(); 
    public static function getInstance() { 
    return $this->theInstance; 
    } 
} 

function someFunction() { 
    $database= mysql::getInstance(); 
    $database->get_record(...) 
} 
+4

呃,请不要建议使用globales! – 2011-01-06 19:22:27

2

这是一个普遍的问题,所以有这个共同的解决方案。如您所知,在软件开发中常见问题的常见解决方案称为设计模式。

有两种设计模式可以帮助您解决此问题。 在一个更抽象的意义上你所面对的问题是:

我怎样才能让在B类获得A类?

的单例模式

“以单例模式一类可以其本身一个实例分发到其他类。”

这不完全是你要找的,因为你的网站可能会使用多个数据库连接。但是,这样被很多人使用。

阅读有关使用一个单独的类作为数据库提供商在这里的一些信息: https://www.ibm.com/developerworks/library/os-php-designptrns/#N10124

在PHP单件模式的更多信息: http://www.fluffycat.com/PHP-Design-Patterns/Singleton/

另一种明智的做法是注册表模式:

注册表模式

您可以f ind有关注册表模式在下面的链接,以及几乎相同的,你正在寻找的实现: http://www.sitecrafting.com/blog/php-patterns-part/

更强大的是单身人士和注册表之间的组合。

祝你好运,享受学习面向对象的PHP!

+2

实际上,在这种特殊情况下,单例模式并不是真的需要 - 毕竟,对数据库连接没有任何作用的任何东西都不需要访问该类,并且通过使用单例,您的整个应用程序可以访问单身人士。注册表也是如此,尽管这是一个稍微好一点的选择。不,我会说数据库交互对象是一个服务,服务可以分配给需要它们的对象,例如通过使用依赖注入模式。请参阅:http://martinfowler.com/articles/injection.html – fwielstra 2011-01-06 19:45:49

5

其中之一,你不需要在这种情况下使用单例 - 或者实际上,你几乎不会做。例如,请参阅this article

其次,我认为你的OO设计有点不合适。面向对象编程和设计的要点是将职责分离到不同的类中。现在,您要为您的User类提供两项主要职责 - 存储/携带一个用户的相关数据,并查询数据服务(在这种情况下,这是一个简单的MySQL /数据库抽象层)。

您应该先将该功能移到单独的对象中。通常这叫做服务 - 所以在这种情况下,它是一个UserService。 A UserService有一个责任:提供对User对象的访问。所以它会八九不离十是这样的:

class UserService { 
    public function __construct($mysql); // uses the mysql object to access the db. 
    public function get($id) { 
     $result = $this->mysql->get_record("select x from y"); 
     $user = new User($result['id'], $result['name']); // assuming user has a constructor that takes an id and a name 
     return $user; 
    } 
    public function save($user); 
    public function delete($user); 
} 

您在您的要求开始将其结合在一起(或者你需要访问用户):

$mysql = new MySQL($credentials); 
$service = new UserService($mysql); 
$user = $service->find(1337); 

它并不完美,但它是一个更简洁的设计。你的MySQL对象做它需要做的事(建立一个连接,执行查询),你的用户对象是愚蠢的,你的服务只做一件事,即在实际的存储层和调用它的事物之间提供一层。