php在不同类中使用相同的方法

时间:2018-01-22 12:22:25

标签: php class oop

我有各种类,其方法具有相同的代码。维护观点是一种非常糟糕的做法。

这是这个类的一个例子:

班级帐户控制器:

<?php

namespace controller\admin;

class accountController extends \controller\baseController
{
    private $table = 'account';

    public function itemslist()
    {
        list($res, $totalcount) = $this->getResultAndCount();

        return $this->twig->render('/admin/accounts.html.twig');
    }
    .
    ... other methods
    .
    private function getResultAndCount()
    {
        $sql = 'SELECT * FROM ' . $this->table;
        $count = $this->pdo->rowCount();
        $rows = $this->pdo->resultset();

        return array($rows, $count);
    }
}

类userController:

<?php

namespace controller\admin;

class userController extends \controller\baseController
{
    private $table = 'user';

    public function itemslist()
    {
        list($res, $totalcount) = $this->getResultAndCount();

        return $this->twig->render('/admin/users.html.twig');
    }
    .
    ... other methods
    .
    private function getResultAndCount()
    {
        $sql = 'SELECT * FROM ' . $this->table;
        $count = $this->pdo->rowCount();
        $rows = $this->pdo->resultset();

        return array($rows, $count);
    }
}

如图所示,具有相同代码的方法getResultAndCount是重复的。不是OOP的专家我一直在寻找在某处只有一个代码的方法,并在itemslistAction()方法中引用它。

我已经看到了这样做的方法,就像拥有这个方法的另一个类并在父类中调用它,接口,方法一样......但我很困惑,我想知道这将是实现它的最好方法以及如何。

3 个答案:

答案 0 :(得分:0)

你的两个课程都扩展了\controller\baseController课程。您可以将复制函数放在\controller\baseController类中,但如果您有其他扩展\controller\baseController的类,并且如果您将仅在您声明的类中使用此函数,则可以创建一个新类,扩展<?php namespace controller\admin; class bridgeClass extends \controller\baseController { //... protected function getResultAndCount() { $sql = 'SELECT * FROM ' . $this->table; $count = $this->pdo->rowCount(); $rows = $this->pdo->resultset(); return array($rows, $count); } } ?> 并在此类中实现重复功能。

bridgeClass

我们在上面声明的private中实现了该功能。另请注意,我们将函数的可见性从protected更改为bridgeClass,以便子类可以毫无问题地访问函数。然后,您可以使两个类扩展bridgeClass。因此,在这种情况下,现在您的两个班级都有\controller\baseController\n作为他们的父母。

答案 1 :(得分:0)

<?php

namespace controller\admin;

abstract class baseController
{
    private $table;

    public function itemslist()
    {
        list($res, $totalcount) = $this->getResultAndCount();
        return $this->twig->render('/admin/accounts.html.twig');
    }

    private function getResultAndCount()
    {
        $sql = 'SELECT * FROM ' . $this->table;
        $count = $this->pdo->rowCount();
        $rows = $this->pdo->resultset();

        return array($rows, $count);
    }
}

班级帐户控制器:

<?php
namespace controller\admin;

class accountController extends \controller\baseController
{
    private $table = 'account';

    // more method ....
}

类userController:

<?php
namespace controller\admin;

class userController extends \controller\baseController
{
    private $table = 'user';

    // more method ....
}

答案 2 :(得分:0)

只是划伤:

interface IValue{
    public function value();
}

class DBQuery implements IValue{
    private $pdo;
    private $sql;

    public function __construct(...){
        ....
    }

    public function value(){
        // execute $this->sql
    }    
}

class LazyTemplate{
    private $twig;
    private $template;
    private $data;

    public function __construct(..., IValue $data){
        ....
    }

    public function render(){
        return $this->twig->render(
            $this->template, 
            $this->data->value()
        );
    }
}

namespace controller\admin;

class accountController extends \controller\baseController
{
    private $items;

    public function __construct(...){
        $this->items = new LazyTemplate(
            $this->twig,
            '/admin/accounts.html.twig',
            new DBQuery($this->pdo, 'SELECT * FROM account')
        );
    }

    public function itemslist()
    {
        return $this->items->render();
    }
}

class userController extends \controller\baseController
{
    private $items;

    public function __construct(...){
        $this->items = new LazyTemplate(
            $this->twig,
            '/admin/users.html.twig',
            new DBQuery($this->pdo, 'SELECT * FROM user')
        );
    }

    public function itemslist()
    {
        return $this->items->render();
    }
}

P上。秒。我不知道Twig API,所以可能有更好的方法。

许多人建议使用继承来删除重复的代码。实际上,继承允许您快速而简单地执行此操作,但请考虑此方法的缺点:

  • 我们的课程越来越大,虽然领域模型不需要它。

  • 我们可能很容易需要一些列表,但我们只提供了一个继承。进一步炸毁基类?

  • 其他地方可能需要列表。将代码复制到那里并再次复制?

  • 我们只是使测试复杂化。有必要添加一个易于测试的非常小的方面,但现在我们拥有整个层次结构的这一部分。

这是出于我们的意图。重复代码我们真的想说什么? - 我会这样说:“有必要 以某种方式 来获取数据, *以某种方式* 将它们传输到模板”。 “ 以某种方式 ”,我想说,是抽象的界限,那些应该在不同实体中突出显示的地方。

以某种方式 将它们(数据)传输到模板” - 是某种实体,根据需要,获取数据,将其提供给模板并返回渲染的结果。我调用了这个实体LazyTemplate,因为它执行“惰性计算”(即使没有缓存,因为它通常会发生)。

LazyTemplate可以立即或通过闭包接收数据,但我选择了接口IValue。接口是“严格类型”,我们可以轻松地通过PHP本身提供参数检查(5.0+)。此外,我们在紧急情况发生之前不需要这些数据。如果我们的列表被隐藏,那么执行查询到DB是没有意义的。 IValue只是LazyTemplate与其环境之间的契约。

以某种方式 获取数据” - 这是另一个实体。理想情况下,此实体不应指定此数据的来源,但为简单起见,我决定立即描述类DBQuery。此外,我们已经有IValue,它执行相同的功能。

当然,我们必须引入几个额外的抽象(非常小的抽象,值得注意),但现在我们可以重用它们,扩展它们(例如,通过创建类CachedValue,{{1只测试一个特定的功能。

控制器仍然有类似的代码行,但不要盲目地尝试根除重复。用户列表和帐户列表是两个 不同的 列表,它们将来可能会变得完全不兼容。

P上。秒。我为任何错误道歉。