【问题标题】:One method retrieves all the data or few smaller methods retrieve each part?一种方法检索所有数据还是几个较小的方法检索每个部分?
【发布时间】:2013-01-05 22:17:28
【问题描述】:

我对我正在创建的 OOP PHP 代码有几个疑问。它(到目前为止)用于检索在线存储的不同语言的标题和多个章节。但首先我将展示代码,因为我的怀疑涉及到这一点。这是我目前正在使用的课程:

<?php
// Requires PHP 5.4+
class Subject
  {
  private $DB;
  private $Language;
  private $Keyword;

  public function __construct($DB, $Keyword, $Language)
    {
    $this->DB=$DB;
    $this->Keyword=$Keyword;
    $this->Language=$Language;
    }

  private function query($query, $arg)
    {
    $STH = $this->DB->prepare($query);
    $STH->execute(array_merge((array)$this->Keyword, (array)$arg));
    return $STH->fetch()[$this->Language];  // PHP 5.4+
    }

  public function retrieveTitle ()
    {
    return $this->query("SELECT * FROM subject WHERE keyword = ? ORDER BY date DESC LIMIT 1");
    }

  public function retrieveChapter ($arg)
    {
    return $this->query("SELECT * FROM chapters WHERE subject_keyword = ? AND type = ? ORDER BY date DESC LIMIT 1", $arg);
    }
?>

然后我做类似的事情来显示页面:

if (isset($_GET['a']))
  {
  $Subject=new Subject($DB, $_GET['a'], $User->get('language'));

  if ($Subject->retrieveTitle())
    {
    echo '<h1 id="Title">'.$Subject->retrieveTitle().'</h1>';

    // Index
    if ($Subject->retrieveTitle())
      // ... code for the index

    // Introduction
    if ($Subject->retrieveChapter('Introduction'))
      echo '<h2 id="Introduction">' . $_('Introduction') . '</h2>' . $Subject->retrieveChapter('Introduction');

    // ... more non-relevant code.
    }
  }
else
  // ... whatever

第一个问题。我不确定这是否是处理此类数据的正确方法。我试图将这些方法分开并使它们尽可能小,同时也尽量不重复太多代码。这是感觉正确的方式。但我不明白为什么这个与前一个类似的其他代码不太受欢迎。注意:这个类肯定有一些错别字并且没有经过测试,这里只是为了说明区别,所以请不要使用它(至少不是字面意思):

<?php
// Requires PHP 5.4+
class Subject
  {
  public $Title;
  public $Chapters = array ();

  public function __construct($DB, $Keyword, $Language)
    {
    // Retrieve all
    $STH = $DB->prepare("SELECT * FROM subject WHERE keyword = ? ORDER BY date DESC LIMIT 1");
    $STH->execute(array($Keyword));
    $this->Title = $STH->fetch()[$Language];  // PHP 5.4+

    // Retrieve chapters
    $ToForeach = ('Introduction','History','1');
    $STH = $DB->prepare("SELECT * FROM chapters WHERE subject_keyword = ? AND type = ? ORDER BY date DESC LIMIT 1");
    foreach ($ToForeach as $part)
      {
      $STH->execute(array($Keyword, $part));
      $this->Chapters = $STH->fetch()[$Language];
      }
    }
  }
?>

然后直接访问属性(或者甚至在中间构建一些 get(),但你明白了)。

那么,有什么不同吗?第一种方法与第二种方法编写类的优缺点是什么?第一个中的内存使用量应该稍微小一些,但我认为与这种情况下的可读性相比,这不会是一个交易破坏者。

编辑:只是以一种让其他人理解的方式写下问题,就让我以其他方式思考它。第一种方法看起来也更容易测试。

第二个顾虑。如果我想做一个/一些方法来保存数据,我应该把它放在同一个类还是不同的类?因为如果我把它放在一个中,它会将所有与主题相关的方法捆绑在一个非常独立的类中,如果我将它分开,我就会有更多具有分离角色的专业类。

也欢迎任何进一步的建议,特别是关于编码最佳实践 [我可能没有遵循] 的建议!

【问题讨论】:

    标签: php class methods pdo


    【解决方案1】:

    这并不容易以好的方式回答。所以我只能关注其中的一些小部分。为了不重复代码,我想说你给出的第一个例子有很多重复的代码:

    class Subject
    {
        /**
         * @var ParametrizedQueryFetchQueryFactory
         */
        private $queryFactory;
    
        public function __construct($DB, $Keyword, $Language) {
    
            $this->queryFactory = new ParametrizedQueryFetchQueryFactory($DB, $Language, [$Keyword]);
        }
    
        private function query($query, array $args = array()) {
            return $this->queryFactory->query($query, $args);
        }
    
        public function retrieveTitle() {
    
            return $this->query("SELECT * FROM subject WHERE keyword = ? ORDER BY DATE DESC LIMIT 1");
        }
    
        public function retrieveChapter($part) {
            return $this->query(
                "SELECT * FROM chapters WHERE subject_keyword = ? AND TYPE = ? ORDER BY DATE DESC LIMIT 1",
                [$part]
            );
        }
    }
    
    class ParametrizedQueryFetchQueryFactory
    {
        private $db, $returnIndex, $defaultArgs;
    
        public function __construct($db, $returnIndex, array $defaultArgs = array()) {
            $this->db = $db;
            $this->returnIndex = $returnIndex;
            $this->defaultArgs = $defaultArgs;
        }
    
        public function query($query, array $args = array()) {
            $fetcher = new ParametrizedQueryFetch($this->db,$query, $this->returnIndex, $this->defaultArgs);
            return $fetcher->execute($args);
        }
    }
    
    class ParametrizedQueryFetch
    {
        private $db, $query, $returnIndex, $defaultArgs;
        public function __construct($db, $query, $returnIndex, array $defaultArgs = array()) {
            $this->db = $db;
            $this->query = $query;
            $this->returnIndex = $returnIndex;
            $this->defaultArgs = $defaultArgs;
        }
    
        public function execute(array $args) {
            $args = array_merge($this->defaultArgs, $args);
            $stmt = $this->db->prepare($this->query);
            $stmt->excute($args);
            return $stmt->fetch()[$this->returnIndex];
        }
    }
    

    顺便说一句,为了使这个 PHP 5.3 兼容,您只需在此处更改一行。

    【讨论】:

    • 我编辑了我的原始代码以避免重复代码。然而,我真的很惊讶你的代码有多长,实际上花了一段时间来理解它是如何工作的。现在我知道了,但我不知道为什么。我真的很好奇你的代码有什么好处来证明它更长,那么它们是什么?顺便说一句,感谢您详细的回答!
    • 当您在 shell 类中执行 1000 条此类参数化 SQL 查询时,这些查询为您的代码提供与数据库中数据的接口,添加一些为此工作的东西是有意义的案例,例如就像从类中运行这些参数化的、部分预配置的查询一样。就这样。当然对于两个函数来说太冗长了,你也可以从公共函数中将代码放入private function query()。这是第一步。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-19
    • 1970-01-01
    • 2019-10-11
    • 1970-01-01
    • 2019-06-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多