#Простой пост с комментариями
##Миграции
Эта миграция для таблицы posts
:
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreatePostsTable extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
//Здесь создается таблиц 'posts'
Schema::create('posts', function(Blueprint $table)
{
//вообще движок таблицы указывать не обязательно, но на всякий случай.
$table->engine = 'InnoDB';
//increments - создает беззнаковое (unsigned),
// целочисленное(integer) поле с атрибутом AUTOINCREMENT
// беззнаковое - это как модуль числа - неположительное и не отрицательное
$table->increments('id');
//string - создаст поле varchar
$table->string('title');
// вторым параметром можно передать максимальную длину поля.
// По умолчанию она 255.
// Для "тела" поста этого явно маловато, а вот 20к вполне хватит.
$table->string('body', 20000);
// Эта хитрая команда создаст сразу два поля типа TIMESTAMP:
// created_at и updated_at
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('posts');
}
}
сформируется таблица:
id | title | body | created_at | updated_at |
---|
эта миграция для comments
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreatePostsTable extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
//тут все тоже самое
Schema::create('comments', function(Blueprint $table)
{
$table->engine = 'InnoDB';
$table->increments('id');
$table->string('text');
//здесь у нас создается целочисленное поле, а после добавляем,
// что он должно быть беззнаковым, как и id поста
$table->integer('post_id')->unsigned();
//тоже самое для пользователья
$table->integer('user_id')->unsigned();
$table->timestamps();
// Здесть мы как раз и определям внений ключ.
// Говорим, что post_id завязано на поле id в таблице posts,
// а при удаленни поста, камменты удаляются каскадно
$table->foreign('post_id')->references('id')->on('posts')->onDelete('cascade');
//здесь для пользователя тоже самое, но без каскадного удаления
$table->foreign('user_id')->references('id')->on('users');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('comments');
}
}
сформирует таблицу:
id | text | post_id | user_id | created_at | updated_at |
---|
##Модель поста
class Post extends Eloquent{
public function comments()
{
return $this->hasMany('Comment');
}
}
##Модель коммента
class Comment extends Eloquent{
public function post()
{
return $this->belongsTo('Post');
}
}
И ничего больше. Почему? Потому что:
##Роут
//для админки
Route::group(['prefix' => 'admin', 'before' => 'auth'], function()
{
Route::controller('posts', 'AdminPostController');
});
//для фронта
Route::controller('posts', 'PostController');
##Контроллер в админке
class AdminPostController extends BaseController{
public function __construct()
{
// Вообще вот это лучше вынести в базовый контроллер, чтобы не повторятся.
// Ну да пусть пока тут потусуется.
$this->beforeFilter('csrf', ['on' => 'post']);
}
// по даресу 'admin/posts' отдаст список всех постов.
public function anyIndex()
{
$posts = Post::all();
return View::make('admin.posts.list');
}
// по даресу 'admin/posts/new' отдаст страницу с формой.
public function getNew()
{
return View::make('admin.posts.new');
}
// по даресу 'admin/posts/edit/{id}' отдаст страницу с редактирования поста.
public function getEdit($id)
{
$post = Post::find($id);
return View::make('admin.posts.edit')
->with('post', $post);
}
// по адресу 'admin/posts/store' примет данные для нового поста,
// сохранит его и перенаправит назад,
// добавив к сессии сообщение "типа успех".
public function postStore()
{
$post = new Post;
$post->title = Input::get('title');
$post->body = Input:get('body');
$post->save();
return Redirect::back()->with('message', Lang::get('post.add_success'));
}
// по адресу 'admin/posts/update' примет данные для апдейта поста,
// сохранит его и перенаправит назад,
// добавив к сессии сообщение "типа успех".
public function postUpdate($id){
$post = Post::find($id);
$post->title = Input::get('title');
$post->body = Input:get('body');
$post->image = Input::get('image');
$post->save();
return Redirect::back()->with('message', Lang::get('post.update_success'));
}
// по адресу 'admin/posts/delete/' примет id поста для удаления,
// удалит и перенаправит назад,
// добавив к сессии сообщение "типа успех".
public function postDelete(){
Post::delete(Input::get('id'));
return Redirect::back()->with('message', Lang::get('post.delete_success'));
}
}
##Контроллер во фронте
class AdminPostController extends BaseController{
public function __construct()
{
$this->beforeFilter('csrf', ['on' => 'post']);
}
//по адресу '/posts' вернет список всех постов
public function anyIndex()
{
$posts = Post::orederBy('created_at', 'desc');
return View::make('front.post.list')->with('posts', $posts);
}
//по адресу '/posts/full/{id}' вернет конкретный пост с комментариями
public function anyFull($id)
{
$post = Post::with('comments')->find($id);
return View::make('front.post.full')->with('post', $post);
}
// по адресу 'posts/add-comment/{post_id} примет данные для коммента,
// добавит его к посту и перенаправит назад,
// добавив к сессии сообщение "типа успех"
public function postAddComment($id)
{
$comment = new Comment;
$comment->text = Input::get('text');
$comment->user_id = Auth::user()->id;
$comment->post_id = $id;
$comment->save();
return Redirect::back()->with('message', Lang::get('post.addComment_success'));
}
}
Есть еще фишки с автозаполнением (fill) и прочими "чтучками". Еще можно (и нужно) обрабатывать исключения. Но это уже совсем другая история. Также стоит отметить, что Джеффри не рекомендует использовать неявные роуты. Сам же я скажу, что это касается скорее больших приложений. Кроме того, роуты всегда можно переписать явным образом. Ну и кончно же, нужна валидация и много чего еще... но общая картина дана.