简体   繁体   English

PHP继承和MySQL

[英]PHP Inheritance and MySQL

So I'm trying to adopt good object oriented programming techniques with PHP. 所以我试图采用PHP的良好的面向对象编程技术。 Most (read all) of my projects involve a MySQL database. 大多数(全部读完)我的项目涉及MySQL数据库。 My immediate problem deals with the users model I need to develop. 我的直接问题涉及我需要开发的用户模型。

My current project has Agents and Leads. 我目前的项目有代理商和潜在客户。 Both Agents and Leads are Users with much of the same information. 代理商和潜在客户都是具有大量相同信息的用户。 So, obviously, I want a class Agents and a class Leads to extend a common class Users. 所以,显然,我想要一个类Agents和一个类Leads来扩展一个公共类Users。 Now, my question is as follows: 现在,我的问题如下:

How should the SQL best be handled for loading these objects? 如何最好地处理SQL来加载这些对象? I don't want to execute multiple SQL statements when I instantiate an Agent or a Lead. 我实例化代理或潜在客户时,我不想执行多个SQL语句。 However, logic tells me that when the Users constructor is fired, it should execute a SQL statement to load the common information between Agents and Leads (username, password, email, contact information, etc). 但是,逻辑告诉我,当用户构造函数被触发时,它应该执行一个SQL语句来加载代理和潜在客户之间的公共信息(用户名,密码,电子邮件,联系信息等)。 Logic also tells me that when the Agents or Leads constructor is fired, I want to execute SQL to load the data unique to the Agents or Leads class....But, again, logic also tells me that it's a bad idea to execute 2 SQL statements every time I need an Agent or Lead (as there may be thousands of each). Logic还告诉我,当激活Agents或Leads构造函数时,我想执行SQL来加载Agents或Leads类的唯一数据....但是,逻辑也告诉我执行2是个坏主意每次我需要代理或潜在客户时的SQL语句(因为每个可能有数千个)。

I've tried searching for examples of how this is generally handled with no success...Perhaps I'm just searching for the wrong thing? 我已经尝试过搜索一般如何处理但没有成功的例子......也许我只是在寻找错误的东西?

You basically have three approaches to this problem (one of which I'll eliminate immediately): 你基本上有三种解决这个问题的方法(其中一种我会立即消除):

  1. One table per class (this is the one I'll eliminate); 每班一张桌子(这是我要消除的一张桌子);
  2. A record type with optional columns; 包含可选列的记录类型; and
  3. A record type with a child table depending on type that you join to. 具有子表的记录类型,具体取决于您加入的类型。

For simplicity I generally recommend (2). 为简单起见,我一般建议(2)。 So once you have your table: 所以,一旦你有了你的桌子:

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

where type can be 'AGENT' or 'LEAD' (for example). 其中type可以是'AGENT'或'LEAD'(例如)。 Alternatively you can use one character type codes. 或者,您可以使用一个字符类型代码。 You can then start to fill in the blanks with the object model: 然后,您可以开始使用对象模型填充空白:

  • You have a User parent class; 你有一个用户父类;
  • You have two child classes: Lead and Agent; 你有两个子课:领导和代理;
  • Those children have a fixed type. 那些孩子有固定的类型。

and it should fall into place quite easily. 它应该很容易到位。

As for how to load in one statement, I would use some kind of factory. 至于如何加载一个语句,我会使用某种工厂。 Assuming these barebones classes: 假设这些准系统类:

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);
  }
  ...
}

a factory could look like this: 工厂看起来像这样:

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]'");
  }
}

Alternatively, you could have the factory method be a static method on, say, the User class and/or use a lookup table for the types to classes. 或者,您可以将工厂方法设置为User类的静态方法和/或使用查找表来获取类的类。

Perhaps polluting the classes with the query result resource like that is a questionable design in the strictest OO sense, but it's simple and it works. 也许使用查询结果资源来污染类是最严格的OO意义上的可疑设计,但它很简单并且有效。

Will you ever have a user that's not a Lead or Agent? 您是否会有一个不是潜在客户或代理商的用户? Does that class really need to pull data from the database at all? 那个类真的需要从数据库中提取数据吗?

If it does, why not pull the SQL query into a function you can override when you create the child class. 如果是这样,为什么不将SQL查询拉入您在创建子类时可以覆盖的函数。

Could you not inherit say a skeleton of the SQL, then use a function in each sub-class to complete the query based on its needs? 难道你不能继承说SQL的骨架,然后在每个子类中使用一个函数来根据需要完成查询吗?

Using a really basic example: 使用一个非常基本的例子:

<?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();
?>

As you can see my example isn't amazing, but should allow you to see what I am getting at. 你可以看到我的例子并不令人惊讶,但应该让你看看我得到了什么。 If your query is very similar between subclasses then I think my suggestion could work. 如果您的查询在子类之间非常相似,那么我认为我的建议可行。

Obviously it will need some tweaking but it is probably the approach I would take. 显然它需要一些调整,但它可能是我会采取的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM