Статьи

Создайте базу данных с помощью Eloquent, Faker и Flysystem

В этой части мы создадим структуру базы данных. Мы создадим таблицы, используя миграции, и заполним базу данных, используя сеялки. Кроме того, вы узнаете, как получить несколько случайных изображений из LoremPixel и поместить их в файловую систему с помощью Flysystem . Вы также будете добавлять некоторые случайно сгенерированные данные, используя библиотеку Faker .
Как и в первой части, вы можете скачать код этой части с github .

Установите библиотеки

Установка очень проста с Composer .

Требуются эти проекты:

"fzaninotto/faker": "1.5.*@dev", "league/flysystem": "dev-feature/eventable-filesystem", "dropbox/dropbox-sdk": "dev-master" 

Выполните composer update и все будет установлено и обновлено гладко.

Построить структуру базы данных

До сих пор у нас был только один файл миграции. Нам нужны еще два для нашего приложения. Одна таблица, в которой будут храниться данные для фотографий, а другая — для категорий. Чтобы узнать больше об Artisan и Migrations, см. Этот пост .

 php artisan migrate:make create_photos_table php artisan migrate:make create_categories_table 

Эти две команды создают два файла миграции. Давайте начнем заполнять их некоторой схемой. Сначала мы начнем с файла миграции фотографий. Остановитесь на мгновение и подумайте, что нам нужно для этого. Ранее мы установили библиотеку flysystem.

Библиотека flysystem может обрабатывать файлы в разных местах: локальная файловая система, Dropbox, AWS3, Rackspace Cloud Files и многое другое. Нам это нужно для локальной файловой системы в нашей среде разработки, и мы должны использовать Dropbox для производства. Это почему? Heroku — это Paas (платформа как услуга), поэтому мы не имеем полного контроля над файловой системой. Доступны для записи только две директории: ./temp и ./logs . Вы можете записывать файлы только используя git для развертывания, а не в любой другой папке. Почему бы нам просто не использовать эти два каталога? Потому что они временные. Если что-то пойдет не так и Dyno перезапустится, все файлы в этих каталогах будут удалены. Работать с этими двумя каталогами небезопасно.

Если вы хотите узнать больше о flysystem, прочитайте эту статью на сайте Point of Lukas White или их документацию .

Приложение Dropbox

Прежде чем использовать flysystem и Dropbox для производства, мы должны создать приложение Dropbox, которое позволяет нам использовать их Api. Затем нам нужно сделать некоторые настройки. Если у вас еще нет учетной записи Dropbox, создайте ее, а затем вернитесь к оставшейся части статьи. Если вы используете Rackspace или AWS3, вы можете использовать любой из них. Я использую Dropbox здесь, потому что для этого не требуется кредитная карта, и она бесплатна для использования. Перейдите по ссылке и создайте приложение Dropbox. Вот как это сделать.

Create a DropBox App

Далее идут конфигурации. Мы собираемся использовать его только на производстве. Хорошая идея отделить конфигурацию от логики приложения. Создайте dropbox.php внутри /app/config или в /app/config/production .

 return array( 'token' => 'token_here', 'appName' => 'Your App Name' ); 

И для извлечения использовать:

 Config::get('dropbox.appName'); Config::get('dropbox.token'); 

Нам нужна flysystem, чтобы создать папку с изображениями (папку, в которой будут храниться images/photos ) и удалить ее. В методе up мы создадим папку, а в методе down мы удалим ее. В __construct мы создаем объект файловой системы, передавая локальный адаптер (или Dropbox, Rackspace…). Внутри этого локального адаптера мы указываем путь.

Обратите внимание, что создание папки и удаление ее в процессе миграции является антишаблоном. В этом нет ничего критического, но это нарушает принцип единой ответственности. Не беспокойтесь, этот код предназначен только для демонстрации и демонстрации работы библиотеки — просто помните об этом и в следующий раз попробуйте использовать его внутри контроллеров.

Функция public_path() является вспомогательной функцией Laravel, которая возвращает полный путь к public_path() папке.

Чтобы определить схему, просто укажите, какой тип полей вы хотите использовать, и укажите имя поля в качестве параметра. Для получения дополнительной информации о схеме прочитайте документы Laravel .

 /* /app/database/migrations/some_date_CreatePhotosTable.php */ use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; use Dropbox\Client; use League\Flysystem\Filesystem; use League\Flysystem\Adapter\Local as Adapter; use League\Flysystem\Adapter\Dropbox; class CreatePhotosTable extends Migration { private $filesystem; public function __construct(){ if(App::environment() === "local"){ // If its on local use the local filesystem $this->filesystem = new Filesystem(new Adapter( public_path() )); }else{ // Use dropbox on other cases, // including testing here (not a good idea) $client = new Client(Config::get('dropbox.token'), Config::get('dropbox.appName')); $this->filesystem = new Filesystem(new Dropbox($client)); } } public function up() { $this->filesystem->createDir('images'); Schema::create('photos', function($table) { $table->increments('id'); $table->integer('user_id'); $table->string('title'); $table->string('url')->unique(); $table->text('description'); $table->integer("category"); $table->timestamps(); }); } public function down() { Schema::dropIfExists('photos'); try{ $this->filesystem->deleteDir('images'); }catch (\Dropbox\Exception_BadResponse $e){} } } 

Для метода up мы создали id , user_id , title , url , category и description для фотографии. Мы также использовали то, что не похоже на другие. $table->timestamps() — это специальная функция, которая автоматически добавляет еще два поля: created_at и updated_at .

В методе down удалите таблицу, если она существует, и удалите папку, созданную нами в методе up . Мы будем использовать сеялки для установки некоторых изображений, поэтому рекомендуется удалить все фотографии и засеять их новыми.

Этот начальный файл работает и в производстве. Для разработки мы использовали локальную файловую систему, а для производства — приложение Dropbox. Загрузите все изменения в Heroku и выполните миграцию + заполнение, и вы увидите, что в вашем приложении Dropbox была создана папка.

После создания файла миграции фотографий нам нужен файл миграции категорий. Это проще В схеме мы создаем идентификатор, который увеличивается каждый раз, когда в таблицу добавляется новая запись. Нам также нужно название для категории. Имея имя и идентификатор для категории, мы можем сделать вещи более динамичными. В методе down отбросьте таблицу, если она существует.

 /* /app/database/migrations/some_date_CreateCategoriesTable.php */ use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateCategoriesTable extends Migration { public function up() { Schema::create('categories', function($table) { $table->increments('id'); $table->string('name'); $table->timestamps(); }); } public function down() { Schema::dropIfExists('categories'); } } 

После создания этих двух файлов давайте применим миграцию, выполнив:

 php artisan migrate:refresh php artisan db:seed 

или

 php artisan migrate:refresh --seed 

Это вернет старую миграцию (если вы ее применили) и создаст новую схему. После этого сеялки будут казнены.

Если вы еще не выполнили миграцию, появится сообщение об ошибке. Используйте php artisan migrate и все потом будет работать нормально.

Создайте Модели

Прежде чем идти дальше с сеялками, лучше сначала создать модели. При создании моделей, миграций и сеялок вы должны знать, что вы делаете. Подумайте о том, чего вы действительно хотите. Отношения между моделями важны и экономят время.

Модели Laravel расширяют класс ORM Eloquent. Приятной особенностью Eloquent являются отношения. Поскольку в этой серии мы имеем дело с REST Api, эта функция очень помогает нам на конечных точках размещать данные, связанные с данным ресурсом. У EmberJ на внешней стороне есть похожая логика отношений, и это автоматизирует большую часть кода. Эта четность делает код более понятным и масштабируемым.

Для модели User вам не нужно беспокоиться. Он создан Laravel и готов к использованию. Отредактируйте эту модель и добавьте некоторую связь с другими моделями, которые мы собираемся создать. Модели находятся в /app/models .

 /* /app/models/User.php */ use Illuminate\Auth\UserTrait; use Illuminate\Auth\UserInterface; class User extends Eloquent implements UserInterface{ use UserTrait; protected $table = 'users'; // The table that this model uses public function photos() { return $this->hasMany('Photo'); } } 

Метод photos() определяет связь с моделью Photo, которой пока нет. Кроме того, защищенная переменная $table используется для указания имени таблицы, которую использует эта модель. В качестве дополнительной функции в этой модели реализован UserInterface для упрощения интеграции с аутентификацией.

Давайте создадим фотомодель. Создайте новый файл в /app/models и назовите его Photo.php . Помните, что имя класса должно начинаться с заглавных букв и расширяться Eloquent.

 /* /app/models/Photo.php */ class Photo extends Eloquent { protected $table = 'photos'; public function author(){ return $this->belongsTo('User', 'user_id'); } } 

Переменная $table в этом случае указывать необязательно. Если переменная $table не существует, Laravel использует множественное число имени в нижнем регистре в качестве имени таблицы. Здесь мы указали другое отношение: отношение belongsTo . Первый параметр для модели, которая имеет отношение к нему. Второй — для поля, которое используется в этой модели, чтобы указать, кому принадлежит эта фотография. Это может быть использовано так:

 Photo::find($id)->author; 

Это возвращает объект User с идентификатором, идентичным user_id в модели Photo.

Для категорий создайте другой файл в /app/models и назовите его Category.php .

 class Category extends Eloquent { protected $table = 'categories'; } 

Заполните таблицы некоторыми данными

Теперь, когда у нас есть структура базы данных, пришло время заполнить ее некоторыми данными. Вот тут-то и появляется библиотека Faker. Для получения дополнительной информации о Faker см. Документацию Faker или для получения информации о более сложных функциях и сценариях использования см. Упрощение создания тестовых данных с помощью Faker .

В настоящее время у нас есть только файл сеялки. Давайте отредактируем его и используем библиотеку Faker для генерации поддельного имени пользователя и пароля. Отредактируйте файл UserTableSeeder.php папке /app/database/seeds UserTableSeeder.php .

Нам нужно знать одного пользователя для аутентификации. Один пользователь в базе данных должен быть создан без Faker.

Инициировать объект Faker:

 $faker = Faker\Factory::create(); // Faker uses Factory design pattern 

Как создать имя пользователя и пароль:

 $faker->userName; // returns a username Hash::make($faker->name . $faker->year); // Creates a password 

В конце UserTableSeeder должен выглядеть примерно так:

 /* /app/database/seeds/UserTableSeeder.php */ class UserTableSeeder extends Seeder { public function run() { Eloquent::unguard(); DB::table('users')->delete(); $faker = Faker\Factory::create(); for($i = 0; $i < 2; $i++){ User::create(array( 'username' => $faker->userName, 'password' => Hash::make($faker->name . $faker->year), 'name' => $faker->name, 'lastname' => $faker->lastName )); } User::create(array( 'username' => 'foo', 'password' => Hash::make('password'), 'name' => $faker->name, 'lastname' => $faker->lastName )); } } 

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

Что осталось, так это файлы категорий и фотографий. Создайте PhotoTableSeeder.php и CategoryTableSeeder.php внутри /app/database/seeds PhotoTableSeeder.php .

 /* /app/database/seeds/CategoryTableSeeder.php */ class CategoryTableSeeder extends Seeder { public function run() { Eloquent::unguard(); DB::table('categories')->delete(); for($i = 1; $i < 5; $i++){ Category::create(array( 'name' => 'category' . $i )); } } } 

Для исходного файла категорий нам даже не нужен Faker. Просто имя categorynumber будет делать для названия категории. Идентификатор будет автоматически увеличиваться при каждом добавлении новой категории.

Класс семян фотографий немного сложнее. В этом файле миграции нам нужно получить некоторые изображения из LoremPixel и поместить их в папку /public/images . Также нам нужна библиотека flysystem с локальным адаптером или адаптером Dropbox.

Вот как мы создаем случайную строку. Длина аргумента — это длина случайной строки. Это будет имя изображения.

 $faker->lexify($string = '???????????????????'); 

Получить изображения из lorempixel просто: ширина и высота — это фрагменты URL. Такая ссылка затем возвращает изображение с заданным размером. При запросе этого URL несколько раз возвращаются разные изображения, поэтому дублирование не происходит. file_get_contents($url); получает содержимое этого URL. В этом случае этот URL будет http://lorempixel.com/400/200/ , и это изображение

 file_get_contents('http://lorempixel.com/640/400/'); 

Метод предложения Faker возвращает предложение с указанным количеством слов в качестве аргумента

 $faker->sentence(40); 

В конце PhotoTableSeeder.php должен выглядеть примерно так.

 /* /app/database/seeds/PhotoTableSeeder.php */ use Dropbox\Client; // DropBox Client use League\Flysystem\Filesystem; use League\Flysystem\Adapter\Local as Adapter; use League\Flysystem\Adapter\Dropbox; // The DropBox Adapter class PhotoTableSeeder extends Seeder { private $filesystem; public function __construct(){ if(App::environment() === "local"){ $this->filesystem = new Filesystem(new Adapter( public_path() . '/images/')); }else{ $client = new Client(Config::get('dropbox.token'), Config::get('dropbox.appName')); $this->filesystem = new Filesystem(new Dropbox($client, '/images')); } } public function run() { Eloquent::unguard(); DB::table('photos')->delete(); $faker = Faker\Factory::create(); for($i = 0; $i < 10; $i++){ $file = file_get_contents('http://lorempixel.com/640/400/'); $url = $faker->lexify($string = '???????????????????'); try{ $this->filesystem->write($url, $file); }catch (\Dropbox\Exception $e){ echo $e->getMessage(); } Photo::create(array( 'url' => $url, 'user_id' => (int) rand(1, 4), 'title' => $faker->sentence(5), 'description' => $faker->sentence(40), 'category' => rand(1, 4) )); } } } 

Не забудьте вызвать эти файлы миграции в DatabaseSeeder.php . Добавьте эти строки в /app/database/seeds/DatabaseSeeder.php :

 $this->call('PhotoTableSeeder'); $this->call('CategoryTableSeeder'); 

Таким образом, DatabaseSeeder вызовет два новых файла сеялки. Давайте применим миграцию и посев на Heroku. Первый толчок проекта

 git add . git commit -m "a message here" git push heroku master 

А затем запустите миграцию и семя

 heroku run php artisan migrate:refresh --seed 

После выполнения миграции и заполнения на сервере это снимок экрана в папке приложений Dropbox.

Dropbox apps folder

Вывод

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