Составные первичные ключи CakePHP

В версии 3.0 моего любимого фреймворка, кажется, появятся составные первичные ключи у моделей. Держим кулачки :)

Перебор записей БД по одной CakePHP 2.x

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

В документации на Cake ничего похожего не описано, но возможность такая все-таки есть. По крайней мере в случае Mysql (и, видимо, других источников данных БД).

Модель CakePHP обращается к экземпляру класса Datasource для выборки данных, однако, на самом деле, это экземпляр класса DboSource, наследник Datasource. А у DboSource есть методы execute() и fetchRow(). Поэтому такая конструкция вполне работает:

Внутри модели, конечно, все тоже работает. Просто я из контроллера пробовал :) Как правильно, в соответствии с CakeWay, составлять строку запроса сами разберетесь, не новички.

Одно поле из двух

Столкнулся с необходимостью сделать так, чтобы Cake проверял при валидации заполненность хотя бы одного поля формы из двух. Чтобы от клиента требовать хотя бы имя или фамилию ну, или оба.

Сделал вот такой метод для валидации:

Вот так его в правилах валидации указываю.

Получилось красиво, но насыпалась неприятностей:

  1. Cake считает, что оба поля необходимы, в форме он формирует поля со свойством required и div обертки с соответствующим классом
  2. Если принудительно указать при вызове помощника (helper), что ‘required’=>false, то у input’а свойство убирает, но div продолжает оборачивать. Возможно, глюк dev-версии 2.4
  3. Если обоим полям в модели при валидации указать ‘allowEmpty’=>true, то красивый метод не срабатывает, Cake тогда считает что оба пустых поля тоже валидны

Увы, придется, видимо, в beforeValidation или afterValidation переносить проверку.

Особенности межплагинного взаимодействия

Конечно, вызывать методы классов плагина из другого плагина не очень хорошо. Но, тем не менее. Чтобы впоследствии не было мучительно больно, при объявлении связей между моделями, надо всегда указывать свойство className, причем полностью, т.е. ‘Plugin.MyModel’. Иначе возможны весьма забавные эффекты. Справедливо для версий 1.2 и 1.3. Дальше немного кода.

Читать далее Особенности межплагинного взаимодействия

Список всех-всех контроллеров

Понадобилось мне получить список всех контроллеров приложения, включая контроллеры плагинов. Configure::listObjects, увы, такого не умеет. Этот метод выдает только все контроллеры приложения, но без контроллеров плагинов. Пришлось немного адаптировать метод, предложенный Rob Weaver в гуглогруппе CakePHP. На выходе у моего метода получается объединенный список контроллеров. Основные — как отдает метод listObjects, а принадлежащие плагинам в виде «Plugin.Controller». Можно их поочередно скармливать сразу в App::import. Разве что выбрость те, названия которых на «App» заканчивается, если они не нужны. Будете загружать, помните, что класс «Controller» уже должен быть загружен.

Читать далее Список всех-всех контроллеров

Контроллеры: загрузка

Удивительно но факт. Если из консольного, например, приложения нужно попользоваться моделью, то, само собой, надо загрузить класс модели.

Но загрузить контроллер так не получится. Получим сообщение об ошибке из-за невозможности найти базовый класс Controller. Вот найти класс Model кейк может, а Controller — нет. Во всяком случае 1.2.5. В версии 1.3 не пробовал.

Поэтому приходится загружать его явно и напрямую:

Компоненты: перезагрузка

Не знаю, такую-ли ситуацию имел в виду BorisPlus в своем комментарии. Ну, чем богаты. Вообще не хотел это все описывать, потому как код довольно халтурно написан.

Этот код приложения, изначально крутившийся по Cake 1.1, был переписан для какой-то беты Cake 1.2. С текущей версией, 1.2.5, он работает без проблем, но, возможно, нуждается в чистке.

Эта часть программы выполняющий импорт данных от поставщиков. Поставщики предоставляют данные в CSV формате, но порядок колонок, некоторые значения и т.д., конечно разные. Для осмысленной обработки эти полученные данные надо привести к единообразному виду.

Данные поступают из написанного куцего Datasource, скармливанются компоненту, который и выполняет разбор и приведение к общему виду, потом записываются в нашу таблицу.

Читать далее Компоненты: перезагрузка

Кэш и консоль

За полноценный пост не считается. Так, узелок на память.

В качестве кэша байткода и переменных я использую XCache. Но при запуске консольных приложений, он у меня не работает. Должен или нет, не знаю, не разбирался. Наверное, не должен, если подумать. :-) Просто отметил, что консольные приложения Cake, включая ‘cake bake‘ высыпают кучу ошибок, если XCache используется, как кэш по умолчанию. Поэтому в конфигурации кэша приложения (APP/config/core.php) на CakePHP добавляю маленькую проверку на тип API.

Вот как-то так:

Можно пользоваться константой PHP_SAPI или функцией php_sapi_name(), не важно.