Статьи

Создайте панель администратора с помощью Fuel PHP Framework

В первой части этой серии мы рассмотрели основы инфраструктуры FuelPHP. В этой второй части мы увеличим скорость и перейдем к более сложным темам! Мы будем создавать админ-панель для нашего приложения, охватывать общие области применения ORM и использовать пакет аутентификации для ограничения доступа.

Присоединяйтесь ко мне после перерыва, чтобы начать!


С первой статьи Fuel был переименован в FuelPHP. Также в отличие от первой статьи, которая была основана на v1.0.1, эта статья требует v1.1.0, поэтому некоторые мелочи отличаются. Вся теория, которую вы узнали из первой статьи, все еще точна и не сильно изменилась, так что это должно быть легко.


Если вы еще не установили служебное масло командной строки и вам повезло работать на Linux, Mac, Solaris и т. Д., То сделайте это с помощью следующей команды:

1
$ curl get.fuelphp.com/oil |

Команда oil поможет вам создавать новые проекты с помощью нескольких нажатий клавиш и псевдонима php oil в ваших приложениях FuelPHP:

1
2
$ oil create Sites/blog
$ cd Sites/blog

Это создаст для нас приложение для блога и, если у вас в папке «Сайты» работает Apache или какой-либо другой веб-сервер, вы сможете загрузить следующий URL и увидеть страницу приветствия .

alt text

Теперь, когда FuelPHP активен и ваш веб-сервер работает нормально, мы можем приступить к настройке нашего приложения.


Откройте ваш любимый редактор, и мы начнем с настройки соединения с базой данных и настройки приложения. Это почти идентично v1.0.x, поэтому создайте базу данных и настройте пользователей SQL, как обычно. Когда дело доходит до конфигурации базы данных, есть два различия:

  • PDO теперь драйвер по умолчанию
  • FuelPHP v1.1 теперь имеет папки конфигурации на основе среды.

Эти изменения довольно просты, но вы можете вернуться к использованию собственного драйвера MySQL, если хотите. PDO более полезен для разработчиков, поскольку означает, что ваше приложение будет работать практически с любым ядром базы данных, а не только с теми, для которых были созданы специальные драйверы FuelPHP. Это означает, что это также может быть SQLite или PostgreSQL.

Просто откройте fuel/app/config/development/db.php и измените ваш fuel/app/config/development/db.php , где dbname=blog — это имя вашей базы данных, а также ваши собственные имя пользователя и пароль для сервера базы данных:

1
2
3
4
5
6
7
8
9
return array(
  ‘default’ => array(
     ‘connection’ => array(
         ‘dsn’ => ‘mysql:host=localhost;dbname=blog’,
         ‘username’ => ‘root’,
         ‘password’ => ‘password’,
     ),
  ),
);

Далее вам просто нужно открыть fuel/app/config/config.php и включить пакеты auth и orm, как предложено в первом посте.

1
2
3
4
5
6
7
8
9
/**************************************************************************/
/* Always Load */
/**************************************************************************/
‘always_load’ => array(
 
    ‘packages’ => array(
        ‘auth’,
‘orm’,
    ),

В этом конфигурационном файле нам нужно внести одно небольшое изменение в массив whitelisted_classes что позволит нам передавать объекты проверки в представление:

1
2
3
4
5
6
7
‘whitelisted_classes’ => array(
    ‘Fuel\\Core\\Response’,
    ‘Fuel\\Core\\View’,
    ‘Fuel\\Core\\ViewModel’,
    ‘Fuel\Core\Validation’,
    ‘Closure’,
),

Пакет auth, включенный в FuelPHP, основан на драйвере, и по умолчанию мы используем «SimpleAuth», который является единственным драйвером, включенным в пакет. Когда вы разбираетесь в FuelPHP, вы можете начать создавать собственные драйверы для интеграции с системами других пользователей, такими как сторонние форумы, системы управления контентом и т. Д.

Чтобы включить группы для SimpleAuth, мы просто открываем fuel/packages/auth/config/simpleauth.php и устанавливаем для групп следующее:

1
2
3
4
5
6
7
8
9
return array(
  ‘groups’ => array(
      -1 => array(‘name’ => ‘Banned’, ‘roles’ => array(‘banned’)),
      0 => array(‘name’ => ‘Guests’, ‘roles’ => array()),
      1 => array(‘name’ => ‘Users’, ‘roles’ => array(‘user’)),
      50 => array(‘name’ => ‘Moderators’, ‘roles’ => array(‘user’, ‘moderator’)),
      100 => array(‘name’ => ‘Administrators’, ‘roles’ => array(‘user’, ‘moderator’, ‘admin’)),
  ),
);

Конечно, это может быть что угодно, но они довольно стандартны для большинства приложений и подойдут для этого урока.


Поскольку мы создаем панель администратора, нам нужно создать таблицу пользователей, а затем заполнить ее записью пользователя, который будет первым администратором. Мы могли бы использовать что-то вроде phpMyAdmin или графический интерфейс, такой как Navicat, но лучше делать это через Oil, чтобы мы оставались в нашей базе кода. Это означает, что хеширование пароля происходит правильно с любым используемым драйвером — и вот как мы будем это делать:

1
2
3
4
$ oil generate model users username:varchar[50] password:string group:int email:string last_login:int login_hash:string profile_fields:text
  Creating model: /Users/phil/Sites/blog/fuel/app/classes/model/user.php
  Creating migration: /Users/phil/Sites/blog/fuel/app/migrations/001_create_users.php
$ oil refine migrate

Это создает для нас пользовательскую модель и создает еще одну миграцию, которая будет строить нашу пользовательскую таблицу при запуске задачи миграции для очистки масла. Затем мы должны создать пользователя-администратора, что, опять же, мы могли бы сделать через графический интерфейс, но где в этом удовольствие?

1
2
3
4
5
$ oil console
Fuel 1.1-rc1 — PHP 5.3.6 (cli) (Sep 8 2011 19:31:33) [Darwin]
>>> Auth::create_user(‘admin’, ‘password’, ‘[email protected]’, 100);
1
— Ctrl + C to exit

Мы использовали консоль Oil для написания кода в реальном времени и получения ответа. Auth::create_user() было передано имя пользователя, пароль, адрес электронной почты и group_id для администраторов, которые на данный момент мы просто будем использовать 100 — которые мы установили в конфигурации. 1 является ответом от кода, что означает, что user_id имеет значение 1 .


Генераторы — отличный способ создать кучу кода с нуля и начать работу.

Как объяснялось в первой статье, мы можем использовать скаффолдинг для быстрого создания больших кусков приложения. Это делается с помощью команды oil и все это очень необязательно, но это отличный способ собрать кучу кода с нуля. Некоторые люди смотрят на генерацию кода как на «инструмент для людей, которые не знают, как кодировать», или думают, что это какая-то черная магия, но если вы новичок в фреймворке и не хотите изучать, как все собрать тогда наличие системного кода для вас не так уж плохо.

FuelPHP v1.1 продвигает генерацию кода на один шаг вперед. Вместо того, чтобы просто создавать строительные леса (незащищенные CRUD), теперь вы можете генерировать код администратора. Это работает точно так же, но реализует простой шаблон администратора, контроллер администратора и т. Д. И использует пакет auth для блокировки вашего сгенерированного кода. Воспользовавшись Twitter Bootstrap , все это выглядит достаточно хорошо для использования, и с небольшим количеством настроек у вас будет приложение, которое вы можете отправить.

Это делается через командную строку с помощью команды масла. Мы сгенерируем некоторый код, а затем пройдемся по нему.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
$ oil generate admin posts title:string slug:string summary:text body:text user_id:int
    Creating controller: /Users/phil/Sites/blog/fuel/app/classes/controller/base.php
    Creating controller: /Users/phil/Sites/blog/fuel/app/classes/controller/admin.php
    Creating views: /Users/phil/Sites/blog/fuel/app/views/admin/template.php
    Creating views: /Users/phil/Sites/blog/fuel/app/views/admin/dashboard.php
    Creating views: /Users/phil/Sites/blog/fuel/app/views/admin/login.php
    Creating migration: /Users/phil/Sites/blog/fuel/app/migrations/002_create_posts.php
    Creating model: /Users/phil/Sites/blog/fuel/app/classes/model/post.php
    Creating controller: /Users/phil/Sites/blog/fuel/app/classes/controller/admin/posts.php
    Creating view: /Users/phil/Sites/blog/fuel/app/views/admin/posts/index.php
    Creating view: /Users/phil/Sites/blog/fuel/app/views/admin/posts/view.php
    Creating view: /Users/phil/Sites/blog/fuel/app/views/admin/posts/create.php
    Creating view: /Users/phil/Sites/blog/fuel/app/views/admin/posts/edit.php
    Creating view: /Users/phil/Sites/blog/fuel/app/views/admin/posts/_form.php
    Creating view: /Users/phil/Sites/blog/fuel/app/views/template.php

Это довольно много кода, потому что это первый раз, когда он был запущен. FuelPHP создаст несколько базовых шаблонов и файлов, а затем создаст компоненты MVC для раздела сообщений. Помните, это все равно что писать код самостоятельно, но быстрее. Вы можете посмотреть на этот вывод, перейдя в /blog/public/admin/posts :

Posts - Admin Generated code

Мы добавили Controller_Base которая будет содержать логику для всего вашего приложения, поэтому каждый контроллер может расширяться от этого. Файл просто содержит:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
abstract class Controller_Base extends Controller_Template {
 
    public function before()
    {
        parent::before();
         
        // Assign current_user to the instance so controllers can use it
        $this->current_user = Auth::check() ?
         
        // Set a global variable so views can use it
        View::set_global(‘current_user’, $this->current_user);
    }
 
}

Расширяя Controller_Template , все представления будут автоматически оборачиваться шаблоном. Затем в функции before() мы делаем небольшую логику, чтобы получить текущего пользователя и сделать его доступным как $this->current_user в контроллерах и $current_user в представлениях.

Будет создан еще один контроллер с именем Controller_Admin который расширяет Controller_Base , поэтому, помимо того, что текущий пользователь собирается, мы можем проверить, действительно ли пользователь является администратором:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
abstract class Controller_Admin extends Controller_Base {
 
    public $template = ‘admin/template’;
 
    public function before()
    {
        parent::before();
 
        if ( ! Auth::member(100) and Request::active()->action != ‘login’)
        {
            Response::redirect(‘admin/login’);
        }
    }
 
    // ….
         
}

Вы заметите, что этот контроллер устанавливает собственный шаблон, поэтому вместо поиска fuel/app/views/template.php он будет искать fuel/app/views/admin/template.php . Затем, если пользователь не соответствует member(100) — идентификатору группы администраторов, установленному ранее, — он будет отправлен со страницы входа в систему.

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

Controller_Admin_Posts расширяет Controller_Admin . Это означает, что он содержит такую ​​же проверку before() и поэтому защищен так же, как и любой другой контроллер в вашей панели администратора.

Генерация кода — это только первый шаг в работе над приложением. Нам все еще нужно настроить наши формы и создать интерфейс. Например, если вы создадите или отредактируете сообщение, оно user_id поле user_id в виде текстового поля.


Мы собираемся изменить наш action_create() в fuel/app/classes/admin/posts.php чтобы у нас был список доступных пользователей. Для этого мы можем заменить метод следующим кодом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public function action_create($id = null)
{
    $view = View::forge(‘admin/posts/create’);
 
    if (Input::method() == ‘POST’)
    {
        $post = Model_Post::forge(array(
            ‘title’ => Input::post(‘title’),
            ‘slug’ => Inflector::friendly_title(Input::post(‘title’), ‘-‘, true),
            ‘summary’ => Input::post(‘summary’),
            ‘body’ => Input::post(‘body’),
            ‘user_id’ => Input::post(‘user_id’),
        ));
 
        if ($post and $post->save())
        {
            Session::set_flash(‘success’, ‘Added post #’.$post->id.’.’);
            Response::redirect(‘admin/posts’);
        }
 
        else
        {
            Session::set_flash(‘error’, ‘Could not save post.’);
        }
    }
 
    // Set some data
    $view->set_global(‘users’, Arr::assoc_to_keyval(Model_User::find(‘all’), ‘id’, ‘username’));
 
    $this->template->title = «Create Post»;
    $this->template->content = $view;
}

Это то же самое, что и предыдущий код с двумя изменениями:

1
$view = View::forge(‘admin/posts/create’);

Это создает новый объект View. Мы можем назначить свойства этому представлению, установив их как свойства, чтобы данные наших пользователей можно было легко передавать и, как правило, работать примерно так:

1
$view->users = array(1 => «User 1», 2 => «User 2»);

Теперь мы делаем аналогичное обновление для action_edit() :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public function action_edit($id = null)
{
    $view = View::forge(‘admin/posts/edit’);
     
    $post = Model_Post::find($id);
 
    if (Input::method() == ‘POST’)
    {
        $post->title = Input::post(‘title’);
        $post->slug = Inflector::friendly_title(Input::post(‘title’), ‘-‘, true);
        $post->summary = Input::post(‘summary’);
        $post->body = Input::post(‘body’);
        $post->user_id = Input::post(‘user_id’);
 
        if ($post->save())
        {
            Session::set_flash(‘success’, ‘Updated post #’ . $id);
            Response::redirect(‘admin/posts’);
        }
 
        else
        {
            Session::set_flash(‘error’, ‘Could not update post #’ . $id);
        }
    }
 
    else
    {
        $this->template->set_global(‘post’, $post, false);
    }
     
    // Set some data
    $view->set_global(‘users’, Arr::assoc_to_keyval(Model_User::find(‘all’), ‘id’, ‘username’));
 
    $this->template->title = «Edit Post»;
    $this->template->content = $view;
}

Однако, поскольку представления create.php и edit.php разделяют частичную тему _form.php темы, а свойства устанавливают переменные только для этого конкретного представления, нам необходимо использовать метод View::set_global() :

1
$view->set\_global(‘users’, Arr::assoc_to_keyval(Model\_User::find(‘all’), ‘id’, ‘username’));

Он использует объект Model_User чтобы получить всех наших пользователей, а затем объединяет их в ассоциативный массив для нашей формы.

Теперь необходимо изменить HTML- user_id , поэтому удалите div-оболочку «slug» — мы сделаем это сами и изменим поле user_id поля ввода на поле выбора:

1
2
3
4
5
6
7
8
<div class=»clearfix»>
    <?php echo Form::label(‘User’, ‘user_id’);
 
    <div class=»input»>
        <?php echo Form::select(‘user_id’, Input::post(‘user_id’, isset($post) ? $post->user_id : $current_user->id), $users, array(‘class’ => ‘span6’));
 
    </div>
</div>
User dropdown form

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

Создать базовый веб-интерфейс очень просто, поэтому не стоит беспокоиться об использовании кода.

Создайте новый контроллер fuel/app/classes/controller/blog.php :

01
02
03
04
05
06
07
08
09
10
11
12
class Controller_Blog extends Controller_Base
{
    public function action_index()
    {
        $view = View::forge(‘blog/index’);
         
        $view->posts = Model_Post::find(‘all’);
         
        $this->template->title = ‘My Blog about Stuff’;
        $this->template->content = $view;
    }
}

И файл fuel/app/views/blog/index.php :

1
2
3
4
5
6
7
8
9
<h2>Recent Posts</h2>
 
<?php foreach ($posts as $post): ?>
 
    <h3><?php echo Html::anchor(‘blog/view/’.$post->slug, $post->title) ?></h3>
     
    <p><?php echo $post->summary ?></p>
 
<?php endforeach;

Это простой цикл через массив $posts который содержит все ваши статьи.

Comment form

Цикл foreach, гиперссылка и сводка — все, что нам нужно для этого файла представления, и мы создадим другой файл представления, чтобы фактически увидеть сообщение. Мы вызовем этот метод контроллера action_view() и view.php файл представления с именем view.php :

1
2
3
4
5
<h2><?php echo $post->title ?></h2>
 
<p><strong>Posted: </strong><?php echo date(‘nS F, Y’, $post->created_at) ?> (<?php echo Date::time_ago($post->created_at)?>)</p>
 
<p><?php echo nl2br($post->body) ?></p>

Это метод для контроллера блога:

1
2
3
4
5
6
7
8
9
public function action_view($slug)
{
    $post = Model_Post::find_by_slug($slug);
     
    $this->template->title = $post->title;
    $this->template->content = View::forge(‘blog/view’, array(
        ‘post’ => $post,
    ));
}

Метод find_by_slug() — это «магический метод», который будет строить WHERE slug = "foo" в вашем запросе и возвращать один экземпляр Model_Post с Model_Post данными.

Comment form

Теперь люди могут заглянуть на ваш ужасно непристойный веб-сайт и посмотреть базовый блог, а у вас есть интерфейс администратора для управления им!


До сих пор мы использовали ORM для наших моделей для создания базового CRUD, но мы еще не видели ничего общего с отношениями. ORM делает это невероятно простым, так как, по какой-то причине, это означает «объектно-реляционное сопоставление». Чтобы установить отношения, все, что нам нужно сделать, это немного изменить наши модели, чтобы объяснить, как ORM должен связывать данные.

Пост создается одним пользователем, поэтому мы говорим, что он принадлежит пользователю. В Model_Post мы можем добавить:

1
protected static $_belongs_to = array(‘user’);

Пользователь может публиковать несколько блогов, поэтому мы добавим эту строку:

1
protected static $_has_many = array(‘posts’);

Быстрый способ проверить это работает, запустив масляную консоль:

1
2
3
4
5
Fuel 1.1-rc2 — PHP 5.3.6 (cli) (Sep 8 2011 19:31:33) [Darwin]
>>> $post = Model_Post::find(‘first’);
>>> $post->user->username
admin
— Ctrl + C to exit

Здорово, отношения работают!

Теперь в представлении мы можем работать с $post->user и выводить его имя, поэтому давайте изменим fuel/app/views/blog/view.php :

1
2
3
4
5
6
7
8
<h2><?php echo $post->title ?></h2>
 
<p>
    <strong>Posted: </strong><?php echo date(‘nS F, Y’, $post->created_at) ?> (<?php echo Date::time_ago($post->created_at)?>)
    by <?php echo $post->user->username ?>
</p>
 
<p><?php echo nl2br($post->body) ?></p>

Делать вещи таким способом называется ленивой загрузкой . В основном происходит то, что когда вы запрашиваете $post->user ORM возвращает объект пользователя на основе содержимого поля user_id . Это значит получить сообщение, и первый пользователь получит два запроса, второй получит третий, и т. Д., Поэтому все эти дополнительные запросы могут оказаться очень медленными.

Чтобы повысить производительность, вы можете переключиться с отложенной загрузки на активную загрузку, которая в основном говорит ORM, что вы собираетесь присоединиться к пользователям, поэтому он должен сделать это как часть первого запроса. Это может сделать для одного более крупного запроса, но ORM хорошо подрежет его для вас, и вы не заметите разницу.

1
$post = Model_Post::find_by_slug($slug, array(‘related’ => array(‘user’)));

Если вы посмотрите на запрос, который производит ORM, он будет примерно таким:

1
SELECT <code>t0</code>.<code>id</code> AS <code>t0_c0</code>, <code>t0</code>.<code>title</code> AS <code>t0_c1</code>, <code>t0</code>.<code>slug</code> AS <code>t0_c2</code>, <code>t0</code>.<code>summary</code> AS <code>t0_c3</code>, <code>t0</code>.<code>body</code> AS <code>t0_c4</code>, <code>t0</code>.<code>user_id</code> AS <code>t0_c5</code>, <code>t0</code>.<code>created_at</code> AS <code>t0_c6</code>, <code>t0</code>.<code>updated_at</code> AS <code>t0_c7</code>, <code>t1</code>.<code>id</code> AS <code>t1_c0</code>, <code>t1</code>.<code>username</code> AS <code>t1_c1</code>, <code>t1</code>.<code>password</code> AS <code>t1_c2</code>, <code>t1</code>.<code>group</code> AS <code>t1_c3</code>, <code>t1</code>.<code>email</code> AS <code>t1_c4</code>, <code>t1</code>.<code>last_login</code> AS <code>t1_c5</code>, <code>t1</code>.<code>login_hash</code> AS <code>t1_c6</code>, <code>t1</code>.<code>profile_fields</code> AS <code>t1_c7</code>, <code>t1</code>.<code>created_at</

Сначала это может выглядеть безумно, но ORM точно знает, что происходит. Используя этот подход в прошлом, я сократил приложение с 300+ запросов на загруженной странице (очень медленно) до примерно 2 (очень быстро).


Множество уроков по созданию блога останавливаются до того, как они попадают в комментарии, которые, как мне кажется, являются серьезным недоразумением. Каждый блог нуждается в комментариях, и мы хотим быстро их добавить, чтобы мы могли заняться чем-то более увлекательным, чтобы мы могли использовать генерацию кода для создания интерфейса администратора:

01
02
03
04
05
06
07
08
09
10
11
12
$ oil generate admin comments name:string email:string website:string message:text post_id:int
    Creating migration: /Users/phil/Sites/blog/fuel/app/migrations/003_create_comments.php
    Creating model: /Users/phil/Sites/blog/fuel/app/classes/model/comment.php
    Creating controller: /Users/phil/Sites/blog/fuel/app/classes/controller/admin/comments.php
    Creating view: /Users/phil/Sites/blog/fuel/app/views/admin/comments/index.php
    Creating view: /Users/phil/Sites/blog/fuel/app/views/admin/comments/view.php
    Creating view: /Users/phil/Sites/blog/fuel/app/views/admin/comments/create.php
    Creating view: /Users/phil/Sites/blog/fuel/app/views/admin/comments/edit.php
    Creating view: /Users/phil/Sites/blog/fuel/app/views/admin/comments/_form.php
 
$ oil refine migrate
Migrated app:default to latest version: 3.

Комментарии будут нуждаться в некоторых подобных настройках, как это сделал Post, поэтому мы устанавливаем отношения.

Model_User

1
2
protected static $_has_many = array(‘posts’, ‘comments’);
protected static $_belongs_to = array(‘user’);

Model_Post

1
2
protected static $_belongs_to = array(‘user’);
protected static $_has_many = array(‘comments’);

Model_Comment

1
protected static $_belongs_to = array(‘post’, ‘user’);

Добавьте комментарий через интерфейс обманным путем, перейдя по http://localhost/blog/public/admin/comments/create и введя его.

Comment admin

Теперь мы можем снова проверить отношения в консоли:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
Fuel 1.1-rc2 — PHP 5.3.6 (cli) (Sep 8 2011 19:31:33) [Darwin]
>>> Model_Post::find(1)->comments
array (
  1 =>
  Model_Comment::__set_state(array(
   ‘_is_new’ => false,
   ‘_frozen’ => false,
   ‘_data’ =>
  array (
  ‘id’ => ‘1’,
  ‘name’ => ‘Phil Sturgeon’,
  ’email’ => ’[email protected]’,
  ‘website’ => ‘http://philsturgeon.co.uk/’,
  ‘message’ => ‘This is an epic article.’,
  ‘post_id’ => ‘1’,
  ‘created_at’ => ‘1322931744’,
  ‘updated_at’ => ‘1322931744’,
  ),
   ‘_original’ =>
  array (
  ‘id’ => ‘1’,
  ‘name’ => ‘Phil Sturgeon’,
  ’email’ => ’[email protected]’,
  ‘website’ => ‘http://philsturgeon.co.uk/’,
  ‘message’ => ‘This is an epic article.’,
  ‘post_id’ => ‘1’,
  ‘created_at’ => ‘1322931744’,
  ‘updated_at’ => ‘1322931744’,
  ),
   ‘_data_relations’ =>
  array (
  ),
   ‘_original_relations’ =>
  array (
  ),
   ‘_view’ => NULL,
   ‘_iterable’ =>
  array (
  ),
  )),
)

Вывод массива объектов ORM немного многословен, но по крайней мере мы можем видеть данные. Это означает, что отношения работают хорошо, поэтому давайте action_view() запрос ORM в action_view() контроллеров блога, action_view() комментарии:

1
$post = Model_Post::find_by_slug($slug, array(‘related’ => array(‘user’, ‘comments’)));

Теперь обновите представление блога, чтобы вывести комментарии и добавить форму:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<h2><?php echo $post->title ?></h2>
 
<p>
    <strong>Posted: </strong><?php echo date(‘nS F, Y’, $post->created_at) ?> (<?php echo Date::time_ago($post->created_at)?>)
    by <?php echo $post->user->username ?>
</p>
 
<p><?php echo nl2br($post->body) ?></p>
 
<hr />
 
<h3 id=»comments»>Comments</h3>
 
<?php foreach ($post->comments as $comment): ?>
 
    <p><?php echo Html::anchor($comment->website, $comment->name) ?> said «<?php echo $comment->message?>»</p>
 
<?php endforeach;
 
<h3>Write a comment</h3>
 
<?php echo Form::open(‘blog/comment/’.$post->slug) ?>
 
<div class=»row»>
    <label for=»name»>Name:</label>
    <div class=»input»><?php echo Form::input(‘name’);
</div>
 
<div class=»row»>
    <label for=»website»>Website:</label>
    <div class=»input»><?php echo Form::input(‘website’);
</div>
 
<div class=»row»>
    <label for=»email»>Email:</label>
    <div class=»input»><?php echo Form::input(’email’);
</div>
 
<div class=»row»>
    <label for=»message»>Comment:</label>
    <div class=»input»><?php echo Form::textarea(‘message’);
</div>
 
<div class=»row»>
    <div class=»input»><?php echo Form::submit(‘submit’);
</div>
 
<?php echo Form::close() ?>

Этот код выведет все комментарии в очень простом стиле, за которым последует очень простая форма с использованием разметки Twitter Bootstrap. Я уверен, что вы можете сделать несколько стилей для раздела комментариев.

Comment form

Мы видим, что выводится комментарий, и все добавленные комментарии также будут вставлены. Поэтому следующим и последним этапом процесса является сохранение комментариев.

Строка с Form::open('blog/comment/'.$post->slug) установит действие в blog/comment/women-love-guys-who-use-fuelphp что означает, что Controller_Blog нужен новый метод action_comment($slug) который должен выглядеть примерно так:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public function action_comment($slug)
{
    $post = Model_Post::find_by_slug($slug);
     
    // Lazy validation
    if (Input::post(‘name’) AND Input::post(’email’) AND Input::post(‘message’))
    {
        // Create a new comment
        $post->comments[] = new Model_Comment(array(
            ‘name’ => Input::post(‘name’),
            ‘website’ => Input::post(‘website’),
            ’email’ => Input::post(’email’),
            ‘message’ => Input::post(‘message’),
            ‘user_id’ => $this->current_user->id,
        ));
         
        // Save the post and the comment will save too
        if ($post->save())
        {
            $comment = end($post->comments);
            Session::set_flash(‘success’, ‘Added comment #’.$comment->id.’.’);
        }
        else
        {
            Session::set_flash(‘error’, ‘Could not save comment.’);
        }
         
        Response::redirect(‘blog/view/’.$slug);
    }
     
    // Did not have all the fields
    else
    {
        // Just show the view again until they get it right
        $this->action_view($slug);
    }
}

В этой статье пропущено несколько вещей, например, как настроить симпатичный URL вместо localhost / blog / public и как использовать проверку формы в модели или контроллере, но все это можно найти в документации FuelPHP. Я планировал коснуться таких вещей, как «Загрузка файлов» и «Миграция», но опять же, все это уже задокументировано.

Теперь у вас должно быть достаточно кода, чтобы его можно было отделить и поиграть, и у любого проекта, над которым вы работаете с FuelPHP, уже есть блог, поэтому создайте заставку, создайте ее, и вы готовы сделать следующую книгу SquareFaceTwitBook.