Хорошо, поэтому я пытаюсь научить себя фреймворку CakePHP, и я пытаюсь создать для себя простое демонстрационное приложение.
У меня все контроллеры, представления и модели настроены и работают, но я хочу сделать что-то немного большее, чем показано в базовой интерактивной справке.
У меня есть файл guitars_controller.php следующим образом ...
<?php
class GuitarsController extends AppController {
var $name = 'Guitars';
function index() {
$this->set('Guitars', $this->Guitar->findAll());
$this->pageTitle = "All Guitars";
}
function view($id = null) {
$this->Guitar->id = $id;
$this->set('guitar', $this->Guitar->read());
// Want to set the title here.
}
}
?>
Объект Guitar содержит атрибут с именем Name, и я хотел бы иметь возможность установить его в качестве pageTitle для отдельных просмотров страниц.
Кто-нибудь может указать, как я это сделаю, пожалуйста?
NB: Я знаю, что есть общие разногласия по поводу того, где в приложении устанавливать такие данные, но для меня это связано с данными.






$this->pageTitle = $this->Guitar->Name;
Хотя он должен идти в View, я не PHP или cakePHP, но это то, что должно делать представление, а не контроллер.
$ this-> pageTitle = $ this-> Guitar-> Name; Я тоже так думал, но не работает. Это имеет смысл в объектно-ориентированной парадигме, но явно не в CakePHP.
Важно понимать, что в отличие от Rails, CakePHP не создает данные модели как объекты. Классы модели в приложении / модели - это в значительной степени просто DAO. Данные всегда доступны в виде ассоциативных массивов.
Он должен войти в контроллер. См. это
Вы также можете установить его в представлении
Вы можете установить это в контроллере:
function view($id = null) {
$guitar = $this->Guitar->read(null, $id);
$this->set('guitar', $guitar);
$this->pageTitle = $guitar['Guitar']['name'];
}
Или в представлении:
<? $this->pageTitle = $guitar['Guitar']['name']; ?>
Значение, установленное в представлении, переопределит любое значение, которое, возможно, уже было установлено в контроллере.
В целях безопасности вы должны убедиться, что ваш макет / представление, которое отображает html pageTitle, кодирует эти произвольные данные, чтобы избежать атак с использованием инъекций и сломанного HTML.
<?php echo h( $title_for_layout ); ?>
"but I want to do something slightly more than the basic online help shows."
Разве это не всегда проблема? Так много документации сводится к минимуму, что на самом деле мало помогает. Вы можете пройти многие из доступных руководств, но как только вы сделаете 1 шаг от резервации, возникнет путаница. Ну, это либо абсолютный минимум, либо максимум профессионального разработчика, но редко попадает в золотую середину легкости, ясности и глубины.
В настоящее время я переписываю некоторую документацию Zend Framework для собственного использования, чтобы я мог сгладить несоответствия, прояснить замалчиваемые предположения и добраться до основного, "передового" способа понимания этого. Моя мантра: легкость, ясность, глубина. Легкость, четкость, глубина.
Ах, неочевидный ответ таков ...
$this->pageTitle = $this->viewVars['guitar']['Guitar']['Name'];
Я нашел это, поместив следующий код в контроллер (честно говоря, это был долгий путь, который окупился)
echo "<pre>"; print_r($this);echo "</pre>";
Спасибо всем, кто пытался помочь.
Для этой цели у cake есть отличная функция, называемая debug (). В вашем контроллере или представлении: debug ($ variable, true); Логическое значение htmlencode кодирует данные отладки. Также не следует читать из viewVars. Проверьте ответ Пауло, который в настоящее время получил наибольшее количество голосов.
Спасибо за эту ценную информацию. Я постараюсь не забыть использовать это в следующий раз. :)
Эти действия не зависят от модели, поэтому их можно поместить в файл app / app_controller.php.
<?php
class AppController extends Controller {
function index() {
$this->set(Inflector::variable($this->name), $this->{$this->modelClass}->findAll());
$this->pageTitle = 'All '.Inflector::humanize($this->name);
}
function view($id = null) {
$data = $this->{$this->modelClass}->findById($id);
$this->set(Inflector::variable($this->modelClass), $data);
$this->pageTitle = $data[$this->modelClass][$this->{$this->modelClass}->displayField];
}
}
?>
Указание в вашем браузере / guitars вызовет действие index вашего контроллера гитары, которого не существует, поэтому будет запущено действие в AppController (от которого GuitarsController наследует). То же самое для действия просмотра. Это также будет работать для ваших DrumsController, KeyboardsController и т. д.
По-моему, это не так уж и полезно, поскольку в большинстве реальных настроек вам нужно, чтобы произошло больше вещей, чем это. Кроме того, он отвечает на вопрос, но также усложняет его больше, чем нужно, поскольку он больше запутывает, чем помогает. По крайней мере, учитывая базовое понимание, которое есть у OP.
Все, что вам нужно сделать, нужно делать в подклассе this. Это отличный пример выделения общего кода. Синтаксис немного сложнее, но эта сложность оправдана из-за удаления дублирующего кода.
Хотя это прекрасно работает, это может показаться слишком общим и запутанным для новичка.
В ответ на ваш собственный ответ о парадигме oo. Это вот так :
function view($id) {
$this->Guitar->id = $id;
$this->Guitar->read();
$this->pageTitle = $this->Guitar->data['Guitar']['name'];
$this->set('data', $this->Guitar->data);
}
Кстати, вы должны проверить, установлен ли идентификатор и действителен ли и т. д., Поскольку это вводимый пользователем URL.
echo "<pre>"; print_r($this);echo "</pre>";
как насчет
pr( $this );
Хорошо, я действительно хочу установить заголовок страницы в контроллере, а не в представлении. Итак, вот что я сделал:
class CustomersController extends AppController {
var $name = 'Customers';
function beforeFilter() {
parent::beforeFilter();
$this->set('menu',$this->name);
switch ($this->action) {
case 'index':
$this->title = 'List Customer';
break;
case 'view':
$this->title = 'View Customer';
break;
case 'edit':
$this->title = 'Edit Customer';
break;
case 'add':
$this->title = 'Add New Customer';
break;
default:
$title = 'Welcome to '.$name;
break;
}
$this->set('title',$this->title);
}
Хитрость в том, что $this->title нельзя установить ни в какое действие, это не сработает. Мне кажется, что веб-страница достигает действия после рендеринга, однако вы можете сделать это в beforeFilter.
Начиная с CakePHP 1.3, настройка заголовка страницы была изменена.
$this->pageTitle = "Title"; //deprecated
$this->set("title_for_layout",Inflector::humanize($this->name)); // new way of setting title
Примечание: Подробнее о Inflector: http://api13.cakephp.org/class/inflector#method-Inflector
может также должен быть установлен в представлении. Однако CakePHP предоставляет данные в виде ассоциативных массивов, а не объектов. $ this-> pageTitle = $ guitar ['Гитара'] ['имя']