2009-07-27 57 views
6

所以我试图采用良好的面向对象编程技术与PHP。我的大部分(全部读)项目涉及MySQL数据库。我的直接问题涉及我需要开发的用户模型。PHP的继承和MySQL

我目前的项目有代理商和销售线索。代理商和潜在客户都是拥有大量相同信息的用户。所以,显然,我想要一个类代理和一个类导致扩展一个普通的类用户。现在,我的问题如下:

SQL如何最好地处理加载这些对象?我不想在实例化代理或潜在客户时执行多个SQL语句。但是,逻辑告诉我,当用户构造函数被触发时,它应该执行一条SQL语句来加载代理和潜在客户之间的共同信息(用户名,密码,电子邮件,联系信息等)。 Logic还告诉我,当Agents或Leads构造函数被触发时,我想执行SQL来加载对Agents或Leads类唯一的数据....但是,逻辑还告诉我,执行2每当我需要代理或主管时,SQL语句(因为可能每个成千上万)。

我试过寻找这个通常如何处理没有成功的例子......也许我只是在寻找错误的东西?

回答

7

你基本上有三种方法解决这个问题(其中之一,我会立即消除):

每班
  1. 一个表(这是一个我会消除);
  2. 具有可选列的记录类型;和
  3. 具有子表的记录类型取决于您加入的类型。

为了简单起见,我一般推荐(2)。所以一旦你有你的桌子:

CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY, 
    type VARCHAR(10), 
    name VARCHAR(100) 
); 

其中类型可以是'代理'或'铅'(例如)。或者,您可以使用一种字符类型代码。然后,您可以使用对象模型开始填充空白:

  • 您有一个用户父类;
  • 你有两个孩子班:领导和代理;
  • 那些孩子有固定类型。

它应该很容易就位。

至于如何在一个语句中加载,我会使用某种工厂。假设这些准系统类:

class User { 
    private $name; 
    private $type; 
    protected __construct($query) { 
    $this->type = $query['type']; 
    $this->name = $query['name']; 
    } 
    ... 
} 

class Agent { 
    private $agency; 
    public __construct($query) { 
    parent::constructor($query); 
    $this->agency = $query['agency']; 
    } 
    ... 
} 

class Lead { 
    public __consruct($query) { 
    parent::constructor($query); 
    } 
    ... 
} 

工厂看起来是这样的:

public function loadUserById($id) { 
    $id = mysql_real_escape_string($id); // just in case 
    $sql = "SELECT * FROM user WHERE id = $id"; 
    $query = mysql_query($sql); 
    if (!query) { 
    die("Error executing $sql - " . mysql_error()); 
    } 
    if ($query['type'] == 'AGENT') { 
    return new Agent($query); 
    } else if ($query['type'] == 'LEAD') { 
    return new Lead($query); 
    } else { 
    die("Unknown user type '$query[type]'"); 
    } 
} 

或者,你可以有工厂方法上,比如说一个静态方法,用户类和/或使用查找类为类的查找表。

也许用这种查询结果资源污染类是最严格的OO意义上的可疑设计,但它很简单并且可行。

+0

我真的很喜欢这个想法。但是最让我厌烦的是执行SQL来加载所有数据的地方......我不能把它放在User类中,因为根据类型,我需要不同的SQL。我不想把它全部放在Agent和Lead类中,因为大部分代码都是相同的,我想避免复制和粘贴...理想情况下,我希望User类能够加载共同的信息和Agent/Lead类来加载独特的信息......但是,我每次执行2个SQL语句,每次我实例化一个Agent或Lead,这是不希望的..... – SpaDusA 2009-07-27 15:44:39

+0

你可以做到这一点在1个SQL语句中。告诉我,你用什么来加载一个特定的用户?你通过什么?一个ID?还有别的吗? – cletus 2009-07-27 15:52:45

0

你会有一个不是领导或代理的用户吗?该类真的需要从数据库中提取数据吗?

如果是这样,为什么不把SQL查询拉入可以在创建子类时重写的函数中。

0

难道你不能继承说一个SQL的骨架,然后使用每个子类中的函数来完成基于它的需求的查询?

使用非常基本的例子:

<?php 
//our query which could be defined in superclass 
$query = "SELECT :field FROM :table WHERE :condition"; 

//in our subclass 
$field = "user, password, email"; 
$table = "agent"; 
$condition = "name = 'jim'"; 

$dbh->prepare($query); 
$sth->bindParam(':field', $field); 
$sth->bindParam....;//etc 

$sth->execute(); 
?> 

正如你可以看到我的例子并不惊人,但应该让你明白我在获得。如果你的查询在子类之间非常相似,那么我认为我的建议可以起作用。

显然它需要一些调整,但它可能是我会采取的方法。