Создание контроллера в Laravel

Создание миграции в Laravel

Давайте создадим миграцию create_articles_table, которая будет создавать таблицу в базе данных articles с полями:

  • id – индегтификатор
  • title – заголовок статьи
  • text – текст статьи
  • created_at – дата создания статьи
  • updated_at – дата обновления статьи

Для этого выполним в консоли следующую команду:

php artisan make:migration create_articles_table --create=articles

Создание миграции в Laravel

Теперь в метод up нашей только что созданной миграции (database/migrations/<дата_создания>_<id-миграции>_create_articles_table.php) добавим следующий код:

public function up()

{

Schema::create('articles', function (Blueprint $table) {

$table->increments('id');

$table->string('title');

$table->text('text');

$table->timestamps();

});

}

И запускаем процесс миграции:

php artisan migrate

Выполнение процесса миграции

Отлично, миграция выполнена. Если перейдем в нашу базу данных, то увидим, что создана (помимо таблиц: migrations, password_resets и users) таблица articles.

Создание модели в Laravel

Теперь нам нужно создать модель для работы с нашей таблицей articles. Для этого выполним в консоли следующую команду:

php artisan make:model Article

Создание модели с помощью artisan

И добавим в нашу модель (app/Article.php) следующий код:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Article extends Model

{

protected $fillable = [

'title', 'text'

];

}

Создание контроллера в Laravel

Теперь давайте создадим контроллер ресурсов:

php artisan make:controller ArticleController --resource

Создание контроллера с помощью artisan

Добавим роуты к этому контроллеру. Открываем файл routes/web.php и добавляем:

Route::resource('/article', 'ArticleController',['only' => ['index', 'store', 'show', 'destroy']]);

И давайте в методе index контроллера ArticleController добавим для теста:

public function index()

{

return "INDEX";

}

Перейдем <домен>/article. В моем случае это http://lara.loc/article

проверка роута для контроллера ресурсов

Отлично, работает.

Вывод всех статей.

За вывод всех статей отвечает метод index контроллера ArticleController. Давайте опишем его:

public function index()

{

$articles = Article::all(['id','title']);

return view('index',['articles' => $articles]);

}

Мы получаем все записи из таблицы articles (но получаем только поля id и title) и передаем все в шаблон index.blade.php и не забываем добавить:

use App\Article;

Давайте создадим шаблон index.blade.php в каталоге resources/view и поместим в него следующий код:

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="utf-8">

<meta http-equiv="X-UA-Compatible" content="IE=edge">

<meta name="viewport" content="width=device-width, initial-scale=1">

<meta name="csrf-token" content="{{ csrf_token() }}">

<title>Список статей</title>

<!-- Bootstrap -->

<link href="{{ asset('css/bootstrap.min.css') }}" rel="stylesheet">

<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->

<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->

<!--[if lt IE 9]>

<script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>

<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>

<![endif]-->

</head>

<body>

<div class="container">

<h1>Список статей</h1>

<div class='row'>

<button type="button" class="btn btn-primary btn-lg pull-right" data-toggle="modal" data-target="#addArticle">

Добавить статью

</button>

</div>

<br />

<div class='row @if(count($articles)!= 0) show @else hidden @endif' id='articles-wrap'>

<table class="table table-striped ">

<thead>

<tr>

<th>ID</th>

<th>Заголовок</th>

<th></th>

</tr>

</thead>

<tbody>

@foreach($articles as $article)

<tr>

<td>{{ $article->id }}</td>

<td><a href="{{ route('article.show', ['id' => $article->id]) }}">{{ $article->title }}</a></td>

<td><a href="" class="delete" data-href=" {{ route('article.destroy',$article->id) }} ">Удалить</a></td>

</tr>

@endforeach

</tbody>

</table>

</div>

<div class="row">

<div class="alert alert-warning @if(count($articles) != 0) hidden @else show @endif" role="alert"> Записей нет</div>

</div>

</div>

<!-- Modal -->

<div class="modal fade" id="addArticle" tabindex="-1" role="dialog" aria-labelledby="addArticleLabel">

<div class="modal-dialog" role="document">

<div class="modal-content">

<div class="modal-header">

<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>

<h4 class="modal-title" id="addArticleLabel">Добавление статьи</h4>

</div>

<div class="modal-body">

<div class="form-group">

<label for="title">Заголовок</label>

<input type="text" class="form-control" id="title">

</div>

</div>

<div class="modal-body">

<div class="form-group">

<label for="text">Текст</label>

<textarea class="form-control" id="text"></textarea>

</div>

</div>

<div class="modal-footer">

<button type="button" class="btn btn-default" data-dismiss="modal">Закрыть</button>

<button type="button" class="btn btn-primary">Сохранить</button>

</div>

</div>

</div>

</div>

<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>

<!-- Include all compiled plugins (below), or include individual files as needed -->

<script src="{{ asset('js/bootstrap.min.js') }}"></script>

</body>

</html>

Проверяем, что получилось.

Вывод списка статей

Все работает. У нас записей в таблице пока нет. Давайте реализуем метод добавления статьи.

Добавление статьи с помощью ajax запроса

На странице со списком статей у нас есть кнопка, при нажатии на которую появляется модальное окно.

Добавление статьи

В данном окне мы вводим данные новой статьи. А при нажатии кнопки «Сохранить» передаем данные с помощью ajax для сохранения.

Модальное окно для добавления статьи

Давайте напишем JavaScript, который при клике по «Сохранить» будет отправлять ajax запрос на адрес <домен>/article (в моем случае http://lara.loc/article), а данные передавать методом POST.

Первое, что сделаем – это добавим к кнопке «Сохранить» id=«save». И напишем небольшой код на JavaScript. В конце файла index.blade.php, после подключения скриптов, добавим:

<script>

$(function() {

$('#save').on('click',function(){

var title = $('#title').val();

var text = $('#text').val();

$.ajax({

url: '{{ route('article.store') }}',

type: "POST",

data: {title:title,text:text},

headers: {

'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')

},

success: function (data) {

$('#addArticle').modal('hide');

$('#articles-wrap').removeClass('hidden').addClass('show');

$('.alert').removeClass('show').addClass('hidden');

var str = '<tr><td>'+data['id']+

'</td><td><a href="/article/'+data['id']+'">'+data['title']+'</a>'+

'</td><td><a href="/article/'+data['id']+'" class="delete" data-delete="'+data['id']+'">Удалить</a></td></tr>';

$('.table > tbody:last').append(str);

},

error: function (msg) {

alert('Ошибка');

}

});

});

})

</script>

Думаю, что код пояснять не нужно. Просто тут мы передаем методом POST две переменные title и text на адрес, который определяем по имени роута.

Теперь давайте опишем метод контроллера, который вызывается этим роутом (в нашем случае это контроллер ArticleController и метод store). Добавим в метод store следующий код:

$res = Article::create(['title' => $request->title, 'text' => $request->text]);

$data = ['id' => $res->id, 'title' => $request->title, 'text' => $request->text];

return $data;

Можем проверять. Давайте создадим первую статью.

Статья добавлена с помощью AJAX запроса

Статья добавлена. Если мы откроем нашу таблицу в базе данных, то увидим запись.

Давайте реализуем просмотр статьи.

Просмотр статьи

Для просмотра статьи у нас есть метод show контроллера ArticleController, давайте добавим следующий код:

public function show($id)

{

$article = Article::find($id);

return view('show',['article' => $article]);

}

Мы в базе ищем статью по ее id, и все возвращаем в шаблон show.blade.php. Давайте создадим шаблон show.blade.php и добавим в него следующий код. (Напомню, что шаблон, в нашем случае, должен находиться в resources/view)

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="utf-8">

<meta http-equiv="X-UA-Compatible" content="IE=edge">

<meta name="viewport" content="width=device-width, initial-scale=1">

<meta name="csrf-token" content="{{ csrf_token() }}">

<title>{{ $article->title }}</title>

<!-- Bootstrap -->

<link href="{{ asset('css/bootstrap.min.css') }}" rel="stylesheet">

<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->

<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->

<!--[if lt IE 9]>

<script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>

<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>

<![endif]-->

</head>

<body>

<div class="container">

<div class="panel panel-default">

<div class="panel-heading">

<h3 class="panel-title">{{ $article->title }}</h3>

</div>

<div class="panel-body">

{{ $article->text }}

</div>

</div>

</div>

</body>

</html>

Давайте проверим. На странице со списком статей кликаем по ссылке с названием статьи:

Просмотр статьи

Отлично. По нашей задаче осталось реализовать только удаление статьи.

Удаление статьи методом ajax.

За удаление статьи у нас отвечает метод destroy контроллера ArticleController. Давайте опишем этот метод.

public function destroy ($ id)
{
Article::find ($id)->delete();
return 'ok';
}

Теперь в шаблоне index.blade.php нам необходимо реализовать javascript, который будет передавать ajax данные методу для удаления. Но данные передаются методом DELETE.

Давайте приступим к реализации.

Добавим в секцию <script> следующий скрипт:

$('body').on('click','.delete',function(e){

e.preventDefault();

var url = $(this).data('href');

var el = $(this).parents('tr');

$.ajax({

url: url,

type: "POST",

headers: {

'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')

},

success: function (data) {

el.detach();

},

error: function (msg) {

alert('Ошибка');

}

});

});

Давайте проверим, что у нас получилось. Добавим еще несколько статей и попробуем их удалить.

Отлично все работает.

Заключение.

Мы свами на практике реализовали ajax запросы в Laravel. Создали контроллер ресурсов, в котором  реализовали создание статьи по ajax запросу, просмотр статьи (обычный get запрос) и удаление статьи ajax запросом.

Да, при добавлении статьи мы могли к полю text подключить WYSIWYG, как это сделать описано в статье «Подключаем текстовый (wysiwyg) редактор к Laravel», также мы не сделали валидацию при добавлении статей. Но цель статьи была не в этом и цель мы достигли: использование AJAX запросов в Laravel.