国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Laravel學(xué)習(xí)筆記之Seeder填充數(shù)據(jù)小技巧

cgspine / 2144人閱讀

摘要:而且,與是一對多關(guān)系一個分類下有很多,一個只能歸屬于一個與是一對多關(guān)系一篇博客下有很多,一條只能歸屬于一篇與是多對多關(guān)系一篇有很多,一個下有很多。

說明:本文主要聊一聊Laravel測試數(shù)據(jù)填充器Seeder的小技巧,同時介紹下Laravel開發(fā)插件三件套,這三個插件挺好用哦。同時,作者會將開發(fā)過程中的一些截圖和代碼黏上去,提高閱讀效率。

備注:在設(shè)計個人博客軟件時,總會碰到有分類Category、博客Post、給博客貼的標(biāo)簽Tag、博客內(nèi)容的評論Comment。
而且,Category與Post是一對多關(guān)系One-Many:一個分類下有很多Post,一個Post只能歸屬于一個Category;Post與Comment是一對多關(guān)系One-Many:一篇博客Post下有很多Comment,一條Comment只能歸屬于一篇Post;Post與Tag是多對多關(guān)系Many-Many:一篇Post有很多Tag,一個Tag下有很多Post。
開發(fā)環(huán)境:Laravel5.2 + MAMP + PHP7 + MySQL5.5

開發(fā)插件三件套

在先聊測試數(shù)據(jù)填充器seeder之前,先裝上開發(fā)插件三件套,開發(fā)神器。先不管這能干些啥,裝上再說。
1、barryvdh/laravel-debugbar

composer require barryvdh/laravel-debugbar --dev

2、barryvdh/laravel-ide-helper

composer require barryvdh/laravel-ide-helper --dev

3、mpociot/laravel-test-factory-helper

composer require mpociot/laravel-test-factory-helper --dev

然后在config/app.php文件中填上:

        /**
         *Develop Plugin
        */
        BarryvdhDebugbarServiceProvider::class,
        MpociotLaravelTestFactoryHelperTestFactoryHelperServiceProvider::class,
        BarryvdhLaravelIdeHelperIdeHelperServiceProvider::class,
設(shè)計表的字段和關(guān)聯(lián) 設(shè)計字段

按照上文提到的Category、Post、Comment和Tag之間的關(guān)系創(chuàng)建遷移Migration和模型Model,在項目根目錄輸入:

php artisan make:model Category -m
php artisan make:model Post -m
php artisan make:model Comment -m
php artisan make:model Tag -m

在各個表的遷移migrations文件中根據(jù)表的功能設(shè)計字段:

//Category表
class CreateCategoriesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create("categories", function (Blueprint $table) {
            $table->increments("id");
            $table->string("name")->comment("分類名稱");
            $table->integer("hot")->comment("分類熱度");
            $table->string("image")->comment("分類圖片");
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop("categories");
    }
}
    
//Post表
class CreatePostsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create("posts", function (Blueprint $table) {
            $table->increments("id");
            $table->integer("category_id")->unsigned()->comment("外鍵");
            $table->string("title")->comment("標(biāo)題");
            $table->string("slug")->unique()->index()->comment("錨點");
            $table->string("summary")->comment("概要");
            $table->text("content")->comment("內(nèi)容");
            $table->text("origin")->comment("文章來源");
            $table->integer("comment_count")->unsigned()->comment("評論次數(shù)");
            $table->integer("view_count")->unsigned()->comment("瀏覽次數(shù)");
            $table->integer("favorite_count")->unsigned()->comment("點贊次數(shù)");
            $table->boolean("published")->comment("文章是否發(fā)布");
            $table->timestamps();
            //Post表中category_id字段作為外鍵,與Category一對多關(guān)系
            $table->foreign("category_id")
                  ->references("id")
                  ->on("categories")
                  ->onUpdate("cascade")
                  ->onDelete("cascade");
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        //刪除表時要刪除外鍵約束,參數(shù)為外鍵名稱
        Schema::table("posts", function(Blueprint $tabel){
            $tabel->dropForeign("posts_category_id_foreign");
        });
        Schema::drop("posts");
    }
}

//Comment表
class CreateCommentsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create("comments", function (Blueprint $table) {
            $table->increments("id");
            $table->integer("post_id")->unsigned()->comment("外鍵");
            $table->integer("parent_id")->comment("父評論id");
            $table->string("parent_name")->comment("父評論標(biāo)題");
            $table->string("username")->comment("評論者用戶名");
            $table->string("email")->comment("評論者郵箱");
            $table->string("blog")->comment("評論者博客地址");
            $table->text("content")->comment("評論內(nèi)容");
            $table->timestamps();
            //Comment表中post_id字段作為外鍵,與Post一對多關(guān)系
            $table->foreign("post_id")
                  ->references("id")
                  ->on("posts")
                  ->onUpdate("cascade")
                  ->onDelete("cascade");
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
    //刪除表時要刪除外鍵約束,參數(shù)為外鍵名稱
        Schema::table("comments", function(Blueprint $tabel){
            $tabel->dropForeign("comments_post_id_foreign");
        });
        Schema::drop("comments");
    }
}

//Tag表
class CreateTagsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create("tags", function (Blueprint $table) {
            $table->increments("id");
            $table->string("name")->comment("標(biāo)簽名稱");
            $table->integer("hot")->unsigned()->comment("標(biāo)簽熱度");
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop("tags");
    }
}

由于Post表與Tag表是多對多關(guān)系,還需要一張存放兩者關(guān)系的表:

//多對多關(guān)系,中間表的命名laravel默認(rèn)按照兩張表字母排序來的,寫成tag_post會找不到中間表
php artisan make:migration create_post_tag_table --create=post_tag

然后填上中間表的字段:

class CreatePostTagTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create("post_tag", function (Blueprint $table) {
            $table->increments("id");
            $table->integer("post_id")->unsigned();
            $table->integer("tag_id")->unsigned();
            $table->timestamps();
            //post_id字段作為外鍵
            $table->foreign("post_id")
                  ->references("id")
                  ->on("posts")
                  ->onUpdate("cascade")
                  ->onDelete("cascade");
            //tag_id字段作為外鍵      
            $table->foreign("tag_id")
                  ->references("id")
                  ->on("tags")
                  ->onUpdate("cascade")
                  ->onDelete("cascade");
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table("post_tag", function(Blueprint $tabel){
            $tabel->dropForeign("post_tag_post_id_foreign");
            $tabel->dropForeign("post_tag_tag_id_foreign");
        });
        Schema::drop("post_tag");
    }
}
設(shè)計關(guān)聯(lián)

寫上Migration后,還得在Model里寫上關(guān)聯(lián):

class Category extends Model
{
    //Category-Post:One-Many
    public function posts()
    {
        return $this->hasMany(Post::class);
    }
}

class Post extends Model
{
    //Post-Category:Many-One
    public function category()
    {
        return $this->belongsTo(Category::class);
    }

    //Post-Comment:One-Many
    public function comments()
    {
        return $this->hasMany(Comment::class);
    }

    //Post-Tag:Many-Many
    public function tags()
    {
        return $this->belongsToMany(Tag::class)->withTimestamps();
    }
}

class Comment extends Model
{
    //Comment-Post:Many-One
    public function post()
    {
        return $this->belongsTo(Post::class);
    }
}

class Tag extends Model
{
    //Tag-Post:Many-Many
    public function posts()
    {
        return $this->belongsToMany(Post::class)->withTimestamps();
    }
}

然后執(zhí)行遷移:

php artisan migrate

數(shù)據(jù)庫中會生成新建表,表的關(guān)系如下:

Seeder填充測試數(shù)據(jù)

好,在聊到seeder測試數(shù)據(jù)填充之前,看下開發(fā)插件三件套能干些啥,下文中命令可在項目根目錄輸入php artisan指令列表中查看。
1、barryvdh/laravel-ide-helper
執(zhí)行php artisan ide-helper:generate指令前:

執(zhí)行php artisan ide-helper:generate指令后:

不僅Facade模式的Route由之前的反白了變?yōu)榭梢远ㄎ坏皆创a了,而且輸入Config Facade時還方法自動補全auto complete,這個很方便啊。

輸入指令php artisan ide-helper:models后,看看各個Model,如Post這個Model:

belongsTo(Category::class);
    }

    //Post-Comment:One-Many
    public function comments()
    {
        return $this->hasMany(Comment::class);
    }

    //Post-Tag:Many-Many
    public function tags()
    {
        return $this->belongsToMany(Tag::class)->withTimestamps();
    }
}

根據(jù)遷移到庫里的表生成字段屬性和對應(yīng)的方法提示,在控制器里輸入方法時會自動補全auto complete字段屬性的方法:

2、mpociot/laravel-test-factory-helper
輸入指令php artisan test-factory-helper:generate后,database/factory/ModelFactory.php模型工廠文件會自動生成各個模型對應(yīng)字段數(shù)據(jù)。Faker是一個好用的生成假數(shù)據(jù)的第三方庫,而這個開發(fā)插件會自動幫你生成這些屬性,不用自己寫了。

define(AppUser::class, function (FakerGenerator $faker) {
    return [
        "name" => $faker->name,
        "email" => $faker->safeEmail,
        "password" => bcrypt(str_random(10)),
        "remember_token" => str_random(10),
    ];
});
$factory->define(AppCategory::class, function (FakerGenerator $faker) {
    return [
        "name" =>  $faker->name ,
        "hot" =>  $faker->randomNumber() ,
        "image" =>  $faker->word ,
    ];
});

$factory->define(AppComment::class, function (FakerGenerator $faker) {
    return [
        "post_id" =>  function () {
             return factory(AppPost::class)->create()->id;
        } ,
        "parent_id" =>  $faker->randomNumber() ,
        "parent_name" =>  $faker->word ,
        "username" =>  $faker->userName ,
        "email" =>  $faker->safeEmail ,
        "blog" =>  $faker->word ,
        "content" =>  $faker->text ,
    ];
});

$factory->define(AppPost::class, function (FakerGenerator $faker) {
    return [
        "category_id" =>  function () {
             return factory(AppCategory::class)->create()->id;
        } ,
        "title" =>  $faker->word ,
        "slug" =>  $faker->slug ,//修改為slug
        "summary" =>  $faker->word ,
        "content" =>  $faker->text ,
        "origin" =>  $faker->text ,
        "comment_count" =>  $faker->randomNumber() ,
        "view_count" =>  $faker->randomNumber() ,
        "favorite_count" =>  $faker->randomNumber() ,
        "published" =>  $faker->boolean ,
    ];
});

$factory->define(AppTag::class, function (FakerGenerator $faker) {
    return [
        "name" =>  $faker->name ,
        "hot" =>  $faker->randomNumber() ,
    ];
});

在聊第三個debugbar插件前先聊下seeder小技巧,用debugbar來幫助查看。Laravel官方推薦使用模型工廠自動生成測試數(shù)據(jù),推薦這么寫的:

//先輸入指令生成database/seeds/CategoryTableSeeder.php文件: php artisan make:seeder CategoryTableSeeder
create()->each(function($category){
            $category->posts()->save(factory(AppPost::class)->make());
        });
    }
}
//然后php artisan db:seed執(zhí)行數(shù)據(jù)填充

但是這種方式效率并不高,因為每一次create()都是一次query,而且每生成一個Category也就對應(yīng)生成一個Post,當(dāng)然可以在each()里每一次Category繼續(xù)foreach()生成幾個Post,但每一次foreach也是一次query,效率更差。可以用debugbar小能手看看。先在DatabaseSeeder.php文件中填上這次要填充的Seeder:

    public function run()
    {
        // $this->call(UsersTableSeeder::class);
        $this->call(CategoryTableSeeder::class);
    }

在路由文件中寫上:

Route::get("/artisan", function () {
    $exitCode = Artisan::call("db:seed");
    return $exitCode;
});

輸入路由/artisan后用debugbar查看執(zhí)行了15次query,耗時7.11ms:

實際上才剛剛輸入幾個數(shù)據(jù)呢,Category插入了10個,Post插入了5個。
可以用DB::table()->insert()批量插入,拷貝ModelFactory.php中表的字段定義放入每一個表對應(yīng)Seeder,當(dāng)然可以有些字段為便利也適當(dāng)修改對應(yīng)假數(shù)據(jù)。

class CategoryTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
//        factory(AppCategory::class, 20)->create()->each(function($category){
//            $category->posts()->save(factory(AppPost::class)->make());
//        });

        $faker = FakerFactory::create();
        $datas = [];
        foreach (range(1, 10) as $key => $value) {
            $datas[] = [
                "name" =>  "category".$faker->randomNumber() ,
                "hot" =>  $faker->randomNumber() ,
                "image" =>  $faker->url ,
                "created_at" => CarbonCarbon::now()->toDateTimeString(),
                "updated_at" => CarbonCarbon::now()->toDateTimeString()
            ];
        }
        DB::table("categories")->insert($datas);
    }
}

class PostTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $faker = FakerFactory::create();
        $category_ids = AppCategory::lists("id")->toArray();
        $datas = [];
        foreach (range(1, 10) as $key => $value) {
            $datas[] = [
                "category_id" => $faker->randomElement($category_ids),
                "title" =>  $faker->word ,
                "slug" =>  $faker->slug ,
                "summary" =>  $faker->word ,
                "content" =>  $faker->text ,
                "origin" =>  $faker->text ,
                "comment_count" =>  $faker->randomNumber() ,
                "view_count" =>  $faker->randomNumber() ,
                "favorite_count" =>  $faker->randomNumber() ,
                "published" =>  $faker->boolean ,
                "created_at" => CarbonCarbon::now()->toDateTimeString(),
                "updated_at" => CarbonCarbon::now()->toDateTimeString()
            ];
        }
        DB::table("posts")->insert($datas);
    }
}

class CommentTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $faker = FakerFactory::create();
        $post_ids = AppPost::lists("id")->toArray();
        $datas = [];
        foreach (range(1, 50) as $key => $value) {
            $datas[] = [
                "post_id" => $faker->randomElement($post_ids),
                "parent_id" =>  $faker->randomNumber() ,
                "parent_name" =>  $faker->word ,
                "username" =>  $faker->userName ,
                "email" =>  $faker->safeEmail ,
                "blog" =>  $faker->word ,
                "content" =>  $faker->text ,
                "created_at" => CarbonCarbon::now()->toDateTimeString(),
                "updated_at" => CarbonCarbon::now()->toDateTimeString()
            ];
        }
        DB::table("comments")->insert($datas);
    }
}

class TagTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $faker = FakerFactory::create();
        $datas = [];
        foreach (range(1, 10) as $key => $value) {
            $datas[] = [
                "name" =>  "tag".$faker->randomNumber() ,
                "hot" =>  $faker->randomNumber() ,
                "created_at" => CarbonCarbon::now()->toDateTimeString(),
                "updated_at" => CarbonCarbon::now()->toDateTimeString()
            ];
        }
        DB::table("tags")->insert($datas);
    }
}

class PostTagTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $faker = FakerFactory::create();
        $post_ids = AppPost::lists("id")->toArray();
        $tag_ids = AppTag::lists("id")->toArray();
        $datas = [];
        foreach (range(1, 20) as $key => $value) {
            $datas[] = [
                "post_id" =>  $faker->randomElement($post_ids) ,
                "tag_id" =>  $faker->randomElement($tag_ids) ,
                "created_at" => CarbonCarbon::now()->toDateTimeString(),
                "updated_at" => CarbonCarbon::now()->toDateTimeString()
            ];
        }
        DB::table("post_tag")->insert($datas);
    }
}

在DatabaseSeeder.php中按照順序依次填上Seeder,順序不能顛倒,尤其有關(guān)聯(lián)關(guān)系的表:

class DatabaseSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        // $this->call(UsersTableSeeder::class);
        $this->call(CategoryTableSeeder::class);
        $this->call(PostTableSeeder::class);
        $this->call(CommentTableSeeder::class);
        $this->call(TagTableSeeder::class);
        $this->call(PostTagTableSeeder::class);
    }
}

輸入路由/artisan后,生成了10個Category、10個Post、50個Comments、10個Tag和PostTag表中多對多關(guān)系,共有9個Query耗時13.52ms:

It is working!!!

表的遷移Migration和關(guān)聯(lián)Relationship都已設(shè)計好,測試數(shù)據(jù)也已經(jīng)Seeder好了,就可以根據(jù)Repository模式來設(shè)計一些數(shù)據(jù)庫邏輯了。準(zhǔn)備趁著端午節(jié)研究下Repository模式的測試,PHPUnit結(jié)合Mockery包來TDD測試也是一種不錯的玩法。
M(Model)-V(View)-C(Controller)模式去組織代碼,很多時候也未必指導(dǎo)性很強,給Model加一個Repository,給Controller加一個Service,給View加一個Presenter,或許代碼結(jié)構(gòu)更清晰。具體可看下面分享的一篇文章。

最近一直在給自己充電,研究MySQL,PHPUnit,Laravel,上班并按時打卡,看博客文章,每天喝紅牛。很多不會,有些之前沒咋學(xué)過,哎,頭疼。后悔以前讀書太少,書到用時方恨少,人丑還需多讀書。

研究生學(xué)習(xí)機器人的,本打算以后讀博搞搞機器人的(研一時真是這么想真是這么準(zhǔn)備的,too young too simple)。現(xiàn)在做PHP小碼農(nóng)了,只因當(dāng)時看到智能機就激動得不行,決定以后做個碼農(nóng)試試吧,搞不好是條生路,哈哈。讀書時覺悟太晚,耗費了青春,其實我早該踏入這條路的嘛,呵呵。Follow My Heart!

不扯了,在凌晨兩點邊聽音樂邊寫博客,就容易瞎感慨吧。。

分享下最近發(fā)現(xiàn)的一張好圖和一篇極贊的文章:

文章鏈接:Laravel的中大型專案架構(gòu)

歡迎關(guān)注Laravel-China。

RightCapital招聘Laravel DevOps

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/21662.html

相關(guān)文章

  • Laravel學(xué)習(xí)筆記Redis保存頁面瀏覽量

    摘要:說明本文主要講述使用作為緩存加快頁面訪問速度。何不用來做緩存,等到該達(dá)到一定瀏覽頁面后再刷新下,效率也很高。可作緩存系統(tǒng)隊列系統(tǒng)。 說明:本文主要講述使用Redis作為緩存加快頁面訪問速度。同時,作者會將開發(fā)過程中的一些截圖和代碼黏上去,提高閱讀效率。 備注:作者最近在學(xué)習(xí)github上別人的源碼時,發(fā)現(xiàn)好多在計算一篇博客頁面訪問量view_count時都是這么做的:利用Laravel...

    z2xy 評論0 收藏0
  • Laravel 中的數(shù)據(jù)遷移和數(shù)據(jù)填充

    摘要:本文首發(fā)于作者這是一篇基礎(chǔ)教程,對標(biāo)文檔中的數(shù)據(jù)遷移和數(shù)據(jù)填充。那么,中的數(shù)據(jù)庫遷移概念,就是用于解決團隊中保證數(shù)據(jù)庫結(jié)構(gòu)一致的方案。和不同,如果多次執(zhí)行就會進行多次數(shù)據(jù)填充。好了,數(shù)據(jù)遷移和數(shù)據(jù)填充的基本操作也就這些了。 showImg(https://segmentfault.com/img/remote/1460000012252769?w=648&h=422); 本文首發(fā)于 h...

    mengera88 評論0 收藏0
  • laravel入門

    摘要:開發(fā)根目錄測試分為單元測試和功能測試創(chuàng)建一個文件執(zhí)行測試測試前清除配置緩存運行單個測試用例小提示在開發(fā)與進行交互的第三方擴展包時,最好選擇注入契約而不使用。 參考https://laravelacademy.org/ 概念 單詞 契約Contract 就是接口 repository 倉庫(封裝數(shù)據(jù)訪問,可以搜索:repository模式) Container 容器 ServicePr...

    韓冰 評論0 收藏0
  • 如何將 Laravel 數(shù)據(jù)表里的數(shù)據(jù)導(dǎo)出成 Seeder 文件

    摘要:本文經(jīng)授權(quán)轉(zhuǎn)自社區(qū)說明開發(fā)者使用部署一個新項目的時候通常會使用快速填充本地數(shù)據(jù)以方便開發(fā)調(diào)試擴展包提供了可將數(shù)據(jù)表里的數(shù)據(jù)直接轉(zhuǎn)換為文件的功能本項目由團隊成員整理發(fā)布首發(fā)地為社區(qū)使用場景通常情況下我們會希望本地開發(fā)環(huán)境數(shù)據(jù)與生產(chǎn)完全一致這樣 本文經(jīng)授權(quán)轉(zhuǎn)自 PHPHub 社區(qū) 說明 開發(fā)者使用 Laravel 部署一個新項目的時候, 通常會使用 seeder 快速填充本地數(shù)據(jù)以方便開發(fā)...

    BigTomato 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<