Проблемы с родителем / наследованием в PHP - PullRequest
1 голос
/ 09 июня 2009

РЕДАКТИРОВАТЬ: Я получил это работает сейчас. Я обновил код:

Я посмотрел несколько примеров здесь, и все они выглядят логичными. Но я не могу заставить его работать. У меня есть класс, который расширяет мой уровень доступа к данным (DAL). Я хотел бы вызвать родительский класс для получения результатов БД. Что я делаю не так?

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 ]

4 голосов
/ 09 июня 2009

Разница между этими:

// $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 голос
/ 09 июня 2009

Стивен, позвольте мне обратить ваше внимание на другие вещи, которые в вашем образце неверны, хотя и синтаксически верны. Основной проблемой здесь является разделение ответственности: уровень доступа к данным должен действовать только как служебный класс для извлечения / хранения данных общего назначения. Любая дополнительная логика должна быть перемещена за пределы этого класса.

  1. Обработка соединения с базой данных не должна быть частью DAL. Идеальным решением является передача объекта db в конструктор, поэтому DAL работает с соединением, настроенным где-то еще. Это называется инъекцией зависимости и обычно считается хорошей вещью.

  2. Метод getAllCountries слишком специфичен для библиотеки общего назначения. Должен быть заменен на getAll, возвращающий все записи из текущей таблицы. Имя таблицы должно быть передано в конструкторе или определено в подклассе, чтобы каждая таблица имела соответствующий объект DAL.

  3. * Метод getCountryListBox генерирует некоторые выходные данные HTML, которые не являются частью ответственности библиотеки DAL. DAL должен возвращать только необработанные данные.

Стоит разделить вещи, чтобы вы могли использовать их в будущем. Добавление слишком большого количества проблемно-зависимых расширений ослабляет ответственность класса. Основные цели класса должны быть очень узкими, поэтому классы могут специализироваться на выполнении разных задач. Сотрудничество между несколькими узкоспециализированными классами должно быть способом предоставления сложной функциональности.

1 голос
/ 09 июня 2009

для части, которую вы хотите получить список всех стран:

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

вторая строка верна. getAllCountries () - это метод вашего объекта, потому что он унаследован от вашего родительского класса. поэтому вам не нужно вызывать родительский метод. Единственное место, где вы хотите вызывать методы родительского класса, - это методы, в которых вы перезаписываете метод.

В любом случае, я предлагаю вам определить ваши свойства в вашем классе DAL как «защищенные», а не «частные». потому что когда вы определяете их как «частные», они не могут наследоваться .

так в вашем классе 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

вы должны определять эти свойства как частные, только если вы не хотите, чтобы они наследовались. Я думаю, что вашему новому объекту нужна эта информация для подключения к базе данных.

1 голос
/ 09 июня 2009

, если ваш класс myOtherClass не реализует метод getAllCountries (), должно работать следующее:

$result = $this->getAllCountries();    

не забывайте знак $ перед 'this'!

0 голосов
/ 09 июня 2009

Вы уверены, что storelocator является экземпляром MyOtherClass? Поскольку метод, который вы вызываете, getCountryListBox определен в MyOtherClass , и ошибка приводит к появлению неопределенных методов getCountryListBox ...

<?php $sl = new storelocator(); ?>
<form id="label_data_form">  
<?php $sl->getCountryListBox();  ?>
0 голосов
/ 09 июня 2009

Отвечать ли вам редактировать?

Еще одна опечатка:

но я думаю, у вас есть правильный (-> вместо -) в вашем коде.

Вы уверены, что myOtherClass является классом storelocator?

0 голосов
/ 09 июня 2009

Вообще говоря, вы бы использовали

$result = $this->getAllCountries();

(обратите внимание на ** $ ** это, а не на это!)

При вызове getAllCountries из любого места, кроме самого метода getAllCountries. Это гарантирует, что если вы переопределите его, будет вызван переопределенный метод.

Внутри метода, если вы хотите вызвать версию базового класса, вам необходимо устранить неоднозначность вызова с parent ::

parent::getAllCountries();

Обратите внимание, что вы можете использовать эту форму вызова метода в любом методе, но я бы сказал, что по умолчанию это будет плохой практикой, так как это лишает вас возможности переопределить этот метод позже.

0 голосов
/ 09 июня 2009

Обновление

Вы должны добавить логика обработки ошибок внутри query () и getAllCountries ().

this-> getAllCountries (); должно быть хорошо, при условии, что это был тип, и вы действительно имели в виду $ this, то есть с долларом.

Я также хотел бы указать на отсутствующую логику в getAllCountries () для случаев, когда метод query () ничего не возвращает и, следовательно, $ this-> query_result ничего не содержит. getAllCountries () должен возвращать что-то вроде пустого массива, потому что могут быть случаи, когда в базе данных нет страны. Вы хотите быть в состоянии справиться с этим.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...