PHP OOP方法遇到困难

时间:2012-08-01 08:55:25

标签: php oop

请参阅下面的编辑

我正试图深入研究PHP中的OOP开发,我真的开始出现头痛或溃疡。我只是无法绕过它,部分看起来对我来说太不合逻辑了,我不知道从哪里开始它真的让我感到沮丧,因为我相信值得努力尝试学习它并且它提供了我更好的概述关于我的代码。

<击>

昨天我花了一整天的时间在互联网上搜索实际例子和解释性文章,但现在我觉得这只会让我更加困惑。我需要一些实用的技巧,而不是像

这样的例子


class person {
     var $name;
     function set_name($new_name) {
          $this->name = $new_name;
     }
     function get_name() {
          return $this->name;
     }
}
$stefan = new person();
$jimmy = new person;

$stefan->set_name("Stefan"); $jimmy->set_name("Jimmy");

echo "Stefan's full name: " . $stefan->get_name(); echo "Jimmy's full name: " . $jimmy->get_name();

这样的例子让我怀疑为什么我不应该(因为它都在同一页面中定义)只是做

$name = "Stefan"; 
echo "Stefan's full name: ".$name;

如果你问我,会更短(代码更少),更明显吗?

不,我的项目。

我想要做的是一个简单的投资组合网站。因此,我只需要4页,主页信息页面,关于我的工作的页面和联系人形成。我使用了三个表clientscontentmedia,我想在 my work 页面上使用这些表。

我正在考虑我的结构,并且出现了(在我脑海中,不知道如何实现它),例如

class Database{}
class Content extends Database{}
     function showMenu(){}
     function showContent{}
class Clients extends Database{}
     function showClientList{}
     function showClientDetails{}
class Media extends Database{}

我已经创建了一个数据库类,它使用公共方法query($qry)建立数据库连接。我从Content类开始,现在看起来像这样:


class Content extends Database {
    public function topMenu($page){
        $db = new Database();
        $db->connect();
        $db->query("SELECT m_link, m_title, m_accesskey FROM menu WHERE m_type = 'top'"); 
        $res = $db->getResult();
        foreach($res AS $show){
            if($page == $show['m_link']){
                echo("<li id="active">$show['m_title']."</li>\n");
            }else{
                echo("<li>$show['m_title']."</li>\n");
            }
        }
    }
}

顺便说一下这根本没有意义吗?

在我的index.php上,我有以下行显示菜单(工作正常)$content = new Content(); $content->topMenu($_aGET[0]);

我放弃它的方式是顶部显示客户列表客户端详细信息的方式,这取决于变量$_aGET[0](持有网址

假设我想显示客户端详细信息,因此我需要来自所有三个表的记录,所以通常我会使用几个连接,如此

$query = "
    SELECT cl.c_id, cl.c_client, cl.c_client_desc, ncc.clco_cl_id, ncc.clco_co_id, co.c_content, ncm.clme_me_id, ncm.clme_cl_id, GROUP_CONCAT(me.m_link) AS images_link
    FROM clienten AS cl
    LEFT JOIN norm_cl_co_rel AS ncc ON cl.c_id = ncc.clco_cl_id
    LEFT JOIN content AS co ON ncc.clco_co_id = co.c_id
    LEFT JOIN norm_cl_me_rel AS ncm ON cl.c_id = ncm.clme_cl_id
    LEFT JOIN media AS me ON me.m_id = ncm.clme_me_id
    WHERE cl.c_client = '".mysql_real_escape_string($_aGET[1])."'
    AND cl.c_language_id = '"._LANGUAGE."' 
    AND cl.c_active = '1'
";

但是到目前为止我理解OOP的想法,我应该为一个类中定义的每个表都有一个方法(对吧?)但是我该如何加入这些?

或者我的'故事'看起来像是:'老兄,只需放弃它并坚持使用程序编码'?

修改

好的,在Fluffeh的帖子之后,我使用他的例子并对其进行了一些修改以测试它。问题是我确实得到了一些输出,但不是所希望的。我的输出如下

ID: CompanyName
C
Desc: C
Media:
: 
: 
: 
: 
:

虽然我应该得到(值在数据库中):

ID: CompanyName
CompanyName
Desc: CompanyName is a company
Media:
: Image 1
: Image 2
: Image 3
: Image 4
: Image 5

我的代码如下:

class media{
    public $type;
    public $title;
    public $image;
    public $desc;
}

class client{
    public $name;
    public $desc;
}

class clientDetails{

    private $clientID;
    public $clientName;
    public $clientDesc;
    public $clientMedia = array();
    public $clientMediaFiles = 0;

    public function __construct($myID){
        $this->clientID = $myID;
    }

    public function getMyDetails(){

        $db = new Database();
        $db->connect();
        $db->query("
            SELECT c_client, c_client_desc 
            FROM clienten 
            WHERE c_client = '".mysql_real_escape_string($this->clientID)."'
        ");
        foreach($db->getResult() as $client){
            $this->name = $client['c_client'];
            $this->desc = $client['c_client_desc'];
        }

        $db = new Database();
        $db->connect();
        $db->query("
            SELECT ncm.clme_me_id, ncm.clme_cl_id, cl.c_id, me.m_id, me.m_type, me.m_title, me.m_desc, me.m_link
            FROM norm_cl_me_rel AS ncm
            LEFT JOIN clienten AS cl ON cl.c_id = ncm.clme_cl_id
            LEFT JOIN media AS me ON me.m_id = ncm.clme_me_id
            WHERE me.m_id IN(1,2,3,4,5)
        ");
        foreach($db->getResult() as $media){
            $this->clientMedia[$i]= new media();
            $this->clientMedia[$i]->type = $media['m_type'];
            $this->clientMedia[$i]->title = $media['m_title'];
            $this->clientMedia[$i]->image = $media['m_image'];
            $this->clientMedia[$i]->desc = $media['m_desc'];
            $this->clientMediaFiles++;
        }
    }

    public function displayMyResults(){
        echo "ID: $this->clientID";
        echo "&lt;div>&lt;h3>".$this->name."&lt;/h3>";
        echo "Desc: ".$this->desc."&lt;br>";
        echo "Media:&lt;br>";
        for($i=0;$i<$this->clientMediaFiles;$i++){
            echo $this->clientMedia[$i]->title." : ".$this->clientMedia[$i]->desc."&lt;br>";
        }
        echo "&lt;/div>";
    }

}

4 个答案:

答案 0 :(得分:6)

继续使用OOP。一旦你得到它,你将永远不想回到讨厌,麻烦,讨厌,可怕,狂热的程序代码。

举一个这样的例子:假设我想显示客户端的详细信息,因此我需要来自所有三个表的记录,所以通常我会使用几个连接,就像这样......

这是一个很好的例子,可以用来向你展示OOP的用途。

ClientDetails

创建一个类
  • 在其中创建一个接受clientID作为参数的构造函数。
  • 在此构造函数中,让它运行代码并使用查询返回的数据填充其内部变量。
  • 创建一个函数,输出返回的格式很好的数据。
  • 现在从主代码创建它并让它显示它的详细信息

突然间,您在一个类中有几行代码,但可以在两行代码中完美地显示您的数据。

我将很快添加一些示例代码,看看我是否可以翻译一些我的课程进行演示。

编辑:该死的,没有翻过旧的课程,对此非常详细,但我写了一些代码作为例子:

<?php

class clientContact
{
    public $name;
    public $phone;
}

class clientDetails
{
    private $clientID;      //only this class can access this variable.
    public $clientName;     // Anything can change these.
    public $clientPhone;
    public $additionalContacts= array();
    public $associates=0;

    public function __construct($myID)
    // This is a magic function that is called every time we make a new object of this class.
    {
        $this->$clientID=$myID;
    }

    public function getMyDetails()
    // This function will query the database to get it's information properly
    // and populate itself with everything it needs. You could do this as part
    // of the __construct() call, but I didn't want to do TOO much code.
    {
        $sql="select clientName, clientPhone from clients where clientID=".$this->clientID.";";
        // skipping over full SQl bits...
        foreach($stmt as $clientContact)
        {
            $this->clientName=$clientContact->clientName;
            $this->clientPhone=$clientContact->clientPhone;
        }

        $sql="select clientName, clientPhone from associates where assocID=".$this->clientID.";";
        // skipping over full SQl bits...
        foreach($stmt as $clientContact)
        {
            $this->additionalContacts[$i]= new clientContact();
            $this->additionalContacts[$i]->name=$clientContact->name;
            $this->additionalContacts[$i]->phone=$clientContact->phone;
            $this->associates++;
        }

    }

    public function displayMyResults()
    // This function will simply display everything it has in a nicely format
    {
        echo "<div><h3>".$this->clientName."</h3>";
        echo "My contact phone number is :".$this->phone."<br>";
        echo "My associates are:<br>";
        for($i=0;$i<$this-associates;$i++)
        {
            echo $this->additionalContacts[$i]->name." : ".$this->additionalContacts[$i]->phone."<br>";
        }
        echo "</div>";

    }
}

?>

天哪,这很长很可怕吗?

不是真的。这就是原因。

当然,课程中有一些代码,但现在,您可以在主页上执行以下操作:

<?php 

    $someArray=array(36, 25, 76); 
    // This could be from a query, or a form, or anything else

    for($i=0;$i<count($someArray);$i++)
    {
        $currentContact= new clientDetails($someArray[$i]);
        // This is how we create the object.

        $currentContact->getMyDetails();
        // This now tells the object to get it's own data

        $currentContact->displayMyResults();
        // This now displays the data in the object to the page.
        echo "<hr>";
        unset($currentContact);
    }
?>

使用该TINY代码片段,您只需显示所有联系人,按照您的需要进行格式化,您只需完全按照您的需要显示所有联系人。

现在想象一下,不是像这样的一个小例子,而是为所有内容使用这些对象。论坛上的帖子?一个对象。业务关键绩效指标的复杂计算?一个对象可以获取它拥有的所有数据,然后计算预测,在图表中显示结果并通过电子邮件发送给需要它的用户。

当你来自HTML和PHP脚本从上到下执行的背景时,OOP可能会有一个陡峭的学习曲线,但当你开始掌握它时,你会希望你从一开始就学会了它。 / p>

编辑:

您的查询中似乎没有列m_image

    $db = new Database();
    $db->connect();
    $db->query("
        SELECT cl.c_id, ncm.clme_me_id, ncm.clme_cl_id, me.m_type, me.m_title, me.m_desc, me.m_link, m_image
        FROM clienten AS cl
        LEFT JOIN norm_cl_me_rel AS ncm ON cl.c_id = ncm.clme_cl_id
        LEFT JOIN media AS me ON me.m_id = ncm.clme_me_id
        WHERE me.m_id IN(1,2,3,4,5)
    ");
    foreach($db->getResult() as $media){
        $this->clientMedia[$i]= new media();
        $this->clientMedia[$i]->type = $media['m_type'];
        $this->clientMedia[$i]->title = $media['m_title'];
        $this->clientMedia[$i]->image = $media['m_image'];
        $this->clientMedia[$i]->desc = $media['m_desc'];
        $this->clientMediaFiles++;
    }

编辑2:我不是100%肯定,但可能是返回的字段名称。尝试用以下代码替换查询:

SELECT cl.c_id as c_id, ncm.clme_me_id as clme_me_id, ncm.clme_cl_id as clme_cl_id, me.m_type as m_type, me.m_title as m_title, me.m_desc as m_desc, me. as m_link
FROM clienten AS cl
LEFT JOIN norm_cl_me_rel AS ncm ON cl.c_id = ncm.clme_cl_id
LEFT JOIN media AS me ON me.m_id = ncm.clme_me_id
WHERE me.m_id IN(1,2,3,4,5)

答案 1 :(得分:0)

当我在Java上学习OOP时,他们告诉我将每个Object类型视为新变量类型。这意味着,如果你有一个类Person(PS它是一个很好的命名约定,可以使类名中的第一个字母大写),那么持有Person对象的对象可以被认为是{em>类型{{ 1}}

我能给你的最好的例子就是当我做 IRC Bot 时。 Bot需要跟踪PersonUserChannel s。 IRC协议基于完全在字符串上。

虽然我可以处理字符串,但这会大大增加我的应用程序的复杂性以及代码可读性。相反,我选择将该数据转换为ServerChannelUser对象,这些对象具有与IRC服务器交互的方法。

例如:

Server

只要用户加入频道,就会调用此方法。这允许/** * Add $user to $channel. * @param Channel $channel * @param User $user * * @throws Exception */ protected function addUser(Channel $channel, User $user) { if (!isset($this->chanList[$channel->name])) { #Channel is not on channel list throw new Exception("You are not on that channel"); } if (!isset($this->userList[$user->nick])) { #User is not on global user list (New user) $this->userList[$user->nick] = $user; #Add user to list } $this->chanList[$channel->name]->addUser($user); #Add the user to the channel user list } 对象跟踪用户以及他们所处的渠道。代码执行一些验证,然后将Bot对象添加到User对象。

现在想象一下,如果你必须只使用字符串,你必须解析IRC协议中的每一行,提取所需的数据,并操纵一些非常大的数组。最终,你有一个大混乱,而不是保持良好和有条理。

答案 2 :(得分:-1)

所以OOP是很好的方法,如果用例如MVC和前端控制器模式。但是如果你只想要有4个页面的简单网站,你可以真正使用程序代码,没问题。如果你知道drupal,那就是90%的程序代码。

但是...

$db = new Database();
        $db->connect();

创建db对象并在每个方法中连接并不是一个好主意。更好的是在脚本中只共享一个db con对象。你可以使用单例模式并像这样做。

class Database extends PDO {

  private static db = null;

  private function __construct() {
        parent::__construct(/* here get some conf data*/);    
  }

  public static getDb() {
    if(!self::db) self::db = new self();
    return self::db;
  }

  /* here you can add your custom methods like loadMenu etc. */
}

最好可以解析逻辑视图层,看看解压缩php函数,它将数组的所有元素添加到实际符号表中(键是该变量的名称,值是值)。 使用提取功能,您可以执行漂亮的视图层,从视图中分离逻辑。 类似的东西:

define('TEMPLATE_DIR', __DIR__ . '/templates');

function render($template, $variables) {
  extract($variables);
  require TEMPLATE_DIR . "/$template.tpl.php"; 
}

$variables = array('menu_links' => Database::getDb()->getMenu());

render('menu', $variables);

在你的menu.tpl.php中:

<ul>
  <?php foreach($menu_links as $link) : ?>
  <li><a href="<?= $link['href'] ?>"><?= $link['title'] ?></a></li>
  <?php endforeach; ?> 
</ul>

答案 3 :(得分:-2)

PHP OOP通常归结为一个好的MVC(模型视图控制器)conecpt和实现。

如前所述,你经常不需要使用PHP进行OOP,因为它的射击可以用来制作锡罐而不是棒球......因为网站本身往往是MVCd而且多余的代码并没有伤害任何人(只要您在数据库/会话/表单中没有混乱的安全性)

关于PHP MVC的一个很好理解的例子是http://anantgarg.com/2009/03/13/write-your-own-php-mvc-framework-part-1/

第一部分是非常容易理解的,第二部分(在#1末尾链接)有点令人困惑,因为autor重命名了一些类并且没有完全解释它们。

但是查看zip文件中提供的代码已经为您提供了一个好主意。