Я пишу процедурный код с объектами или ООП? - PullRequest
3 голосов
/ 23 сентября 2011

Так что в основном я делаю скачок от процедурного кодирования к ООП.Я пытаюсь реализовать принципы ООП, но у меня есть неприятное ощущение, что я на самом деле просто пишу процедурный стиль с объектами.

Так что, скажем, у меня есть список труб / стульев / принтеров / что угодно, онивсе все перечисленные как продукты в моей единой таблице базы данных.Мне нужно создать веб-приложение, которое отображает весь список и элементы в зависимости от их типа, акцент делается на «правильном» использовании ООП и его парадигмы.

Что-то не так в том, чтобы просто делать это так:

     CLass Show
     {

      public function showALL(){
      $prep = "SELECT * FROM myProducts";
      $q = $this->db-> prepare($prep);     
      $q->execute();
      while ($row = $q->fetch()) 
          {
            echo "bla bla bla some arranged display".$row['something']       
          }
      }

, а затем просто

$sth = new show();
$sth->showAll();

Я бы также реализовал более конкретные методы отображения, такие как:

showSpecificProduct ($ id) -> ($ idбудет передаваться через $ _GET, когда пользователь скажет, что нажимает на одну из ссылок, и у нас будет отдельный файл product.php, который будет в основном содержать

include('show.class.php');
$sth = new show();
$sth->showSpecificProduct($id);

showSpecificProduct () будет выполнять как запрос select, так и вывод htmlдля отображения.

Таким образом, чтобы сократить это, я делаю все правильно, или я просто делаю процедурное кодирование с классами и объектами. Также любые идеи / подсказки и т. д. по решению этого, если я делаю этоне так?

Ответы [ 5 ]

2 голосов
/ 23 сентября 2011

Помимо моделей, описанных @Phil и @Drew, я хотел бы призвать вас разделить бизнес, данные и уровни просмотра.

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

class ProductController
{
    public $view;

    public function __construct() {
        $this->view = new View;
    }

    public function indexAction() {
        $model = new DbProductRepository;
        $products = $model->fetchAll();

        $this->view->products = $products;
        $this->view->render('index', 'product');
    }
}

class View
{
    protected $_variables = array();        

    public function __get($name) {
        return isset($this->_variables['get']) ? $this->_variables['get'] : null;
    }

    public function __set($name, $value) {
        $this->_variables[$name] = $value;
    }

    public function render($action, $controller) {
        require_once '/path/to/views/' . $controller . '/' . $action . '.php';
    }
}

// in /path/to/views/product/index.php
foreach ($this->products as $product) {
    echo "Product ID {$product['id']} - {$product['name']} - {$product['cost']}<br />\n";
}
2 голосов
/ 23 сентября 2011

Лучше всего было бы реализовать шаблон хранилища . Пример интерфейса может быть

interface ProductRepository
{
    public function find($id);

    public function fetchAll();
}

Затем вы создадите конкретную реализацию этого интерфейса

class DbProductRepository implements ProductRepsoitory
{
    private $db;

    public function __construct(PDO $db)
    {
        $this->db = $db;
    }

    public function find($id)
    {
        // prepare execute SQL statement
        // Fetch result
        // return result
    }

    public function fetchAll()
    {
        // etc
    }
}

Это вообще плохая идея echo напрямую из метода или функции. Пусть ваши методы возвращают соответствующие объекты / массивы / что угодно и используют эти результаты.

1 голос
/ 23 сентября 2011

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

http://php.net/manual/en/language.oop5.autoload.php

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

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

перед тем, как начать писать класс, вы должны сначала подумать, как бы вы хотели его использовать (см. Тестовую разработку). Как бы вы хотели, чтобы код выглядел при его использовании?

$user = new User($db_object);
$user->load($id);
$user->setName($new_name);
$user->save();

Теперь, когда вы знаете, как вы хотите его использовать, гораздо проще правильно написать его.

Исследуйте гибкие принципы, когда у вас есть шанс.

1 голос
/ 23 сентября 2011

Сценарий, который вы описываете выше, кажется хорошим кандидатом на MVC .

В вашем случае я бы создал класс строго для доступа к данным (делая выбор категорий продуктов илиопределенные продукты), а затем получить другой файл (на ваш взгляд), взять вывод и отобразить его.

Это может выглядеть примерно так:

class Product_Model {
    public function find($prodId) { ... }
    public function fetchAll($category = '') { ... }
    public function search($string) { ... }
}

Затем в другом месте вы можете сделать:1010 *

$products = new Product_Model();
$list = $products->fetchAll(37); // get all from category 37

// in true MVC, you would have a view that you would assign the list to
// $view->list = $list;

foreach($ilst as $product) {
    echo "Product ID {$product['id']} - {$product['name']} - {$product['cost']}<br />\n";
}

Основной принцип MVC состоит в том, что у вас есть классы моделей, которые являются просто объектами, представляющими данные из некоторого источника данных (например, базы данных).Возможно, у вас есть картограф, который отображает данные из базы данных в ваши объекты данных и из них.Затем контроллер получит данные из классов вашей модели и отправит информацию в представление, где обрабатывается фактическое представление.Нежелательно иметь логику просмотра (html / javascript) в контроллерах, а взаимодействие напрямую с вашими данными из контроллера такое же.

0 голосов
/ 23 сентября 2011

Одно из практических правил заключается в том, что имена классов обычно должны быть существительными, поскольку ООП подразумевает наличие программных объектов, соответствующих реальным концептуальным объектам. Функции-члены класса обычно являются глаголами, то есть действиями, которые вы можете выполнять с объектом.

В вашем примере show - это странное имя класса. Более типичным способом сделать это было бы иметь класс с именем что-то вроде ProductViewer с функцией-членом с именем show () или list (). Кроме того, вы можете использовать подклассы как способ получения специализированных возможностей, таких как настраиваемые представления для определенных типов продуктов.

...