Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 面向对象设计问题_Php_Oop - Fatal编程技术网

Php 面向对象设计问题

Php 面向对象设计问题,php,oop,Php,Oop,我是在PHP中使用OOP的新手。它对我的代码的组织和维护有很大帮助,但我希望在设计类和尽可能高效地使用OOP方面做得更好。我读过四人帮设计模式的书,但仍然需要一些帮助。在构建了一些小应用程序之后,我一直在想一件事 假设我正在构建一个应用程序来跟踪学校的注册信息 我目前的做法是创建一个名为student的类,并在该类中为每个学生的记录上的CRUD创建方法。似乎合乎逻辑的是,我会为这个类提供一个构造函数方法,该方法将student\u id作为参数,这样我就可以从对象中引用它来执行所有这些不同的CR

我是在PHP中使用OOP的新手。它对我的代码的组织和维护有很大帮助,但我希望在设计类和尽可能高效地使用OOP方面做得更好。我读过四人帮设计模式的书,但仍然需要一些帮助。在构建了一些小应用程序之后,我一直在想一件事

假设我正在构建一个应用程序来跟踪学校的注册信息

我目前的做法是创建一个名为
student
的类,并在该类中为每个学生的记录上的CRUD创建方法。似乎合乎逻辑的是,我会为这个类提供一个构造函数方法,该方法将
student\u id
作为参数,这样我就可以从对象中引用它来执行所有这些不同的CRUD操作


但是,当我继续构建应用程序时,我遇到了需要运行返回多个学生的查询的情况。例如,
get_all_students\u from_grade($grade)
get_dropdown\u of_all_students()
,等等。这些方法并不只适用于一个学生,所以在我的
student
类中将它们作为方法似乎很奇怪,因为我在实例化对象时考虑了一个
student\u id
。显然,我可以这样做,但似乎我“做错了”。解决这个问题的最佳方法是什么?

您应该在Student上创建它们。

Student
类(这是一个域类)与它的操作(业务逻辑或数据访问,取决于具体情况)分开,如:

  • student
    -域对象仅包含数据
  • student\u service
    student\u dao
    (数据访问对象)-执行操作
这有时被认为破坏了封装,但这是公认的最佳实践


关于此事的更多信息。从OOP的角度来看,它提供了比破坏封装更多的缺点。因此,尽管这似乎是一种公认的做法,但并不完全是面向对象的。

将其分为两类:

  • 学生
  • 学生资源库
  • 你的学生班对它的关系存储方式一无所知

    $students = student_repository.get_all_students_from_grade($grade)
    

    你可以使用工厂方法,让工厂决定新生的ID应该是什么

    当然,这个工厂必须读取一个数据库来查看索引的起始位置(基于数据库中的学生数量),并且您必须决定如何处理被删除的学生(如果可能的话)

    至于你所描述的方法,我不明白你为什么要把它们包括在学生课堂上。您可以,但它应该是一个静态方法,而不是成员方法。

    我并不假装知道“最佳”方法,但它可能有助于以不同的方式处理问题。您可以让类表示应用程序和数据库之间的数据接口,而不是让一个类表示单个学生

    这个类将知道如何从数据库中检索一组(可能是一个)学生行,将它们缓存在本地数组中,允许应用程序浏览缓存的记录,允许对缓存的记录进行修改,完成后,将缓存的修改写回数据库(通过生成SQL来说明更改)


    这样,您可以避免为每次更改触发单个SQL语句(您仍然使用一组行),同时提供对单个对象的访问(通过维护缓存中当前位置的索引,并允许应用程序在调用类的方法时推进此“指针”)

    正如尼尔在评论中所说(不确定为什么我们没有给出答案),你可能还应该上
    课程
    学校
    课程。您可以在
    学校
    中使用特定于学校的方法(让给定年级的所有学生都参加,缺课天数给定等),在
    课程
    中使用特定于课程的方法(某一课程的所有学生都参加,等)


    您认为,在标准CRUD中,您不希望赋予代表个人的类(即
    学生
    类)加载自身倍数的责任,这是正确的另一方面,如果您想要更多的数据加载方式(这是RubyonRails所采用的),那么您实际上会在
    Student
    类本身上创建所有
    Student
    加载程序方法静态方法。它只取决于您想要如何设置样式,这在一定程度上取决于您的数据模型将变得多么复杂。

    始终有一个起点。在你的情况下,这将是你从学生那里得到的东西(即学校、班级等)


    我遇到了同样的问题,我猜你在使用MySQL?这是一个常见的OOP设计挑战,因为SQL有一种将所有内容扁平化的趋势

    我通过以下步骤解决了这个问题

    1.)创建一个具有三种实例化形式的类

    一个新的地方

    $myStudent = new $Student();
    
    另一种情况是,您知道id,但需要id数据

    $myStudent = new $Student($student_id);
    
    另一种情况是,它的数据已经存在于关联数组中

    $data = array('id'=13,'name' => 'studentname', 'major' => 'compsci');
    $myStudent = new $Student($data['id'], $data);
    
    这允许您创建一个factory类,该类可以从mysql运行查询,获取数据的关联数组,然后从该数组数据创建student实例,而无需访问student每个实例的数据库

    下面是此类的构造函数:

    public function __construct($id=FALSE, $data=FALSE)
    {
        if(!$id) $this->is_new = true;
        else if($id && !$data) $this->get_data_from_db($id);
        else if($id && $data) $this->set_data($data);
    
    }
    

    如果你有“学生”,你可能还想要“课程”和“学校”,这似乎是“获得学生”方法的好地方。这听起来是最简单的方法。您能否描述/提供描述“域”类/对象概念的链接?马修:马丁·福勒(Martin Fowler)的书(应用UML和模式)中对它进行了很好的描述,但是我没有发现任何东西
    public function __construct($id=FALSE, $data=FALSE)
    {
        if(!$id) $this->is_new = true;
        else if($id && !$data) $this->get_data_from_db($id);
        else if($id && $data) $this->set_data($data);
    
    }