在函数PHP中实例化类是不好的做法

时间:2013-11-24 12:29:08

标签: php function class

我正在重新分解大量代码以使其更易于测试,并且我有许多依赖于实例化数据库对象的有用函数。

这样的事情:

function id_from_name($table, $name)
{
    $db = get_database();
    //code that returns an id
}

function username_from_user_id($id)
{
    $db = get_database();
    //code that returns a username
}

有一些更像id_exists,id_active等。

现在我认为这不是正确的事情,因为对象应该作为参数传递?但这意味着每次我想使用一个新对象时,都会创建并发送新对象。

所以,我的问题是:我是否应该将这些函数移动到可以访问数据库对象的自己的类/库中?我上面展示的例子通常是一种糟糕的做事方式吗?

4 个答案:

答案 0 :(得分:4)

更好的方法是制作课程。您将把数据库对象传递给构造函数并使其成为实例变量。这样每个函数都可以访问数据库对象。

现在认为实例化例如不好的原因是每个函数中的数据库对象,是因为如果您决定有一天更改数据源,则可能需要一个巨大的重构器。如果将数据库对象传递给构造函数,则可以在没有任何重构的情况下将正确的对象传递/注入类中。

...关于DI的更多信息......

通过将对象传递给构造函数,您还可以创建更清晰的API =>你知道哪个对象依赖于另一个对象,你确切知道哪个类使用你的DB对象。如果你开始实例化它或者像你一样在函数内部以静态方式访问它,我将不得不浏览所有类来查看数据库对象的使用位置。还有一点,依赖注入力SRP(单一责任原则)=>如果你开始注入太多的对象(构造函数得到很多参数),你应该怀疑你的类做得太多了,并开始重构。

答案 1 :(得分:0)

您可以创建一个类Table_Adapter并在其构造函数中实例化数据库对象:

class Table_Adapter 
{
    protected $db;

    public function __construct() 
    {
        $db = get_database();
    }
}

然后创建子类Items_Table_Adapter' that extends Table_Adapter and put their all methods related to Items`表。

class Items_Table_Adapter extends Table_Adapter
{
    public function item_by_id($id)
    {

    }
}

然后你就像使用它一样:

$tableAdapter = new Items_Table_Adapter();
$item = $tableAdapter->item_by_id(1);

答案 2 :(得分:0)

尝试类似:

class YourClass{

    public static function get_database(){
        // your creation
        return $db;
    }

    public function id_from_name($table, $name)
    {
        /* your code */
        //code that returns an id
    }

    public function username_from_user_id($id)
    {
        /* your code */
    }

}

所以你可以这样使用它:

$db = YourClass::get_database();
$result = $db->id_from_name($table, $name);

答案 3 :(得分:0)

当然建议您可以选择换出数据库连接。

现在,如果您的函数get_database()如下所示:

function get_database() {
  static $db;
  if (!$db)
    $db = new \mysqli(...);
  return $db;
}

然后你真的,真的应该把它改成一个类的包装器,看起来像这样:

function get_database_manager() {
  static $dbmgr;
  if (!$dbmgr)
    $dbmgr = new DbManager;
  return $dbmgr;
}

function get_database() {
  return get_database_manager()->getCurrentConnection();
}

其中DbManager的实例属性包含getCurrentConnection()返回的当前连接。如果要换出连接,请执行get_database_manager()->setConnection($newConn)之类的操作。问题解决了:))

我将在这里留下静态编程的缺点(在这个帖子中有很多例子):http://kunststube.net/static/ 以及摆脱它的常用方法(我们在这里有另一种方法):http://en.wikipedia.org/wiki/Dependency_injection