dongyu4863 2012-09-30 15:17
浏览 36
已采纳

在PHP中选择设计模式?

I develop web applications with PHP. I have many classes using a database connection.

This is the structure i generally use;

class SomeClass {
    private $db;

    function __construct(mysqli $db) {
        $this->db = $db;
    }

    function SomeFunction() {
        $this->db->query(...);
    }
}

And this is what i thought to use;

class Common {
    public static DB = new mysqli(...);
}

class SomeClass {
    function SomeFunction() {
        Common::DB->query(...);
    }
}

There are two parts of my question;

  1. Which one is better practice? If i use first one, i have to pass database object to every class uses db. If i use second one, every class uses db will be dependent to Common class.

  2. I made examples simpler. Actually i have a Database class extends mysqli and a DatabaseTableManager class using Database class. I add GetTable() function to Database class. I create DatabaseTableManager objects in this function (return new DatabaseTableManager($this, $tableNameFromArgument)) so i do not have to pass db object every time. In DatabaseTableManager class, i built some queries to make my job easier.

E.g. to insert a record to a table;

$DB = new Database(...);
$myTable = $DB->GetTable('myActualTableNameInDatabase');
$myTable->Insert( array('col1' => 'val1', 'col2' => 'val2') );

So i use this class a lot in my other classes. Naturally all these classes become dependent to DatabaseTableManager class. What is the better solution?

  • 写回答

3条回答 默认 最新

  • dsm17496 2012-09-30 15:41
    关注

    What is the better solution?

    What is the problem? :) So first of all from the standpoint of a general design it's said that we benefit from not introducing global static state. This disqualifies the singleton and using global variables.

    This reduces the burden to make a choice a lot. Passing the needed Mysqli connection object into the class that needs it via it's constructor is fine. If you're concerned about "passing it all the time", define a place where you create these objects.

    You've already done that in fact, for the "table manager" (maybe manager is not such a good term (it does not manage the tables in the database, it just represents them), but let's focus on the structure first). That class will give birth to objects that represent a table.

    For that part of your application that is consuming these, there is no need to even know about which kind of database lies behind, because you've encapsulated that detail.

    Naturally the table manager itself still needs to have that knowledge. However this is no problem, because you could change that in a central place if you would need to change that.

    So actually I must say, even you're keen to look for problems, what you create actually looks pretty well.

    Sure, as always you can run into problems, however if the way you make use of the database in your application is generally table based, this does not look that wrong to me. The pattern you've implemented might go into the direction of Active Record. It is known that this is suitable for small to medium sized applications that have Transaction Scripts.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
  • doumeng1897 2012-09-30 15:29
    关注
    1. It depends. Do you want to carry over the state of the row pointer? If so, go ahead and create the Common class. From a design perspective, your code that's depending on a database is forced to depend on some sort of abstraction, so go with whatever's most flexible to you. I would personally just have a DB object and pass it around. The single class may have advantages. If you could write a more fleshed-out example, we may be able to provide better answers.

    2. Why not put the methods inside your Database class instead of needlessly creating two classes and/or adding inheritance? Passing objects or variables to functions is normal behavior unless something's keeping track of state. Could you provide a more complete example of your Database and DatabaseTableManager classes?

    评论
  • douye7033 2012-09-30 15:40
    关注

    I would leave it the way you have it now:

    • Your Someclass is not dependent on any other class.
    • gets the DB injected at construction. This is optimal for testing.
    • it is a separation of concerns.
    • this construct is the most easy to convert to a real dependency injector, in combination with a Inversion of Control container.
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥20 关于TRPD(波形特征)局部放电特征提取
  • ¥15 C语言快速排序函数纠错
  • ¥15 C#的一个应用程序书写
  • ¥65 页面调接口时加载卡住不响应
  • ¥35 用C语言解决编程问题
  • ¥15 unity硬件连接与使用
  • ¥15 鱼缸加热棒的数据分析或者实际案例也行
  • ¥15 postgresql11安装完成后,pgadmin无法启动
  • ¥15 (标签-无人机|关键词-Matlab代码)
  • ¥15 执行shell脚本提示参数太多