Объект CakePHP 2.0, а не массив - PullRequest
2 голосов
/ 30 октября 2011

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

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

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

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

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

хош

Ответы [ 5 ]

3 голосов
/ 12 ноября 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 невероятно мощный, неизбежный и предназначен для обращения к бесконечным строкам бесконечно связанных таблиц - автоматических обратных вызовов, автоматической передачи данных, генерации запросов и т. Д. Базовая глубина многомерных массивов зависит в вашем методе find, как только вы работаете с более чем одной $ Post с несколькими ассоциированными моделями (например), вы добавили в микс массивы, и этого просто не избежать.

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

FWIW, Set::map, вероятно, выдает эти undefined index ошибки, потому что (догадываясь) вы случайно пытаетесь отобразить действие редактирования, амирит? По умолчанию в действиях редактирования используется только $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

НТН.

2 голосов
/ 11 ноября 2011

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

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

2 голосов
/ 11 ноября 2011

Вы можете создать дополнительные объекты.Таким образом, вы не будете вмешиваться в автоматизацию 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

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

0 голосов
/ 11 ноября 2011

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

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

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

0 голосов
/ 30 октября 2011

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

...