这个 php 代码是不是按照 OO 原则正确编写?

Posted

技术标签:

【中文标题】这个 php 代码是不是按照 OO 原则正确编写?【英文标题】:Is this php code written correctly according to OO principles?这个 php 代码是否按照 OO 原则正确编写? 【发布时间】:2009-06-20 00:32:02 【问题描述】:

我一直在尝试了解面向对象,我认为我已经开始了解一些概念,但我不确定。如果我的思路是正确的,进行谷歌搜索来回答是相当困难的,所以我决定很快在这里问,请告诉我这个问题是否违反任何规则。

关于消息传递,我的想法是否正确?什么是明显的坏事?在继续学习的过程中,我应该如何思考? 喜欢getpagecontent($page, $connection);

Atm 我正在阅读 [Oreilly - 学习 phpmysql][1] 和 [面向对象环境中的编程][2] 还有一些关于UML的书

这里是代码。

dbfunctions.php

<?php
class dbconnect 

    function dbconnect() 
    $this->dbhost = 'xx';
    $this->dbuser = 'xx';
    $this->dbpass = 'xx';
    $this->dbdatabase = 'xx';
    

    function createdbconnection() 
        require_once('DB.php'); // pear

        $this->connection = DB::connect("mysql://$this->dbuser:$this->dbpass@$this->dbhost/$this->dbdatabase");

        if (DB::isError($this->connection)) 
        die("Could not connect (connection)<br>" . DB::errorMessage($this->connection));
        
    

    function closedbconnection()
        $this->connection->disconnect();
    


class dbinteractions 

   function dbinteractions($connection) 
            $this->connection = $connection;
        

   function searchdb($qstring) 
    if (get_magic_quotes_gpc()) 
        $qstring = stripslashes($qstring);
    

    $qstring = mysql_real_escape_string($qstring);

    $query = "SELECT content FROM site_content WHERE content LIKE '%$qstring%'";
    $result = $this->connection->query($query);

    if(DB::isError($result)) 
        die("Could not connect (query)<br>" . DB::errorMessage($result));
    

    while($result_row = $result->fetchRow()) 
        echo("<h2>Resultat:</h2>");
        foreach($result_row as $out)
            echo($out . "<p>");
    


    function getpagecontent($page) 
        $query = "SELECT * FROM site_content WHERE (page_id = \"" . $page . "\")";
        $result = $this->connection->query($query);;

        while($result_row = $result->fetchRow()) 
            echo "<h1>" . $result_row[0] . "</h1>"; //Echo page_id
            echo $result_row[1]; //Echo content
            echo "<h2>" . $result_row[2] . "</h2>"; //Echo timestamp
        
    


?>

搜索.php

<?php
function displaysearchform()

    echo("<p></p>");
    if($_GET["search"] == '')  //Display search box if no search ?>

        <form method="GET" action="<?php echo(htmlentities($_SERVER['PHP_SELF'])); ?>">
            <label>
                Search: <input type="text" name="search" />
            </label>
            <input type="submit" value="Go!">
        </form>

    <?php
        return false;
    
    else
    
        return true;
    


?>

index.php

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<link rel="stylesheet" href="style.css" type="text/css">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title></title>
</head>
<body>
    <div id="container">
        <div id="sidebar">
            <a href="?id=1">1</a><br>
            <a href="?id=2">2</a><br>
        </div>
        <div id="main">

            <?php
                include("dbfunctions.php");
                include("search.php");

                $dbconnect = new dbconnect();

                $dbconnect->createdbconnection();

                $dbinteractions = new dbinteractions($dbconnect->connection);

                if(!$_GET["id"] && $_GET["search"] == "")  //Check if direct site hit and no search query
                    $dbinteractions->getpagecontent("1");
                    

                else  
                    $page = $_GET["id"];
                    $dbinteractions->getpagecontent($page); //Get and display page content
                

                if (displaysearchform() == true) //If search was made don't display searchform
                    $dbinteractions->searchdb($_GET["search"]);
                

                $dbconnect->closedbconnection(); //Close connection to db
            ?>
        </div>
    </div>
</body>
</html>

【问题讨论】:

【参考方案1】:

我不能说这里真的有很多 OOP,但听起来和看起来更像是您正在尝试使用参数而不是使用全局变量来学习一种好的方法 - 您似乎已经完成了。

如果你想从这段代码中改进更多,这里有一些指针

尝试使用一致的编码风格。比如PEAR coding standard是PHP常用的 将您的数据库代码更改为一个封装连接对象的类。例如,您可以有一个具有 connectsearchclose 方法的数据库类 对您的 HTML 代码使用一些模板解决方案。您可以将 PHP 本身用作模板语言,如demonstrated here。主要思想是将“应用程序逻辑”与“视图逻辑”分开 您可能还想修改使用echo 的函数以简单地返回结果,并使用另一个函数(或只是模板中的代码)来输出它们。通常,您需要一个函数提供/获取数据或输出数据,而不是两者。

最后,我建议查看一些流行的 PHP 框架,因为它们通常遵循良好的 OOP 编码风格。 CakePHP 应该很容易上手,但是因为它使用 PHP4,所以它并不总是很好地执行 OOP。你可以熟悉 Cake 的原理,然后转向 Symfony 或 Zend Framework 之类的东西。开始使用 Zend Fw 后,我自己的编码风格变得更好了。

【讨论】:

感谢您的意见。我用一些实际对象更新了代码,并遵循了您的其他一些建议(我认为至少 :-))【参考方案2】:

我不确定您所说的面向对象是什么意思,但是您的代码看起来不像传统意义上的类、对象和方法的 OO 代码。当大多数人说“OO”时,他们的意思是他们的代码是由您可以调用方法的不同类型的对象构建的。

对我来说,您的代码看起来像典型的过程代码。

【讨论】:

【参考方案3】:

您当然正确地使用了对象,并且正确地访问了它们。从外观上看,您的 DB 对象是一个单例,这很好。而且您正在使用“->”来访问其他对象方法和属性。

但看起来您正在实现应该是 DB 对象一部分的功能。例如,对于我自己的数据库类,我会做这样的事情

$db = DBObject::getInstance(); // The DB object is a singleton

$sql = "Select * from.... etc etc";

$result = $db->query($sql);

我认为这应该可以完成您尝试做的所有事情。 DB 对象应该知道如何自己连接到数据库,发出自己的错误消息并在需要时关闭连接(它可能不需要)。处理引号、斜杠和确保查询安全等内容也可以在 DB 对象中进行处理。

而且,您尝试执行的过程很容易成为一个单独的类(例如:PageRenderer)。但是在这里,您创建了许多使用其他对象的函数。

但是很难给你一个直接的答案。是的,你做得对,但你似乎做得太多了。

【讨论】:

嗯,不,不是。创建一个名为 dbconnect 的类是错误的,原因有两个。首先,所有类都应以大写字母开头;-) 其次,我怀疑您仍在复制任何半体面的 DB 对象固有的功能。这表明您仍然没有掌握 OOP 的工作方式。您是否编写了 DB 类。如果是这样,请考虑该类中属于哪些额外功能。如果您没有编写它,请查看它的方法以找出您正在复制的功能。如果您发现功能缺失,请自行将其添加到 DB 类中。 我还要补充一点,无法回避这样一个事实,即您必须阅读大量内容才能了解 OOP。从程序转换到 OOP 就像徒手挖金子一样。痛得要命,但这是值得的。 事实上......我只是更详细地查看了您的代码,看来您真的错过了重点。将您的函数分组到一个类中绝对是错误的方法。这些“方法”应该是 DB 类本身的一部分。如果您需要针对特定​​任务调整它们,那么您需要考虑使您的方法更抽象,或者将 DB 子类化以获得更细粒度的控制。所以你原来的问题的答案是明确的......不。【参考方案4】:

我认为,当您真正喜欢编写 OO 时,您应该使用相互交互的对象来完成手头的任务。我没有看到任何从类实例化的对象,所以我认为这不是正确的面向对象的代码。如果你问我,这是更多的程序代码。

【讨论】:

【参考方案5】:

对于 OO,您只有一件事是正确的。 $connection 对象。

其他一切都是程序性的。您应该从创建一个类开始,而不是“dbfunctions.php”中的所有松散函数。

还请注意,您应避免将逻辑代码与 HTML 混合。很难维护。

这里可能是the best book you can read on the subject。

进入面向对象的范式并不容易。但是当你得到它时,就像骑自行车一样。你永远不会忘记。

【讨论】:

混音是我想过怎么做的事情之一,你有什么可以想到的建议/例子吗? 您可以首先让所有函数只返回不带任何 html 的字符串。我可以举一个非常简单的例子:你的函数返回一个简单的字符串,然后在你的索引中调用函数并添加 html 标签,这样你只在你的 html 文件中得到一个函数调用,而所有的逻辑都在一个 php 文件中。 【参考方案6】:

我有一个关于面向对象的php编程的小建议;首先阅读 php.net 中的文档,最后你应该阅读 No Starch Press 的“面向对象的 PHP”一书 -> http://nostarch.com/oophp.htm

另外,在你的类/函数文件的顶部使用这个语句,你将包含(搜索和 dbfunctions.php)

if (!defined('page')) exit('不允许直接脚本访问');

并定义使用此类的页面 - 如下示例:

define("页面","搜索"); 包括(“dbfunctions.php”); 包括(“search.php”);

【讨论】:

【参考方案7】:

我喜欢保持简单直接。这是我使用的一个类,在 Jason Gilmore 的 Beginning PHP and MySQL: From Novice to Professional 一书中使用过

<?php

class SQL 


    function __construct() 

        $this->host     = "xxx";

        $this->user     = "xxx";

        $this->password  = "xxx";

        $this->database  = "xxx";



        $this->result;

        $this->querycount;

        $this->connect();

        $this->select();        

    



    function connect() 

        $this->linkid = @ mysql_connect($this->host, $this->user, $this->password);

        if(!$this->linkid) 

            echo "--[ could not connect to sql database ]--";   exit();

        

    



    function select() 

        if(!@ mysql_select_db($this->database, $this->linkid)) 

            echo "--[ could not select database ]--";   exit();

        

    




    function escape($data) 

        return mysql_real_escape_string(trim(htmlspecialchars($data)), $this->linkid);

    



    function query($query) 

        if( $this->result = @ mysql_query($query, $this->linkid) ) 

            $this->querycount++;

            return true;

         else 

            echo "<b>Error:</b>" . mysql_error($this->linkid);              

            return false;

           

    



    function affectedRows() 

        $count =  @ mysql_affected_rows($this->linkid);

        return $count;

    



    function numRows() 

        $count = @ mysql_num_rows($this->result);

        return $count;

    



    function fetchObject() 

        $row = @ mysql_fetch_object($this->result);

        return $row;

    



    function fetchRow() 

        $row = @ mysql_fetch_row($this->result);

        return $row;

    



    function fetchArray() 

        $row = @ mysql_fetch_array($this->result);

        return $row;

    



    function fetchAssoc() 

        $row = @ mysql_fetch_assoc($this->result);

        return $row;

    



    function numQueries() 

        return $this->querycount;

    





?>

我并不是说这是最好的方法。但它非常简单直接;也应该改用mysqli,但我一直很懒=p

【讨论】:

以上是关于这个 php 代码是不是按照 OO 原则正确编写?的主要内容,如果未能解决你的问题,请参考以下文章

OO 设计原则是不是适用于 Python?

OO设计基本原则

OO六大设计原则

常用的OO设计原则

开放/封闭原则 OO 类设计

OO第四次博客