Две модели с общими методами и одной таблицей? [CakePHP]

#php #oop #cakephp #models

#php #ооп #cakephp #Модели

Вопрос:

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

Я знаю, что модели могут быть связаны с одной таблицей, поэтому мне просто нужно добавить $useTable = 'stuff' в модель, и я мог бы добавить type поле. Однако я не могу понять, как создать «родительскую» модель, поскольку каждая модель расширяет AppModel.

Честно говоря, я почти ничего не знаю об ООП, так что, возможно, я упускаю что-то очень очевидное и простое.

Что бы я сделал, не зная, как расширить двух дочерних элементов (продукт и услугу) на родительский элемент (Материал), было бы что-то вроде:

 $this->Stuff->type = 'product';
$products = $this->Stuff->findAvailable();
  

Но я уверен, что есть гораздо более простой и понятный подход.

Спасибо.

Комментарии:

1. почему вы используете 2 модели, когда у вас там одинаковые методы?

2. @alexdd55 потому что это две разные вещи.

Ответ №1:

Используйте поведение. Как указано в кулинарной книге:

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

http://book.cakephp.org/view/1071/Behaviors

Ссылка должна дать вам довольно хорошее представление о том, с чего начать.

Ответ №2:

Вы в основном используете наследоваемость и расширяемость:

Расширяемый: [ссылка удалена в соответствии с моим статусом новичка. Это в файле ниже из gitub]

Наследуемый: http://bakery.cakephp.org/articles/taylor.luk/2008/10/22/inheritable-behavior-missing-link-of-cake-model

Которые были включены в:https://github.com/CakeDC/utils/blob/master/models/behaviors/inheritable.php

Я только что использовал этот же метод (также для продуктов и сервисов). На самом деле, у меня есть разные поля для каждого, общие поля, а затем подтипы (2 класса продуктов и 3 класса услуг), поэтому я создал модель предложения с таблицей предложений, которая выглядит следующим образом:

 CREATE TABLE `offers` (
  `id` int(11) NOT NULL AUTO_INCREMENT,    //common
  `carrier_id` int(11) DEFAULT NULL,       //common
  `category_id` int(11) DEFAULT NULL,      //common
  `name` varchar(255) DEFAULT NULL,        //common
  `description` longtext,                  //common
  `type` ENUM('Product', 'Service') not null default 'Product',
  `sku` varchar(255) DEFAULT NULL,         //product
  `make` varchar(255) DEFAULT NULL,        //product
  `model` varchar(255) DEFAULT NULL,       //product
  `listprice` decimal(9,2) DEFAULT NULL,   //product
  `soc_code` varchar(255) DEFAULT NULL,    //service
  `unit` varchar(255) DEFAULT NULL,        //service
  `units` int(11) DEFAULT NULL,            //service
  `mrc` decimal(9,2) DEFAULT NULL,         //service
  `created` datetime DEFAULT NULL,
  `modified` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `carrier_id` (`carrier_id`),
  KEY `category_id` (`category_id`),
  KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;       
  

Тогда моя предлагаемая модель выглядит следующим образом:

 <?php
class Offer extends AppModel {
  public $name = 'Offer';
  public $useTable = 'offers';
  public $displayField = 'name';

  public $belongsTo = array(
    'Carrier' => array(
      'className' => 'Carrier',
      'foreignKey' => 'carrier_id',
    ),
    'Category' => array(
      'className' => 'Category',
      'foreignKey' => 'category_id',
    )
  );    
  

С моделью продукта:

 <?php
App::import('Model', 'Offer');
class Product extends Offer {
  public $name = 'Product';
  public $useTable = 'offers';
  public $displayField = 'name';
  public $actsAs = array('utils.inheritable');
  

(Сервис практически идентичен).

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

Я надеюсь, что это поможет, если вы еще не нашли решение.

Комментарии:

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

Ответ №3:

Поместите методы, которые используют обе модели, в вашу AppModel:

Этот промежуточный класс, AppModel, пуст, и если вы не создали свой собственный, он берется из папки /cake /. Переопределение AppModel позволяет вам определить функциональность, которая должна быть доступна для всех моделей в вашем приложении. Для этого вам нужно создать свою собственную app_model.php файл, который находится в корне папки /app /.

Ваши модели продуктов и услуг расширяют AppModel. Это означает, что для них доступны все методы из AppModel.