用Eloquent,Faker和Flysystem建立数据库

In this part, we will create the structure of the database. We will create the tables using migrations and seed the database using seeders. Also, you will learn how to grab some random images from LoremPixel and put them on the filesystem using Flysystem. You’ll also be adding some randomly generated data using the Faker library. Much like with part 1, you can download this part’s code from github.

在这一部分中,我们将创建数据库的结构。 我们将使用迁移创建表,并使用播种器为数据库播种。 另外,您还将学习如何从LoremPixel中获取一些随机图像,并使用Flysystem将其放置在文件系统中。 您还将使用Faker库添加一些随机生成的数据。 与第1部分非常相似,您可以从github下载此部分的代码。

安装库 (Install the libraries)

The installation is very straightforward with Composer.

使用Composer安装非常简单。

Require these projects:

需要这些项目:

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

Execute composer update and everything will be installed and updated smoothly.

执行composer update ,所有内容都将顺利安装和更新。

建立数据库的结构 (Build the structure of the database)

Until now, we had just one migration file. We need two more for our application. One table that will keep the data for photos and another for categories. To find out more about Artisan and Migrations, see this post.

到目前为止,我们只有一个迁移文件。 我们的应用程序还需要两个。 一个表将保留照片数据,而另一个表将保留类别数据。 要了解有关Artisan和Migrations的更多信息,请参阅这篇文章

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

These two commands create two migration files. Let’s start filling them with some schema. First, we start with the photos migration file. Stop for a moment and think what we need for this one. Earlier, we installed the flysystem library.

这两个命令创建两个迁移文件。 让我们开始用一些模式填充它们。 首先,我们从照片迁移文件开始。 停一会儿,想一想我们需要什么。 之前,我们安装了flysystem库。

The flysystem library can handle files on different locations: the local filesystem, Dropbox, AWS3, Rackspace Cloud Files and more. We need it for the local filesystem on our development environment and we have to use Dropbox for production. Why is that? Heroku is a Paas (Platform as a Service) so we don’t have full control of the filesystem. There are only two directories that can be writable: ./temp and ./logs. You can write files only using git for deployment, and not in any other folder. Why don`t we just use those two directories? Because they are temporary. If something goes wrong and the Dyno restarts, all the files in those directories are deleted. It’s not safe to work with those two directories.

flysystem库可以处理不同位置的文件:本地文件系统,Dropbox,AWS3,Rackspace Cloud Files等。 我们在开发环境中将其用于本地文件系统,并且必须使用Dropbox进行生产。 这是为什么? Heroku是Paas(平台即服务),因此我们无法完全控制文件系统。 只有两个可写的目录: ./temp./logs 。 您只能使用git进行部署来写入文件,而不能在任何其他文件夹中写入文件。 我们为什么不只使用这两个目录? 因为它们是暂时的。 如果出现问题,并且Dyno重新启动,则这些目录中的所有文件都将被删除。 使用这两个目录并不安全。

If you want to know more about flysystem read this article on sitepoint by Lukas White or their documentation .

如果您想了解有关flysystem的更多信息,请阅读Lukas White 撰写的有关sitepoint文章他们的文档

Dropbox应用程序 (A Dropbox application)

Before using flysystem and Dropbox for production, we have to create a Dropbox application which allows us to use their Api. Then, we need to do some configuring. If you don’t already have a Dropbox account, create one and then return for the rest of the article. If you use Rackspace, or AWS3 then you are free to use either of those. I’m using Dropbox here because it doesn’t require a credit card and it’s free to use. Follow the link and create a Dropbox App. Here is how to create one.

在使用flysystem和Dropbox进行生产之前,我们必须创建一个Dropbox应用程序,该应用程序允许我们使用其Api。 然后,我们需要进行一些配置。 如果您还没有Dropbox帐户,请创建一个帐户,然后返回本文的其余部分。 如果您使用Rackspace或AWS3,则可以自由使用其中任何一个。 我在这里使用Dropbox是因为它不需要信用卡,而且可以免费使用。 点击链接并创建一个Dropbox应用。 这是创建一个的方法。

Create a DropBox App

Next come the configurations. We are going to use it only on production. Its a good idea to separate the configuration from App logic. Create dropbox.php inside /app/config or in /app/config/production.

接下来是配置。 我们将仅在生产中使用它。 将配置与App逻辑分开是一个好主意。 在/app/config/app/config/production创建dropbox.php

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

And for retrieving use:

对于检索用途:

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

We need flysystem to create the images folder (the folder that will hold images/photos) and delete it. In the up method, we will create the folder and in the down method we will delete it. In __construct we create a Filesystem object by passing in a Local adapter (or a Dropbox, Rackspace…). Inside that local adapter we specify a path.

我们需要flysystem创建images文件夹(该文件夹将保存images/photos )并将其删除。 在up方法中,我们将创建文件夹,而在down方法中,我们将其删除。 在__construct我们通过传入本地适配器(或Dropbox,Rackspace…)来创建Filesystem对象。 在该本地适配器内,我们指定一个路径。

Note that creating a folder and deleting it inside a migration is an anti pattern. It’s nothing critical, but it breaks the single responsibility principle. Don’t worry, this code is just for demonstration purposes and to show you how the library works – just keep that in mind and try to use it inside the controllers next time.

请注意,在迁移过程中创建文件夹并将其删除是一种反模式。 这并不重要,但它打破了单一责任原则。 不用担心,该代码仅用于演示目的并向您展示该库的工作方式–请记住这一点,并下次尝试在控制器中使用它。

The public_path() function is a Laravel helper function that returns the full path of the public folder.

public_path()函数是一个Laravel辅助函数返回的完整路径, public文件夹。

To define the schema, just specify what type of fields you want to use and put the name of the field as a parameter. For more info on schema read the Laravel docs.

要定义模式,只需指定要使用的字段类型,然后将字段名称作为参数即可。 有关模式的更多信息,请阅读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){}
    
    	}
    
    }

For the up method we created an id, user_id, title, url, a category, and a description for the photo. We also used something that doesn’t look like the others. $table->timestamps() is a special function that adds two more fields automatically: created_at and updated_at.

对于up方法,我们为照片创建了iduser_idtitleurlcategorydescription 。 我们还使用了看起来不像其他的东西。 $table->timestamps()是一个特殊功能,它会自动添加另外两个字段: created_atupdated_at

In the down method, drop the table if it exists and delete the folder that we created in the up method. We will be using seeders to set some images there, so it’s a good idea to delete all the photos and seed with new photos.

down方法中,删除表(如果存在),然后删除在up方法中创建的文件夹。 我们将使用播种机在此处设置一些图像,因此最好删除所有照片并使用新照片进行播种。

This seed file works in production, too. For development, we have used the local filesystem and for production a Dropbox App. Upload all the changes to Heroku and make a migration + seeding and you will see that in your Dropbox App a folder was created.

该种子文件也可以在生产中使用。 为了进行开发,我们使用了本地文件系统,并使用了Dropbox App。 将所有更改上传到Heroku并进行迁移和播种,您将在Dropbox App中看到已创建一个文件夹。

After creating the photos migration file, we need the categories migration file. This is easier. In the schema, we create an id that increments every time a new record is added into the table. We also need a name for the category. By having a name and an id for the category, we can make things more dynamic. In the down method, drop the table if it exists.

创建照片迁移文件后,我们需要类别迁移文件。 这比较容易。 在模式中,我们创建一个id,每次将新记录添加到表中时ID都会递增。 我们还需要一个类别名称。 通过具有类别的名称和ID,我们可以使事情更加动态。 在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');
    	}
    
    }

After creating those two files let’s apply the migration by executing:

创建这两个文件后,让我们通过执行以下操作来应用迁移:

php artisan migrate:refresh
    php artisan db:seed

or

要么

php artisan migrate:refresh --seed

This will revert the old migration (if you had applied one) and build the new schema. Afterwards, the seeders will be executed.

这将还原旧的迁移(如果已应用迁移)并构建新的架构。 之后,将执行播种机。

If you hadn’t already made a migration then an error will be shown. Use php artisan migrate and everything afterwards will be working just fine.

如果您尚未进行迁移,则会显示一个错误。 使用php artisan migrate ,之后一切都会正常。

创建模型 (Create the Models)

Before going further with the seeders, it’s better if we create the models first. When creating the models, migrations, and the seeders, you have to know what you are doing. Think clearly about what you really want. The relations between models are important and save time down the line.

在继续进行播种之前,最好先创建模型。 在创建模型,迁移和种子时,您必须知道自己在做什么。 仔细考虑一下您真正想要的是什么。 模型之间的关系很重要,可以节省时间。

Laravel’s models extend Eloquent’s ORM class. A nice feature of Eloquent is the Relations. As we are dealing with a REST Api in this series, this feature helps us a lot on the endpoints to put the data that is related with a given resource. EmberJs on the front end side has a similar logic about relations and this automates a large part of the code. This parity makes the code more maintainable and scalable.

Laravel的模型扩展了Eloquent的ORM类。 口才是一个很好的功能。 当我们在处理本系列中的REST Api时,此功能可以帮助我们在端点上做很多事情,以放置与给定资源相关的数据。 前端侧的EmberJs具有类似的关系逻辑,这可以使大部分代码自动化。 这种奇偶校验使代码更易于维护和扩展。

For the User model, you don’t have to worry. It’s created by Laravel and ready to use. Edit that Model and add some relation with other models that we are going to create. The models are located in /app/models.

对于用户模型,您不必担心。 它由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');
        }
    
    }

The photos() method specifies a relation with the Photo model which doesn’t exist for now. Also, the protected variable $table is used for specifying the table name that this model is using. As an additional feature, this model implements the UserInterface for easier integration with authentication.

photos()方法指定与Photo模型的关系,该关系目前尚不存在。 同样,受保护的变量$table用于指定此模型使用的表名。 作为附加功能,此模型实现了UserInterface ,以便与身份验证更轻松地集成。

Let’s create the Photo model. Create a new file in /app/models and name it Photo.php. Remember that the class name should begin with uppercase letters and extend Eloquent.

让我们创建照片模型。 在/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');
        }
    
    }

The $table variable does not have to be specified in this case. If a $table variable does not exist, Laravel uses the plural of the name in lowercase as the table name. We have specified another relation here: the belongsTo relation. The first parameter is for the Model that has a relation with it. The second one is for the field that is being used on this model to specify which user owns this photo. It can by used like this:

在这种情况下,不必指定$table变量。 如果$table变量不存在,Laravel会将名称的小写形式用作表名。 我们在这里指定了另一个关系: belongsTo关系。 第一个参数用于与模型有关系的模型。 第二个是用于此模型上用于指定哪个用户拥有此照片的字段。 它可以这样使用:

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

This returns a User object with an id that is the same as the user_id on the Photo model.

这将返回一个ID与Photo模型上的user_id相同的User对象。

For the categories, create another file in /app/models and name it Category.php.

对于类别,在/app/models创建另一个文件,并将其命名为Category.php

class Category extends Eloquent {

        protected $table = 'categories';
    
    }

给表添加一些数据 (Seed the tables with some data)

Now that we have a structure for the database, it is time to seed it with some data. This is where the Faker library comes in. For more info on Faker read the Faker docs or for more advanced features and use cases, read Simplifying Test Data Generation with Faker.

现在我们有了数据库的结构,是时候为它添加一些数据了。 这是Faker库的来源。有关Faker的更多信息,请阅读Faker文档或了解更多高级功能和用例,请阅读《使用Faker简化测试数据生成》

Currently, we have only a seeder file. Let’s edit it and use the Faker library to generate a fake username and password. Edit the UserTableSeeder.php file inside the /app/database/seeds folder.

目前,我们只有一个种子文件。 让我们对其进行编辑,并使用Faker库生成伪造的用户名和密码。 编辑/app/database/seeds文件夹中的UserTableSeeder.php文件。

We need to know one user for authentication. One user in the database should be created without Faker.

我们需要认识一个用户进行身份验证。 应该在没有Faker的情况下创建数据库中的一位用户。

Init the Faker object:

初始化Faker对象:

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

How to create a username and a password:

如何创建用户名和密码:

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

In the end, the UserTableSeeder should look something like this:

最后,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
            ));
    
        }
    
    }

By executing this seeder Class, we have created two fake users and a hardcoded one. Later, we will test this app by using basic authentication so we need to have a known user.

通过执行此种子级,我们创建了两个假用户和一个硬编码用户。 稍后,我们将使用基本身份验证来测试此应用,因此我们需要拥有一个已知用户。

What’s left are the category and photo seed files. Create PhotoTableSeeder.php and CategoryTableSeeder.php inside /app/database/seeds.

剩下的是类别和照片种子文件。 在/app/database/seeds内创建PhotoTableSeeder.phpCategoryTableSeeder.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
                ));
            }
            
        }
    
    }

For the categories seed file, we don’t even need Faker. Just categorynumber would do for the name of the category. The id will auto increment each time a new category is inserted.

对于类别种子文件,我们甚至不需要Faker。 只需categorynumber就可以用作categorynumber的名称。 每次插入新类别时,ID都会自动递增。

The photo seed class is a bit trickier. In this migration file we need to get some images from LoremPixel and put them into the /public/images folder. Also, we need the flysystem library with a local adapter or Dropbox Adapter.

照片种子类有点棘手。 在此迁移文件中,我们需要从LoremPixel获取一些图像并将其放入/public/images文件夹。 另外,我们需要带本地适配器或Dropbox适配器的flysystem库。

This is how we create a random string. The length of the argument is the length of the random string. This will be the name of the image.

这就是我们创建随机字符串的方式。 参数的长度是随机字符串的长度。 这将是图像的名称。

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

Getting the images from lorempixel is simple: width and height are URL fragments. Such a link then returns an image with the given size. By requesting this url several times, different images are returned so no duplication occurs. file_get_contents($url); gets the content of that url. In this case that url would be https://lorempixel.com/400/200/ , and it’s an image

从lorempixel获取图像很简单:宽度和高度是URL片段。 然后,这样的链接将返回给定大小的图像。 通过多次请求此URL,将返回不同的图像,因此不会发生重复。 file_get_contents($url); 获取该URL的内容。 在这种情况下,该网址为https://lorempixel.com/400/200/ ,它是一个图片

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

The sentence method of Faker returns a sentence with the specified number of words as an argument

Faker的句子方法返回指定数目的单词作为参数的句子

$faker->sentence(40);

In the end, PhotoTableSeeder.php should look something like this.

最后, 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('https://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)
                ));
            }
    
        }
    
    }

Don’t forget to call these migration files into DatabaseSeeder.php . Add these lines into /app/database/seeds/DatabaseSeeder.php:

不要忘记将这些迁移文件调用到DatabaseSeeder.php 。 将这些行添加到/app/database/seeds/DatabaseSeeder.php

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

This way, DatabaseSeeder will call the two new seeder files. Let’s apply the migration and seeding on Heroku. First push the project

这样,DatabaseSeeder将调用两个新的种子文件。 让我们在Heroku上应用迁移和播种。 首先推动项目

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

And then run the migration and the seed

然后运行迁移和种子

heroku run php artisan migrate:refresh --seed

After executing the migration and seeding on the server, this is the screenshoot on my dropbox apps folder.

在服务器上执行迁移和种子设置后,这是我的保管箱应用程序文件夹中的屏幕截图。

Dropbox apps folder

结论 (Conclusion)

In this part, we saw how to create the database using migrations and how to seed that database using seeders with some fake data. We used the Faker library and Flysystem to work with the filesystem. Eloquent is an easy to use ORM, yet very powerful – understanding how Eloquent works simplifies your workflow. Don’t forget that everything starts from the database architecture and defining a smart one in the beginning will spare you many headaches later on. Stay tuned for part 3!

在这一部分中,我们看到了如何使用迁移来创建数据库,以及如何使用带有一些伪造数据的播种器来播种该数据库。 我们使用了Faker库和Flysystem来处理文件系统。 Eloquent是一种易于使用的ORM,但功能非常强大–了解Eloquent的工作原理可简化您的工作流程。 别忘了,一切都始于数据库体系结构,一开始就定义一个智能的体系结构会在以后为您省去许多麻烦。 请继续关注第3部分!

翻译自: https://www.sitepoint.com/build-database-eloquent-faker-flysystem/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值