Всем привет! Продолжаем серию авторских публикаций в преддверии старта курса «Framework Laravel». В прошлой статье мы с вами посмотрели на теоретические основы Laravel. Однако теорию любого фреймворка можно изучать достаточно долго и ничего не понять, пока сам не напишешь ничего на практике.

Поэтому давайте мы с вами напишем приложение, в котором каждому пользователю можно будет авторизовываться, создавать новые альбомы и загружать туда фотографии. Если вы не знаете пока, что такое MVC, почитайте это , скоро вам предстоит воспользоваться этим на практике.
Подобного рода гайды начинаются с объяснения, как настроить свое окружение и т.д. Проблема в том, что на каждой платформе оно разное, но хочется, чтобы статья была интересна всем. Я просто дам ссылки на необходимое, а вы постараетесь поставить и настроить это самостоятельно.
Итак, нам потребуется:

Composer. Для тех, кто в танке, Composer это менеджер пакетов для PHP (да, как npm для JavaScript). Скачать его можно здесь .
Сам Laravel. Здесь есть несколько самых популярных вариантов: Homestead и Valet (и на самом деле множество других). Однако, последний подходит только для Mac OS. Технически, читатель может воспользоваться любой любимой сборкой, лишь бы она соответствовала этим требованиям.
И малозаметная деталь, но Node.js нам тоже понадобится для установки npm пакетов.
Выполняем команду:
Не забудьте поместить каталог
Итак, хороший проект начинается с понятного ТЗ. Давайте попробуем сформулировать основные требования к нашему несложному приложению:

У пользователя есть возможность загружать фотографии на сайт в созданные им самими альбомы. Он может зарегистрироваться, и может авторизоваться. База данных — MySQL. Фреймворк, который используется для упрощения процесса верстки — Bootstrap, как самый распространённый фреймворк для верстки.
Первое действие, которое вы совершаете сразу после создания — это подключение базы данных. Если вы пока плохо понимаете, как установить и запустить свою базу данных, воспользуйтесь готовыми desktop-решениями от корпорации Зла: здесь и здесь. Этого поначалу будет достаточно.
Итак, все готово. Проходим в свою любимую директорию и начинаем проект с
Далее нужно подключить нашу базу данных. Для этого проходим в MySQL Branch создаем новую базу данных gallery (не забудьте настроить Сharacter Set на utf-8, и Сollation на

Далее проходим в файл
После этого мы сможем сделать миграцию наших баз данных.
Если вы правильно настроили ваше подключение в
Как мы с вами договорились на т/з, у нас будет процесс авторизации, регистрации, а также у пользователя будет возможность создавать альбомы и загружать туда фотографии. Для реализации всего нам потребуются соответствующие таблицы в базе данных.
Итак, с чего начинается бэкэнд? С создания таблицы в нашей базе данных. Эта команда в терминале создаст нам возможность совершить миграцию в базу данных:
Итак, нам нужно определить, какие у нас должны быть колонки в нашей таблице. Это нужно сделать в файле, который создался у вас за счет последней миграции. Он находится в вашем проекте в папке
Не забудьте сделать
Теперь вкладка вашей базы данных в MySQL Branch должна принять следующий вид:

Итак, мы создали нашу базу данных, теперь нам нужно связать нашу базу данных с моделью Eloquen, которая и будет взаимодействовать с нашей базой данных.

Теперь нам нужно создать модель Eloquent ORM. Если вы не понимаете, как мы так быстро перешли от одного к другому, вам стоит почитать вот это. Воспользуемся для генерации шаблона модели все тем же помощником Artisan:
php artisan make:model Album
Далее мы проходим в
Здорово! Наша модель альбома готова, теперь можно заняться нашими изображениями. Здесь процесс повторится вновь:
Идем редактировать нашу миграцию:
И снова делаем миграцию:
Надеюсь, ваша миграция удалась! Однако нам нужно объяснить ещё одну вещь, которую слишком долго было бы расписывать в комментариях: мы использовали ключ
Пора создать и модель, которая будет работать с таблицей images. Надеюсь, вы уже догадываетесь что делать:
Шаблон создан, идем в
Здесь тоже все должно быть понятно:
Наша модель Image готова. Теперь нам потребуется контроллер для создания альбомов в нашей базе данных.
Что бы сохранять, показывать и удалять в нашем альбоме, нам нужны некоторые функции в нашем контроллере. Но для начала нужен сам контроллер:
Заходим в
Далее нам предстоит заняться переопределением наших путей. Для тех, кто не знает, роутинг — это настройка путей, которые показываются пользователю в браузере, и действий, которое должно совершать наше приложение. Мы заходим в файл
На этом на сегодня все! Это, понятное дело, только первая часть нашего приложения. Всем спасибо за внимание, в следующей части дополним наши
Полезные ссылки:
Документация на русском языке
Полезный гайд на английском, который лучше, чем в документации объясняет как работает наследование и расширение Blade-шаблонов
Множество полезной информации и практических примеров создания приложений

Поэтому давайте мы с вами напишем приложение, в котором каждому пользователю можно будет авторизовываться, создавать новые альбомы и загружать туда фотографии. Если вы не знаете пока, что такое MVC, почитайте это , скоро вам предстоит воспользоваться этим на практике.
Подобного рода гайды начинаются с объяснения, как настроить свое окружение и т.д. Проблема в том, что на каждой платформе оно разное, но хочется, чтобы статья была интересна всем. Я просто дам ссылки на необходимое, а вы постараетесь поставить и настроить это самостоятельно.
Итак, нам потребуется:

Composer. Для тех, кто в танке, Composer это менеджер пакетов для PHP (да, как npm для JavaScript). Скачать его можно здесь .
Сам Laravel. Здесь есть несколько самых популярных вариантов: Homestead и Valet (и на самом деле множество других). Однако, последний подходит только для Mac OS. Технически, читатель может воспользоваться любой любимой сборкой, лишь бы она соответствовала этим требованиям.
И малозаметная деталь, но Node.js нам тоже понадобится для установки npm пакетов.
Выполняем команду:
composer global require laravel/installer для установки Laravel.Не забудьте поместить каталог
$Home/.composer/vendor/bin (или его эквивалент в вашей ОС) в вашу переменную PATH, чтобы команда Laravel заработала в вашей системе.Итак, хороший проект начинается с понятного ТЗ. Давайте попробуем сформулировать основные требования к нашему несложному приложению:

У пользователя есть возможность загружать фотографии на сайт в созданные им самими альбомы. Он может зарегистрироваться, и может авторизоваться. База данных — MySQL. Фреймворк, который используется для упрощения процесса верстки — Bootstrap, как самый распространённый фреймворк для верстки.
Первое действие, которое вы совершаете сразу после создания — это подключение базы данных. Если вы пока плохо понимаете, как установить и запустить свою базу данных, воспользуйтесь готовыми desktop-решениями от корпорации Зла: здесь и здесь. Этого поначалу будет достаточно.
Итак, все готово. Проходим в свою любимую директорию и начинаем проект с
laravel new gallery
Далее нужно подключить нашу базу данных. Для этого проходим в MySQL Branch создаем новую базу данных gallery (не забудьте настроить Сharacter Set на utf-8, и Сollation на
utf_general_ci для избежания проблем с русским языком). 
Далее проходим в файл
.ENV и настраиваем подобное подключение, не забыв поменять переменные на свое имя пользователя и пароль:DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=gallery DB_USERNAME=pavel DB_PASSWORD=
После этого мы сможем сделать миграцию наших баз данных.
php artisan migrate
Если вы правильно настроили ваше подключение в
.ENV, то у вас все должно сработать.Как мы с вами договорились на т/з, у нас будет процесс авторизации, регистрации, а также у пользователя будет возможность создавать альбомы и загружать туда фотографии. Для реализации всего нам потребуются соответствующие таблицы в базе данных.
Создаем таблицу albums
Итак, с чего начинается бэкэнд? С создания таблицы в нашей базе данных. Эта команда в терминале создаст нам возможность совершить миграцию в базу данных:
php artisan make:migration CreateAlbumsTable
Итак, нам нужно определить, какие у нас должны быть колонки в нашей таблице. Это нужно сделать в файле, который создался у вас за счет последней миграции. Он находится в вашем проекте в папке
gallery/database/migrations и название у него связано со временем его создания. Его нужно отредактировать следующим образом:<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateAlbumsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('albums', function(Blueprint $table) { $table->increments('id')->unsigned(); $table->string('name'); //имя нашего альбома $table->text('description'); // описание нашего альбома $table->string('cover_image'); //картинка на превью $table->timestamps(); // дата создания. Необязательно ее показывать, но может быть полезна }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('albums'); } }
Не забудьте сделать
php artisan migrate
Теперь вкладка вашей базы данных в MySQL Branch должна принять следующий вид:

Итак, мы создали нашу базу данных, теперь нам нужно связать нашу базу данных с моделью Eloquen, которая и будет взаимодействовать с нашей базой данных.
Создаем модель Album

Теперь нам нужно создать модель Eloquent ORM. Если вы не понимаете, как мы так быстро перешли от одного к другому, вам стоит почитать вот это. Воспользуемся для генерации шаблона модели все тем же помощником Artisan:
php artisan make:model Album
Далее мы проходим в
gallery/app/Album.php и редактируем его:<?php namespace App; use Illuminate\Database\Eloquent\Model; class Album extends Model { protected $table = 'albums'; protected $fillable = array('name','description','cover_image'); public function Photos(){ return $this->hasMany('App\Image'); } }
Таблица Images
Здорово! Наша модель альбома готова, теперь можно заняться нашими изображениями. Здесь процесс повторится вновь:
php artisan make:migration CreateImagesTable
Идем редактировать нашу миграцию:
<?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateImagesTable extends Migration { public function up() { Schema::create('images', function (Blueprint $table) { $table->increments('id'); $table->integer('album_id')->unsigned(); $table->string('image'); $table->string('description'); $table->foreign('album_id')->references('id')->on('albums')->onDelete('CASCADE')->onUpdate('CASCADE'); $table->timestamps(); }); } public function down() { Schema::dropIfExists('images'); } }
И снова делаем миграцию:
php artisan migrate
Надеюсь, ваша миграция удалась! Однако нам нужно объяснить ещё одну вещь, которую слишком долго было бы расписывать в комментариях: мы использовали ключ
foreign, чтобы связать две таблицы Albums и Images. У каждого альбома есть свои изображения, и если вы хотите удалить какой-то альбом, тогда вы наверное полагаете что и фотографии у вас тоже удалятся.Модель Image
Пора создать и модель, которая будет работать с таблицей images. Надеюсь, вы уже догадываетесь что делать:
php artisan make:model Image
Шаблон создан, идем в
gallery/app/Image.php его редактировать. Здесь тоже все должно быть понятно:
class Image extends Model { protected $table = 'images'; //сама таблица, с которой мы собираемся связываться protected $fillable = array('album_id','description','image'); //свойства }
Наша модель Image готова. Теперь нам потребуется контроллер для создания альбомов в нашей базе данных.
Создание альбома
Что бы сохранять, показывать и удалять в нашем альбоме, нам нужны некоторые функции в нашем контроллере. Но для начала нужен сам контроллер:
php artisan make:controller AlbumsController
Заходим в
gallery/app/Http/Controllers/AlbumsController.php<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Support\MessageBag; use Validator; use App\Album; class AlbumsController extends Controller { public function getList() //получение списка альбомов { $albums = Album::with('Photos')->get(); return view('index')->with('albums',$albums); } public function getAlbum($id) { $album = Album::with('Photos')->find($id); $albums = Album::with('Photos')->get(); return view('album', ['album'=>$album, 'albums'=>$albums]); } public function getForm() { return view('createalbum'); //форма создания альбома } public function postCreate(Request $request) { $rules = ['name' => 'required', 'cover_image'=>'required|image']; // нельзя создать альбом без имени и обложки $input = ['name' => null]; //валидатор мы обсудим в следующей части $validator = Validator::make($request->all(), $rules); if($validator->fails()){ return redirect()->route('create_album_form')->withErrors($validator)->withInput(); } $file = $request->file('cover_image'); $random_name = str_random(8); $destinationPath = 'albums/'; $extension = $file->getClientOriginalExtension(); $filename=$random_name.'_cover.'.$extension; $uploadSuccess = $request->file('cover_image')->move($destinationPath, $filename); $album = Album::create(array( 'name' => $request->get('name'), 'description' => $request->get('description'), 'cover_image' => $filename, )); return redirect()->route('show_album',['id'=>$album->id]); } public function getDelete($id) // возможность удаления альбома { $album = Album::find($id); $album->delete(); return Redirect::route('index'); } }
Далее нам предстоит заняться переопределением наших путей. Для тех, кто не знает, роутинг — это настройка путей, которые показываются пользователю в браузере, и действий, которое должно совершать наше приложение. Мы заходим в файл
web.php:<?php //роутинг альбомов Route::get('/', array('as' => 'index','uses' => 'AlbumsController@getList')); //получение списка альбомов на главной странице Route::get('/createalbum', array('as' => 'create_album_form','uses' => 'AlbumsController@getForm')); //создание альбома из формы Route::post('/createalbum', array('as' => 'create_album','uses' => 'AlbumsController@postCreate')); //само создание альбома Route::get('/deletealbum/{id}', array('as' => 'delete_album','uses' => 'AlbumsController@getDelete')); // удаление альбома Route::get('/album/{id}', array('as' => 'show_album','uses' => 'AlbumsController@getAlbum')); // удаление альбома //Эта часть связана с обработкой самих фотографий Route::get('/addimage/{id}', array('as' => 'add_image','uses' => 'ImageController@getForm')); //добавление изображений в форме Route::post('/addimage', array('as' => 'add_image_to_album','uses' => 'ImageController@postAdd')); //добавление изображений в сам альбом Route::get('/deleteimage/{id}', array('as' => 'delete_image','uses' => 'ImageController@getDelete')); //удаление Route::post('/moveimage', array('as' => 'move_image', 'uses' => 'ImageController@postMove'));
Здорово. Что бы наше приложение точно могло заработать, перед настройками представления вида нам нужно убедиться, что у нас есть необходимые ссылки на ярлыки (alias) необходимых нам классов в конце файлаОтлично! Теперь нам нужно определить наши представления! Проходим в папкуgallery/config/app.php. Это только технические настройки:
'aliases' => [ 'App' => Illuminate\Support\Facades\App::class, 'Artisan' => Illuminate\Support\Facades\Artisan::class, 'Auth' => Illuminate\Support\Facades\Auth::class, 'Blade' => Illuminate\Support\Facades\Blade::class, 'Broadcast' => Illuminate\Support\Facades\Broadcast::class, 'Bus' => Illuminate\Support\Facades\Bus::class, 'Cache' => Illuminate\Support\Facades\Cache::class, 'Config' => Illuminate\Support\Facades\Config::class, 'Cookie' => Illuminate\Support\Facades\Cookie::class, 'Crypt' => Illuminate\Support\Facades\Crypt::class, 'DB' => Illuminate\Support\Facades\DB::class, 'Eloquent' => Illuminate\Database\Eloquent\Model::class, 'Event' => Illuminate\Support\Facades\Event::class, 'File' => Illuminate\Support\Facades\File::class, 'Gate' => Illuminate\Support\Facades\Gate::class, 'Hash' => Illuminate\Support\Facades\Hash::class, 'Lang' => Illuminate\Support\Facades\Lang::class, 'Log' => Illuminate\Support\Facades\Log::class, 'Mail' => Illuminate\Support\Facades\Mail::class, 'Notification' => Illuminate\Support\Facades\Notification::class, 'Password' => Illuminate\Support\Facades\Password::class, 'Queue' => Illuminate\Support\Facades\Queue::class, 'Redirect' => Illuminate\Support\Facades\Redirect::class, 'Redis' => Illuminate\Support\Facades\Redis::class, 'Request' => Illuminate\Support\Facades\Request::class, 'Response' => Illuminate\Support\Facades\Response::class, 'Route' => Illuminate\Support\Facades\Route::class, 'Schema' => Illuminate\Support\Facades\Schema::class, 'Session' => Illuminate\Support\Facades\Session::class, 'Storage' => Illuminate\Support\Facades\Storage::class, 'URL' => Illuminate\Support\Facades\URL::class, 'Validator' => Illuminate\Support\Facades\Validator::class, 'View' => Illuminate\Support\Facades\View::class, 'Form' => Collective\Html\FormFacade::class, 'Html' => Collective\Html\HtmlFacade::class, ], //потому что класса FORM у вас скорее всего нет)
gallery/resources/views. Можете удалить welcome.blade.php, можете оставить, неважно. Создаем index.blade.php и подпапку includes, чтобы сложить туда повторяющиеся части view. Итак, наш index.blade.php должен принять следующий вид:@include('includes.header') <body> @include('includes.nav') <div class="container"> <div class="starter-template"> <div class="row"> @foreach($albums as $album) <div class="col-lg-3"> <div class="thumbnail" style="min-height: 514px;"> <img alt="{{$album->name}}" src="/albums/{{$album->cover_image}}"> <div class="caption"> <h3>{{$album->name}}</h3> <p>{{$album->description}}</p> <p>{{count($album->Photos)}} image(s).</p> <p>Created date: {{ date("d F Y",strtotime($album->created_at)) }} at {{date("g:ha",strtotime($album->created_at)) }}</p> <p><a href="{{route('show_album', ['id'=>$album->id])}}" class="btn btn-big btn-default">Показать галерею</a></p> </div> </div> </div> @endforeach </div> </div><!-- /.container --> </div> </body> </html>
Содержимоеincludes/header.blade.php:
<!doctype html> <html lang="ru"> <head> <meta charset="UTF-8"> <title>Мои альбомы</title> <link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0-rc1/css/bootstrap.min.css" rel="stylesheet"> <script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0-rc1/js/bootstrap.min.js"></script> <style> body { padding-top: 50px; } .starter-template { padding: 40px 15px; text-align: center; } </style> </head>
Содержимоеincludes/nav.blade.php:
<div class="navbar navbar-inverse navbar-fixed-top"> <div class="container"> <button type="button" class="navbar-toggle"data-toggle="collapse" data-target=".nav-collapse"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="/">Мои альбомы</a> <div class="nav-collapse collapse"> <ul class="nav navbar-nav"> <li><a href="{{URL::route('create_album_form')}}">Создание нового альбома</a></li> </ul> </div><!--/.nav-collapse --> </div> </div>
На этом на сегодня все! Это, понятное дело, только первая часть нашего приложения. Всем спасибо за внимание, в следующей части дополним наши
view и обсудим вопрос валидизации изображений. Полезные ссылки:
Документация на русском языке
Полезный гайд на английском, который лучше, чем в документации объясняет как работает наследование и расширение Blade-шаблонов
Множество полезной информации и практических примеров создания приложений
