这种PHP对象设计方法好还是不好?-寻求批判

3

我在以面向对象的方式使用PHP方面相对较新。在我的最新项目中,我将创建一个网站,从SQL数据库中加载大量条目,然后将这些条目发送到视图进行输出。

在研究如何以最佳方式完成此操作时,我已编写了以下代码:

class entryHandler {

//Store database connection
protected $database;

//List of all entries as multidimensional array fetched from SQL.
private $entriesSQL = array();

//List of all entries (as objects) will be stored in our $entries array
private $entriesObjects = array();


/*
 * 
 * Upon construct
 * 
 */
public function __construct($database) {

    //Check if database class has been passed correctly.
    //Else we exit, since we can not function without it!
    if (isset($database)) {

        $this -> database = $database;

        //Get events
        if ($entriesSQL = $this -> getEventsFromSQL()) {
            // Set SQL entries
            $this -> setEntriesSQL($entriesSQL);

            //And turn them into an array of objects
            $this -> setEntryObjects();
        }
        else {

        }
    }
    else {
        echo 'No database connection has been established. Exiting execution.';
        exit();
    }
}


/*
 * Setter for entriesSQL
 */
private function setEntriesSQL($entriesSQL) {
    $this -> entriesSQL = $entriesSQL;
}


/*
 * Getter for entriesSQL
 */
public function getEntriesSQL() {
    return $this -> entriesSQL;
}


/*
 * Setter for entry objects
 * 
 */
private function setEntryObjects() {
    foreach ($this -> getEntriesSQL() as $key => $val) {
        //entryID, entryUserID, entryTitle, entryTimeStart, entryTimeEnd
        array_push($this -> entriesObjects, new entry($val['entryID'], $val['entryUserID'], $val['entryTitle'], $val['entryTimeStart'], $val['entryTimeEnd']));
    }
}


/*
 * 
 * Getter for entry objects
 * 
 */
public function getEntryObjects() {
    return $this -> entriesObjects;
}

/*
 * 
 * This function grabs events from SQL and return multidimensional-array of content.
 * 
 */
private function getEventsFromSQL() {
    //Define the SQL query
    $SQL = '...snippet...';

    if ($entriesSQL = $this -> database -> read($SQL)) {
        //Entries collected, return them.
        return $entriesSQL;
    }
    else {
        //Error occured. Log it and return false.
        return false;
    }
}

}


class entry {

var $entryID;
var $entryUserID;
var $entryTitle;
var $entryTimeStart;
var $entryTimeEnd;

public function __construct($entryID, $entryUserID, $entryTitle, $entryTimeStart, $entryTimeEnd) {
    $this -> setEntryID($entryID);
    $this -> setEntryUserID($entryUserID);
    $this -> setEntryTitle($entryTitle);
    $this -> setEntryTimeStart($entryTimeStart);
    $this -> setEntryTimeEnd($entryTimeEnd);
}

/*
 * Setter for entryID
 */
private function setEntryID($entryID) {
    $this -> entryID = $entryID;
}

/*
 * Getter for entryID
 */
public function getEntryID() {
    return $this -> entryID;
}



/*
 * Setter for entryUserID
 */
private function setEntryUserID($entryUserID) {
    $this -> entryUserID = $entryUserID;
}

/*
 * Getter for entryUserID
 */
public function getEntryUserID() {
    return $this -> entryUserID;
}



/*
 * Setter for entryTitle
 */
private function setEntryTitle($entryTitle) {
    $this -> entryTitle = $entryTitle;
}

/*
 * Getter for entryTitle
 */
public function getEntryTitle() {
    return $this -> entryTitle;
}



/*
 * Setter for entryTimeStart
 */
private function setEntryTimeStart($entryTimeStart) {
    $this -> entryTimeStart = $entryTimeStart;
}

/*
 * Getter for entryTimeStart
 */
public function getEntryTimeStart() {
    return $this -> entryTimeStart;
}


/*
 * Setter for entryTimeEnd
 */
private function setEntryTimeEnd($entryTimeEnd) {
    $this -> entryTimeEnd = $entryTimeEnd;
}

/*
 * Getter for entryTimeEnd
 */
public function getEntryTimeEnd() {
    return $this -> entryTimeEnd;
}
}

现在,类“entryHandler”是从我的控制器(另一个PHP文件)加载的,如下所示:
    //Instantiate calenderHandler and pass our database handler to it.
    $entryHandler = new entryHandler($database);

    //Load template
    $template -> calendarEntries = $this -> renderEntries($entryHandler -> getEntryObjects());



/*
 * 
 * This functions renders entries content for view.
 * Returns string with content.
 * 
 */
private function renderEntries($entries) {

    $entriesContent = '';

    foreach ($entries as $entry) {

        $entriesContent .= '{
                                title: "' . $entry -> getEntryTitle() . '",
                                start: "' . $entry -> getEntryTimeStart() . '",
                                end:   "' . $entry -> getEntryTimeEnd() . '"
                            }, ';
    }

    //Right trim entries string, so that we do not add trailing comma to last entry in list.
    $entriesContent = rtrim($entriesContent, ', ');

    //And return content to parse it to view.
    return $entriesContent;
}
 }

这是一个不好的设计模式吗?有没有其他方法可以做到?在这段代码中是否存在某种冗余?-需要注意的事情?

感谢大家抽出时间。

问候, fischer


3
这应该在代码审查上进行。(http://codereview.stackexchange.com/) - Sherlock
1
关于构造函数的一个提示:请将您的构造函数从任何逻辑中清除。它们只应该设置值,每个逻辑都应该提取到私有方法中以保持其干净和可扩展性。如果您需要在使用对象之前准备一些值,请以“懒惰的方式”进行 - 通过调用私有方法在需要它的方法中准备它。 - palmic
1
不要忘记在函数注释中添加标签,例如 @param string $arg @return int|bool - Yang
1
对于你的待办事项清单 - 学习自动加载方法(如PSR-0),因为这些会影响你的类/文件夹名称。其次,引用操作符(->)两侧加空格也不是错误的,但我个人认为看起来很奇怪。最后,在你有一个private方法或属性时,决定是否真的想让它对子类不可访问 - 这些可以是protected,从而通过继承可用。 - halfer
1
你在面向对象编程方面似乎已经有了很好的开端。除了答案和评论中提到的其他事情之外,我建议你看一下并遵循PSR-2编码风格,如果你选择使用自动加载,或者发现需要与他人合作时,这可能会对你有所帮助。 - Aran
谢谢大家。我会记得像metal_fan指出的那样在函数注释中添加标签。我也会看一下PSR-2编码风格!:) 谢谢Aran! - fischer
2个回答

3
似乎你现在所做的是将数据进行处理。这样做并不一定是错的,但你也可以选择其他方式。例如:不要将所有SQL条目存储在一个数组里,而是:
  • 从数据库中获取数据。
  • 创建一个持有这些数据的对象。 ( 对象关系映射 )
因此,你将会抛出包含数据的对象,而不是实际数据本身。
这是个好主意,因为这样就容易改变数据行为,或者添加提取数据的方法,无论你需要哪种方式。
另外,你所做的并不一定被分类为面向对象编程,你只是将很多函数放在了一个类里。
创建做你所需的类,并尽可能保持类的小巧。每当你执行的操作超出了该类的范围时,就创建一个新类来处理你需要的东西。 面向对象编程示例 了解如何进行面向对象编程的一个好方法是看看别人是如何做的。我推荐你查看其他的项目,看看他们是如何做的。 Symfony2 - 一个复杂的PHP框架,使用了面向对象编程。
Slim
CodeIgniter
LavarelPHP

Symfony2 是一个相当复杂的框架,不太适合初学者学习。对于面向对象编程和 PHP 框架的初学者来说,更好的选择可能是 SlimCodeigniterLaravelPHP 这些框架。这些框架在我看来要简单得多,是 PHP 面向对象编程和 PHP 框架的良好起点。 - Aran
我会将它们添加到示例中,谢谢。 - Kao
谢谢!你提到我只是随意传递数据的观点,正是我所担心的事情!同时,很高兴你指出了一些可以开始使用的框架。由于你和Arans的评论,我刚刚开始尝试Lavarel。看起来很不错,我会试一试 :) - fischer

0

我基本上同意Kao的答案。无论如何,如果你真的想自己做而不是使用任何DBAL,我建议你阅读一些ORM文档

在你的代码中,允许构造函数同时处理很多事情是一个坏主意。保持干净和分离它们。使用依赖注入而不是在类/方法内部创建对象。


这应该作为评论发布,因为您正在“同意”另一个答案并引入诸如依赖注入之类的术语,而这些术语对于OP来说并不清楚。 - N.B.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接