Объект CakePHP 2.0 не массив

В настоящее время я новичок в CakePHP и играл с CakePHP 1.3, но недавно был выпущен CakePHP 2.0.

Пока мне это нравится, но единственная проблема заключается в том, что он не возвращает объекты, а просто возвращает массивы. Я имею в виду, вряд ли имеет смысл делать $post['Post']['id']. (На мой взгляд) гораздо практичнее просто сделать $post->id.

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

Я следую учебнику по блогу (уже следил за ним в версии 1.3, но снова повторяю его для версии 2.0)

Итак, кто-нибудь знает, как добиться этого, не мешая классу Form?

Хош


person Hosh Sadiq    schedule 30.10.2011    source источник


Ответы (5)


Вы можете создать дополнительные объекты vars. Таким образом, вы не будете мешать автоматической магии Cake, но сможете получить доступ к данным, используя такой формат, как формат $modelNameObj->id;.

Во-первых, создайте AppController.php в /app/Controller, если у вас его еще нет. Затем создайте функцию beforeRender(). Это будет искать данные в стандартных соглашениях об именах Cake и создавать на их основе дополнительные объектные переменные.

<?php
App::uses('Controller', 'Controller');

class AppController extends Controller {

  public function beforeRender() {

    parent::beforeRender();

    // camelcase plural of current model
    $plural = lcfirst(Inflector::pluralize($this->modelClass));

    // create a new object
    if (!empty($this->viewVars[$plural])) {      
      $objects = Set::map($this->viewVars[$plural]);
      $this->set($plural . 'Obj', $objects);     
    }

    // camelcase singular of current model
    $singular = lcfirst(Inflector::singularize($this->modelClass));    

    // create new object 
    if (!empty($this->viewVars[$singular])) {      
      $object = Set::map($this->viewVars[$singular]);
      $this->set($singular . 'Obj', $object);
    }
  }
}

Затем в ваших представлениях вы можете получить доступ к объектам следующим образом:

index.ctp

$productsObj;

view.ctp

$productObj->id;

Все, что мы делаем, это добавляем 'Obj' к именам переменных, которые уже предоставляет Cake. Некоторые примеры сопоставлений:

Товары -> $productsObj

ProductType -> $productTypesObj

Я знаю, что это не идеально, но, по сути, это позволит достичь того, чего вы хотите, и будет доступно для всех ваших моделей.

person Moz Morris    schedule 11.11.2011
comment
Это сработало! Спасибо! Вероятно, это не идеально, как вы сказали, но таким образом у меня будет доступ как к массиву, так и к версии объекта, если мне это понадобится! Спасибо - person Hosh Sadiq; 13.11.2011

Малоизвестный факт: Cake ДЕЙСТВИТЕЛЬНО возвращает их как объекты или, во всяком случае, как свойства объекта. массивы — это синтаксический сахар:

    // In your View:
    debug($this->viewVars);

Shwoing $this — это объект View, а свойство viewVars соответствует $this->set('key', $variable) или $this->set(compact('data', 'for', 'view')) из действия контроллера.

Проблема с раздавливанием их в $Post->id ради нажатий клавиш заключается в том, почему Cake. Cake разработан, чтобы быть тяжелым, поэтому его встроенная ORM невероятно мощная, неизбежная и предназначена для адресации бесконечных строк бесконечных связанных таблиц - автоматические обратные вызовы, автоматическая передача данных, генерация запросов и т. д. Базовая глубина многомерных массивов зависит в вашем методе поиска, как только вы работаете с более чем одним $Post с несколькими связанными моделями (например), вы вводите массивы в микс, и этого просто невозможно избежать.

Различные методы find возвращают массивы разной глубины. Из сгенерированного по умолчанию кода контроллера вы можете видеть, что индекс использует $this->set('posts', $this->paginate()); - просмотр использует $this->set('post', $this->Post->read(null, $id));, а редактирование вообще не использует $this->set с поиском записи - он назначает $this->data = $this->Post->read(null, $id);.

FWIW, Set::map, вероятно, выдает эти undefined index ошибки, потому что (предполагаю) вы пытаетесь сопоставить действие редактирования, amirite? По умолчанию действия по редактированию используют только $this->set для установки связанных результатов поиска модели в представление. Вместо этого результат $this->read отправляется на $this->data. Вероятно, поэтому Set::map не работает. В любом случае, вы все равно будете стремиться к $Post[0]->id или $Post->id (в зависимости от того, какой метод вы использовали), что не является большим улучшением.

Вот несколько общих примеров глубины свойства Set::map() для этих действий:

    // In posts/index.ctp
    $Post = Set::map($posts);
    debug($Post);
    debug($Post[0]->id);

    // In posts/edit/1
    debug($this-viewVars);
    debug($this->data);

    // In posts/view/1
    debug($this-viewVars);
    $Post = Set::map($post);
    debug($Post->id);

http://api13.cakephp.org/class/controller#method-Controllerset

http://api13.cakephp.org/class/model#method-Modelread

http://api13.cakephp.org/class/model#method-ModelsaveAll

ХТН.

person OpenSorceress    schedule 12.11.2011

Хотя мне нравится идея, которую предлагает Моз, существует ряд существующих решений этой проблемы.

Самый быстрый, который я нашел, это https://github.com/kanshin/CakeEntity - но похоже, что вы возможно, потребуется рефакторинг для 2.x - может быть, уже есть ветка или ответвление 2.x, но я не смотрел.

person Abba Bryant    schedule 11.11.2011
comment
Существует ветка 2.0, которая была обновлена ​​с учетом соглашений CakePHP 2.0 об именах файлов и т. д. - person brism; 11.11.2011

Я тоже пару раз прокручивал этот вопрос в голове. Теперь, спустя несколько приложений на основе Cake, я вижу преимущество возможности более удобного ветвления и объединения наборов результатов (am, in_array и т. д.) с массивами, чем с использованием объектов. Форма $Post->id была бы приятным синтаксическим сахаром, но не имела бы реального преимущества перед массивами.

person sibidiba    schedule 30.10.2011
comment
Ценю ваш вклад, но на самом деле это не отвечает на мой вопрос :/ - person Hosh Sadiq; 31.10.2011
comment
Я просто хотел указать, что вы пытаетесь сделать это неправильно. Ассоциативные массивы - это путь. - person sibidiba; 24.11.2011

Вы можете написать функцию, которая перебирает ваши общедоступные свойства (см. ReflectionClass::getProperties) и сохраните его в массиве (и верните массив).

Если у вас есть доступ к этому классу, вы можете реализовать интерфейс ArrayAccess и легко получить доступ к вашему объекту в виде массива.

P.S.: Извините, я никогда не использовал CakePHP, но я думаю, что преобразование объекта в массив не должно быть проблемой, специфичной для фреймворка.

person breiti    schedule 11.11.2011