PHP中父/继承的问题

时间:2009-06-09 08:15:35

标签: php inheritance

编辑:我现在开始工作了。我更新了代码:

我在这里看了几个例子,它们看起来都合乎逻辑。但我无法让它发挥作用。我有一个扩展我的数据访问层(DAL)的类。我想调用父类来检索DB结果。我做错了什么?

DAL课程

class DAL { 
  protected $username;     // the username for db connect 
  protected $pwd;          // the pwd to use when connecting 
  protected $host;         // the host to which one connects 
  protected $dbname;       // the db to select 
  public $conn;          // reference to the db link resource 
  public $db;            // result of db_select 
  public $query_result;  // the stored result of the last query you ran 

  public function __construct() 
  { 
    $this->username     = ""; 
    $this->pwd          = ""; 
    $this->host         = ""; 
    $this->dbname       = ""; 
  } 

  public function connect() 
  { 
    /* connects to DB here */
  }  

  private function query($sql) 
  {
    /* Executes the query here and stores the result in $this->query_result */
  }

  public function getAllCountries()
  {
    $sql =" 
      SELECT id, name
      FROM country";

    //Process query
    $this->query($sql);

    if($this->query_result)
      return $this->query_result;      
  }
}

这是我的另一个班级

class myOtherClass extends DAL{

  public function __construct() {
   parent::__construct();
   parent::connect();
  }

  public function getCountryListBox()
  {
    $result = parent::getAllCountries();

    if($result)
    {
      $selectbox = "<select id='countryListBox' name='countryListBox'>";

      while ($row = mysql_fetch_array($result))
      {
        $selectbox .= "<option value='".($row['id'])."'>".($row['name'])."</option>";
      }
      $selectbox .= "</select>";
    }
    else
      $selectbox = "Countries could not be retrievd from database.";

    return  $selectbox;    
  }  
}

这是我模板中的代码:

$sl = new myOtherClass();

echo '<form id="label_data_form">';
  $sl->getCountryListBox(); 
echo '</form>';

8 个答案:

答案 0 :(得分:4)

这些之间的区别:

// $result = parent::getAllCountries();  // Like this
$result = this->getAllCountries();       // Or like this?

..最好在这里解释一下:

class SuperFoo {
    function fubar () {
        echo "superfoo!";
    }

    function fuz () {
        echo "superfuz!";
    }
}

class SubBar extends SuperFoo {
    function fubar() {
        echo "subbar!";
    }

    function demonstrate() {
        $this->fubar();    // "subbar!"
        parent::fubar();   // "superfoo!"

        $this->fuz();      // "superfuz!"
        parent::fuz();     // "superfuz!"
    }
}

$s = new SubBar();
$s->demonstrate();

(好吧,也许不是最好的解释..)

除非你特别想要在父类中定义的行为,否则我总是使用$this->...,因为你可以根据需要改变行为。


MySQL错误似乎是由SQL问题引起的 - 类继承看起来运行正常。

答案 1 :(得分:1)

如果您的类'myOtherClass'未实现'getAllCountries()'方法,则以下内容应该有效:

$result = $this->getAllCountries();    

在'this'之前不要忘记$ -sign!

答案 2 :(得分:1)

您要获取所有国家/地区列表的部分:

// $result = parent::getAllCountries();  // Like this
$result = $this->getAllCountries();       // Or like this?

第二行是正确的。 getAllCountries()是对象的一种方法,因为它是从父类继承的。所以你不需要调用父方法。你想要调用类父类方法的一个地方是你要覆盖方法的方法。

无论如何我建议你在DAL课程中将你的属性定义为'protected'而不是'private'。因为当你将它们定义为'private'时,they can not be inherited

所以在你的DAL课程中:

protected $username;     // the username for db connect 
protected $pwd;          // the pwd to use when connecting 
protected $host;         // the host to which one connects 
protected $dbname;       // the db to select

只有在您不希望继承它们时,才应将这些属性定义为私有。我认为您的新对象需要这些信息才能连接到数据库。

答案 3 :(得分:1)

史蒂文,让我把你的注意力吸引到其他的东西上,尽管你的语法在句法上是正确的,但这些东西在你的样本中是不正确的。这里的主要问题是责任分离:数据访问层应该只作为通用数据检索/存储实用程序类。任何其他逻辑都应该移到这个类之外。

  1. 数据库连接处理不应该是DAL的一部分。理想的解决方案是在构造函数中传递db对象,因此DAL在其他地方配置的连接上运行。这称为依赖注入,通常被视为一件好事。

  2. 方法getAllCountries对于通用库来说太具体了。应该用getAll替换当前表中的所有记录。表名应该在构造函数中传递或在子类中定义,以便每个表都有其对应的DAL对象。

  3. *方法getCountryListBox生成一些HTML输出,这不是DAL库的责任。 DAL应该只返回原始数据。

  4. 值得将事物分开,以便将来可以重复使用它们。添加太多问题特定的扩展模糊了类的责任。课堂的主要目标应该是非常狭隘的,所以课程可以专门做不同的事情。几个高度专业化的课程之间的合作应该是提供复杂功能的方式。

答案 4 :(得分:0)

<强>更新

您应该在query()和getAllCountries()中添加错误处理逻辑

这 - &GT; getAllCountries();应该没问题,只要它是一种类型,你实际上是指$ this,即一美元。

我还想指出getAllCountries()中缺少逻辑的情况,因为query()方法什么都没有返回,因此$ this-&gt; query_result什么也没有。 getAllCountries()应返回类似空数组的内容,因为可能存在数据库中没有国家/地区的情况。你希望能够处理它。

答案 5 :(得分:0)

一般来说,你会使用

$result = $this->getAllCountries();

(注意** $ **而不是这个!)

从getAllCountries方法本身以外的任何地方调用getAllCountries。这将确保如果您要覆盖它,将调用overriden方法。

在方法内部,如果要调用基类版本,则需要使用parent ::

消除歧义。
parent::getAllCountries();

请注意,您可以在任何方法中使用这种形式的方法调用,但我认为默认情况下执行此操作是不好的做法,因为它会拒绝您稍后重写该方法的机会。

答案 6 :(得分:0)

回答你的编辑?

另一个错字:     

但我想你的代码中有正确的( - >代替 - )。

你确定'myOtherClass'是'storelocator'类吗?

答案 7 :(得分:0)

你确定storelocator是MyOtherClass的一个实例吗?因为您调用的方法 getCountryListBox 是在 MyOtherClass 中定义的,并且该错误会抱怨未定义的方法 getCountryListBox ...

<?php $sl = new storelocator(); ?>
<form id="label_data_form">  
<?php $sl->getCountryListBox();  ?>