PHP构造对象数组

时间:2014-03-17 11:28:27

标签: php oop

作为尝试和学习面向对象的PHP脚本的一种方法,我目前正在尝试重写我之前在过程PHP中编写的数据库Web应用程序。该应用程序用于存储汽车零件和汽车零件的信息。

在我的应用程序中有汽车零件。它们由不同的参考编号标识,由不同的组织(零件的制造商,再制造商,车辆制造商等)分配,并且任何特定的汽车零件可以具有由这些组织指定的零个,一个或多个参考编号(而且,令人困惑的是,每个参考编号可能指的是我正在处理的数据库中定义的多个独特的汽车零件。

据我所知,我正在处理三类不同的实体。有汽车零件,参考编号和参考分配器的编号(在我的内部命名法中,我称之为'推荐人')。当我开始学习OOP时,我开始为每个人创建一些非常基本的类:     

class Part {
    public $part_id;
    public $part_type;
    public $weight;
    public $notes;

    public $references;

            private $db;

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

}

class Reference {
    public $reference_id;
    public $reference;
    public $referrer;
            private $db;

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

class Referrer {
    public $referrer_id;
    public $referrer_name;
            private $db;

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

我一直在努力的是如何填充这些并随后将它们粘合在一起。我的Web应用程序的最基本功能是查看汽车零件,包括其指标和指定的参考编号。

页面请求中包含part_id。最初,我在我的Part类中编写了一个构造函数方法,该方法将在数据库中查找该部分,然后在另一个方法中查找分配给该部件ID的引用号(与referrer表一起使用)。它将迭代结果并为每个引用创建一个新对象,并将整个集合保存在由reference_id数据索引的数组中。

在进一步阅读之后,我开始明白我应该使用工厂类来实现这一点,因为我的Part课程与我的Reference课程之间的这种联系不是责任这些离散类中的任何一个。这在概念上是有道理的,因此我设计了一个我称之为PartReferenceFactory的课程,我理解应该负责组装任何类型的部分参考编号的整理:     

class PartReferenceFactory {

    public static function getReferences(Database $db, $part_id) {


    $db_result = $db->query(
        'SELECT *
        FROM `' . REFERRER_TABLE . '`
            LEFT JOIN `' . REFERENCE_TABLE . '` USING (`referrer_id`)
            INNER JOIN `' . REFERENCE_REL . '` USING (`reference_id`)
        WHERE `part_id` = :part_id
        ORDER BY `order` ASC, `referrer_name` ASC, `reference` ASC',
        array(':part_id' => $part_id);
    );

    if(empty($db_result)) {
        return FALSE;
    } else {
        $references = array();

        foreach($db_result as $reference_id => $reference_properties) {

            $references[$reference_id] = new Reference($db);
            $references[$reference_id]->reference = $reference_properties['reference'];
            $references[$reference_id]->referrer = new Referrer($db);
            $references[$reference_id]->referrer->referrer_id = $reference_properties['referrer_id'];
            $references[$reference_id]->referrer->referrer_name = $reference_properties['referrer_id'];
        }
        return $references;
    }
}

}

    ?>

然后在我的Part类中调用我的工厂类的getReferences方法,我对此进行了修改:         class Part {         public $ part_id;         public $ part_type;         公共重量;         公开$ notes;

    public $references;

    private $db;

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

    function getReferences() {
        $this->references = PartReferenceFactory::getReferences($this->db, $this->part_id);
    }

}

我真的在寻找关于我的一般方法是否是好方法的建议,或者如果我怀疑,我误解了某些东西,忽略了其他事情,并将自己捆绑在一起。我将尝试将其提炼成一些潜在的,直接回答的问题:

  1. 我对班级和工厂班级目的的理解是否有误?

  2. 我存储对象数组是个坏主意吗?我认为,从设计而非性能的角度来看,只要它们没有交织在一起。

  3. 这是构建PHP中类之间的关系/相互依赖关系的合适方法吗?

  4. 在(实例化的)PartReferenceFactory类的getReferences方法中调用Part是否正确?并且将返回的参考对象存储在适当的零件对象中?

  5. 作为应用程序GUI的一部分,我需要提供引用列表,要求我独立于任何部分对象创建另一个ALL引用数组。然而,其中一些引用将存在于部件对象内的$references数组中。我想到,为了避免重复的referrer对象,我可以在每个页面请求的开头选择所有引用的列表,将它们表示为引用的全局数组,并简单地从我的{{1}中引用这些引用。根据需要和Part个类。但是,我已经读过依赖类中的全局范围是不好的。是否有优雅/最佳实践解决方案?

  6. 非常感谢你读这篇文章的时间,我为这个极长的问题道歉。我经常担心我会错误地解释问题,因此希望尽可能精确。如果我的帖子的任何部分被删除,请告知我们。

1 个答案:

答案 0 :(得分:1)

嗯,我认为乔恩是对的,这个问题已经真正致力于让我的头脑清醒,我仍然不确定我知道你所问的一切,但我会给它一个去。

1)您对班级/工厂类的理解是否合适? 是的,没有。是的,你确实理解它,但是你采用了一种非常类似课堂的方法解决问题,而不是经验带来的那种实用主义。 OOP是一种对真实事物进行建模的方法,但它仍然是一种基本的编程工具,所以不要过度复杂化你的结构,只是为了保持它的真实性。主要认为OOP为您提供结构化编程是继承,这意味着您可以编写与其他事物类似的东西,因此只需编码实际上不同的东西就可以更好地重用代码。如果有两件事可以共享代码,那么将它们作为共享父代并将代码放在那里。设想层次结构如何有效工作是设计OOP应用程序的80%的任务,并且您必须在第一次出错并且必须进行重组。 例如。我编写了许多代表数据库中实体的类:即用户,副本,收藏品。每个都具有根本不同的属性和关系集,但也有一组相似的核心事物:他们被询问的方式,数据的呈现方式,他们有属性,领域和关系的事实。所以我编写了一个父类,其中所有内容都继承,并且它包含大部分代码,然后特定的子类只定义了每个类不同的东西,而辛苦的工作是决定在Indexed中可以使用多少来避免重复代码儿童班。最初我在孩子们中有很多代码,但随着它的发展,我将越来越多的代码移到了父类中,并将这些代码稀疏了。就像我说的那样,不要以为你会在第一时间做对。

2)将对象存储在数组中是一个坏主意吗?好吧不,但你为什么要这样?在您的示例中,您在数据库中有一个引用数组,其中关系是多对多关系(即您有3个表,中间有一个连接表)。然后,当您获得数据时,您将创建每个对象并将其存储在数组中。当然你可以做到这一点,但请记住每个对象都有开销。将所有内容加载到内存中很好,但除非您需要,否则不要这样做。还要确保你需要很多< =>很多关系。我可能错误地阅读了您的解释,但我认为您只需要一个多个关系,这可以通过存储对一个'一个'在每个'许多'的记录中(因此失去了中间表并简化了连接)。

5)此时我会跳到最后一个,因为它会进入#2。您需要从不同角度考虑您的应用程序(a)当您有数据并尝试呈现它(读取)时(b)当您有一些数据并且正在尝试添加新数据时,需要链接到现有数据(添加关系)和(c)当你没有数据,并且正在添加新的记录。用户如何获得每个视角以及会发生什么。通常很容易让(a)和(c)工作,但制作(b)直观通常是困难的部分,如果你过于复杂,那么用户根本就不会得到它。在#2中构建内部数据结构时,只需按照用户所处的视角执行所需操作。除非您正在编写应用程序,否则您不需要加载所有内容,只需要加载所有内容。手头的任务。

3)不确定你的意思是'这是否合适'。 OOP允许您将自己束缚在一起,或创造出精彩的艺术作品。从理论上讲,你应该尽量保持简单。有很好的书籍可以举例说明为什么你可能想让事情变得更复杂,但大多数原因并不明显,所以你需要经验来决定你所做的事情是否是不必要的过度复杂化或实际上是否避免了陷阱。根据个人经验,如果你认为它过于复杂,可能就是这样。

4)不确定这是不是你的意思,但是我已经把这个问题问到你是否正确使用了Factory类。我对这个理论的理解是你应该最终得到的东西,除了初始创建一个FactoryClass对象之外没有静态处理的东西,静态存储在正在使用的子类中,然后你必须编写一个抽象方法在父类中,在每个子类中实现,它获取该对象,因此您可以使用方法调用来调用该FactoryClass的对象。我通常只在初始化非工厂类时直接调用FactoryClass的东西(即你需要在一个新对象中填充静态,因为这个类还没有初始化)。我没有看到任何直接调用它的问题,但是我避免这样做,因为工厂是恕我直言的课程的实施细节,所以不应该暴露在外面。

根据我的经验,你总是在学习新事物并发现OOP的陷阱,所以即使我认为我已经专业编写近20年,我也不会声称自己是这方面的专家所以我确信对我所说的内容会有完全反对意见。我认为你通过做你的直觉所说的是正确的学习最多,然后不要太顽固再重新开始,如果你改变了它的想法: - )