larablog 系列文章 03 - 文章模型:使用 Eloquent 建立模型與數(shù)據(jù)填充

本章將開始探索博客的模型躺屁。該模型將使用 Eloquent 對(duì)象關(guān)系映射(ORM)實(shí)現(xiàn)肯夏,還會(huì)介紹如何填充測試數(shù)據(jù),它是一個(gè)有利于我們進(jìn)行開發(fā)和測試數(shù)據(jù)庫的好途徑犀暑。在文章結(jié)束后驯击,你將會(huì)了解如何定義模型,更新數(shù)據(jù)庫并創(chuàng)建一些可用于測試的填充數(shù)據(jù)耐亏,還將了解如何構(gòu)建用于展示博客頁面的基礎(chǔ)知識(shí)徊都。

Eloquent

對(duì)于我們的博客來說,我們需要一種持久化數(shù)據(jù)的方法广辰。而 Laravel 的 Eloquent ORM 提供了漂亮暇矫、簡潔的 ActiveRecord 實(shí)現(xiàn)來和數(shù)據(jù)庫進(jìn)行交互主之。每個(gè)數(shù)據(jù)庫表都有一個(gè)對(duì)應(yīng)的「模型」可用來跟數(shù)據(jù)表進(jìn)行交互。讓給你可以通過模型查找數(shù)據(jù)表內(nèi)的數(shù)據(jù)李根,以及將記錄添加到數(shù)據(jù)表中杀餐。

對(duì)象關(guān)系映射(英語:(Object Relational Mapping,簡稱ORM朱巨,或O/RM,或O/R mapping)枉长,是一種程序技術(shù)冀续,用于實(shí)現(xiàn)面向?qū)ο缶幊陶Z言里不同類型系統(tǒng)的數(shù)據(jù)之間的轉(zhuǎn)換。

ORM 有助于將關(guān)系數(shù)據(jù)庫(如MySQL)的數(shù)據(jù)轉(zhuǎn)換為可以操作的 PHP 對(duì)象必峰。這使我們能夠在類中的表上封裝我們需要的功能洪唐。想想一個(gè)用戶表,它可能有用戶名吼蚁,密碼等字段凭需。使用ORM,我們將操作的是一個(gè)包含成員用戶名肝匆,密碼等內(nèi)容的類粒蜈,它允許我們調(diào)用相應(yīng)的方法來對(duì)數(shù)據(jù)實(shí)體進(jìn)行操作。隨著我們?cè)诒窘坛讨械倪M(jìn)展旗国,你將更加熟悉 ORM 的內(nèi)容枯怖。

文章模型

讓我們先來創(chuàng)建文章模型。

模型通常放在 app 目錄中能曾,不過你可以將他們隨意放在任何可通過 composer.json 自動(dòng)加載的地方度硝。所有的 Eloquent 模型都繼承自 Illuminate\Database\Eloquent\Model 類。

通過命令行進(jìn)入項(xiàng)目所在目錄寿冕,執(zhí)行如下命令:

php artisan make:model Post -m

命令會(huì)生成模型 app/Post.php 和數(shù)據(jù)庫遷移文件 database/migrations/xxxx_xx_xx_xxxxxx_create_posts_table.php蕊程。

如果你留意,在 database/migrations 下已存在 2014_10_12_000000_create_users_table.php2014_10_12_100000_create_password_resets_table.php驼唱,這是 Laravel 框架自帶的默認(rèn)用戶功能的一部分藻茂,這個(gè)自帶的數(shù)據(jù)遷移可以讓你快速構(gòu)建用戶和認(rèn)證信息的存儲(chǔ),如果你用不到用戶功能玫恳,是可以刪除它們的捌治。

關(guān)于數(shù)據(jù)庫

我們?cè)陧?xiàng)目創(chuàng)建之初就已經(jīng)建立了數(shù)據(jù)庫 larablog,此時(shí)我們定義了模型纽窟,我們將通過數(shù)據(jù)遷移來建立和維護(hù)其中的數(shù)據(jù)表肖油。

文章表

找到我們生成 Post 模型時(shí)生成的遷移文件 database/migrations/xxxx_xx_xx_xxxxxx_create_posts_table.php。更改為如下內(nèi)容:

<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreatePostsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title');
            $table->string('author', 100);
            $table->text('content');
            $table->string('image');
            $table->text('tags');
            $table->timestamps();
        });
    }

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

在遷移文件中臂港,我們定義了 posts 表的結(jié)構(gòu)森枪,設(shè)置了不同字段的類型和長度视搏。

關(guān)于數(shù)據(jù)遷移的更多內(nèi)容可以查閱文檔 數(shù)據(jù)遷移

接下來,我們要需要通過命令 php artisan migrate 來執(zhí)行數(shù)據(jù)遷移县袱,創(chuàng)建我們需要的表浑娜。

執(zhí)行效果如下:

larablog php artisan migrate
Migrated: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_100000_create_password_resets_table
Migrated: 2017_07_10_075949_create_posts_table

其中 userspassword_resets 這 2 個(gè)遷移之前提到過是框架自帶,我們可以看創(chuàng)建表 posts 的遷移也已經(jīng)執(zhí)行式散。我們可以通過 http://localhost/phpmyadmin/ 去查看我們的數(shù)據(jù) larablog 現(xiàn)在的情況筋遭。可以看到我們想要的表 posts 已經(jīng)成功的創(chuàng)建了暴拄。

posts 表的結(jié)構(gòu)

默認(rèn)情況下漓滔,Eloquent 會(huì)預(yù)計(jì)你的數(shù)據(jù)表中有 created_at 和 updated_at 字段。如果你不希望讓 Eloquent 來自動(dòng)維護(hù)這兩個(gè)字段乖篷,可在模型內(nèi)將 $timestamps 屬性設(shè)置為 false:
詳細(xì)信息可以查閱 eloquent 時(shí)間戳

整合模型和視圖

現(xiàn)在我們創(chuàng)建了文章模型响驴,并更新了數(shù)據(jù)庫創(chuàng)建了相應(yīng)的數(shù)據(jù)表,我們可以開始將模型集成到視圖中撕蔼。將開始構(gòu)建我們博客的展示頁面豁鲤。

路由

首先打開 app/Http/routes.php 文件,增加文章相關(guān)的路由配置:

Route::resource('posts','PostsController');

可以發(fā)現(xiàn)鲸沮,這和之前定義的 GET, POST 請(qǐng)求路由不同琳骡,這是一個(gè)資源路由。
這條資源路由聲明會(huì)創(chuàng)建多個(gè)路由讼溺,用來處理各式各樣和相片資源相關(guān)的的 RESTful 行為日熬。同樣地,生成的控制器有著各種和這些行為綁定的方法肾胯,包含要處理的 URI 及方法對(duì)應(yīng)的注釋竖席。

更多關(guān)于資源路由的信息可以查閱這里的文檔 RESTful-資源控制器

接下來我們生成控制器 PostsController。通過命令行進(jìn)入項(xiàng)目所在目錄敬肚,執(zhí)行命令:

php artisan make:controller PostsController

生成的 PostsController 就是一個(gè)資源類型的控制器毕荐,可以看到它內(nèi)部已經(jīng)幫我們定義好了很多控制器方法。

接下來看看我們定義路由艳馒,繼續(xù)執(zhí)行如下命令:

php artisan route:list

將會(huì)呈現(xiàn)應(yīng)用的所有路由信息:

?  larablog php artisan route:list
+--------+----------+--------------------+---------------+-------------------------------------------------+------------+
| Domain | Method   | URI                | Name          | Action                                          | Middleware |
+--------+----------+--------------------+---------------+-------------------------------------------------+------------+
|        | GET|HEAD | /                  | homepage      | App\Http\Controllers\PageController@index       |            |
|        | GET|HEAD | about              | about         | App\Http\Controllers\PageController@about       |            |
|        | GET|HEAD | contact            | contact       | App\Http\Controllers\PageController@contact     |            |
|        | POST     | contact            |               | App\Http\Controllers\PageController@postContact |            |
|        | GET|HEAD | posts              | posts.index   | App\Http\Controllers\PostsController@index      |            |
|        | POST     | posts              | posts.store   | App\Http\Controllers\PostsController@store      |            |
|        | GET|HEAD | posts/create       | posts.create  | App\Http\Controllers\PostsController@create     |            |
|        | GET|HEAD | posts/{posts}      | posts.show    | App\Http\Controllers\PostsController@show       |            |
|        | PUT      | posts/{posts}      | posts.update  | App\Http\Controllers\PostsController@update     |            |
|        | PATCH    | posts/{posts}      |               | App\Http\Controllers\PostsController@update     |            |
|        | DELETE   | posts/{posts}      | posts.destroy | App\Http\Controllers\PostsController@destroy    |            |
|        | GET|HEAD | posts/{posts}/edit | posts.edit    | App\Http\Controllers\PostsController@edit       |            |
+--------+----------+--------------------+---------------+-------------------------------------------------+------------+

現(xiàn)在我們能清晰的看到我們所定義的資源路由 posts 的明細(xì)憎亚。考慮到我們后續(xù)應(yīng)該會(huì)對(duì)文章進(jìn)行操作一些操作弄慰,比如第美;編輯,刪除陆爽。資源路由就包含了這些操作文章的請(qǐng)求什往,我們將文章做為一種資源為其定義資源路由很符合我們的需要,如果你在定義路由時(shí)慌闭,盡可能考慮你是否要需要這么定義路由信息别威。

控制方法

我們已經(jīng)建立了控制器 app/Http/Controllers/PostsController.php躯舔,接下來我們定位到 show 方法:

public function show($id)
{
    $post = Post::findOrFail($id);

    return view('posts.show', ['post' => $post]);
}

這里,我們通過模型來查找相應(yīng) id 的文章省古,并渲染視圖顯示內(nèi)容粥庄。如果文章不存在將會(huì)拋出異常 NotFoundHttpException

如果是生產(chǎn)環(huán)境豺妓,這樣的異常信息最終都會(huì)以 404 頁呈現(xiàn)給用戶惜互,這需要我們自己定制相關(guān)的異常錯(cuò)誤處理頁面,關(guān)于這方面的內(nèi)容這里就不展開了琳拭。

視圖顯示

現(xiàn)在我們已建立控制方法 show 來處理文章的顯示训堆。我們需要?jiǎng)?chuàng)建文件 resources/views/posts/show.blade.php 并添加如下內(nèi)容:

@extends('layouts.app')

@section('title', $post->title)

@section('body')
    <article class="blog">
        <header>
            <div class="date">{{ $post->created_at->format('l, F j, Y') }}</div>
            <h2>{{ $post->title }}</h2>
        </header>
        <img src="{{ asset('images/'.$post->image) }}" alt="{{ $post->title }} image not found" class="large" />
        <div>
            <p>{{ $post->content }}</p>
        </div>
    </article>
@endsection

我們將文章使用的圖片信息存放在了 public/images 下,你可以通過下面的鏈接獲得這些靜態(tài)圖片資源臀栈。
圖片資源

CSS

同時(shí)我們要為博客的內(nèi)容增加樣式信息,打開文件 public/css/blog.css挠乳,追加如下內(nèi)容:

.date { margin-bottom: 20px; border-bottom: 1px solid #ccc; font-size: 24px; color: #666; line-height: 30px }
.blog { margin-bottom: 20px; }
.blog img { width: 190px; float: left; padding: 5px; border: 1px solid #ccc; margin: 0 10px 10px 0; }
.blog .meta { clear: left; margin-bottom: 20px; }
.blog .snippet p.continue { margin-bottom: 0; text-align: right; }
.blog .meta { font-style: italic; font-size: 12px; color: #666; }
.blog .meta p { margin-bottom: 5px; line-height: 1.2em; }
.blog img.large { width: 300px; min-height: 165px; }

填充數(shù)據(jù)

Laravel 可以簡單的使用 seed 類來給數(shù)據(jù)庫填充測試數(shù)據(jù)权薯。所有的 seed 類都放在 database/seeds 目錄下。你可以任意地為 Seed 類命名睡扬,但是應(yīng)該遵守某些大小寫規(guī)范盟蚣,可用類似 UserTableSeeder 之類的命名。 Laravel 默認(rèn)為你定義了一個(gè) DatabaseSeeder 類卖怜。你可以在這個(gè)類中使用 call 方法來運(yùn)行其它的 seed 類屎开,以借此控制數(shù)據(jù)填充的順序。

接下來我們就創(chuàng)建編寫數(shù)據(jù)填充類马靠。命令行下進(jìn)入項(xiàng)目所在目錄奄抽,執(zhí)行命令:

php artisan make:seeder PostsTableSeeder

執(zhí)行完命令,文章數(shù)據(jù)填充類就會(huì)生成甩鳄,文件位于 database/seeds/PostsTableSeeder.php逞度,內(nèi)容如下:

<?php

use Illuminate\Database\Seeder;

class PostsTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        //
    }
}

在 seeder 類里只有一個(gè)默認(rèn)方法:run。當(dāng)運(yùn)行 db:seed Artisan 命令 時(shí)就會(huì)調(diào)用此方法妙啃。你可以在 run 方法中給數(shù)據(jù)庫添加任何數(shù)據(jù)档泽。你可使用 查詢語句構(gòu)造器 或 Eloquent 模型工廠 來手動(dòng)添加數(shù)據(jù)。

這個(gè) run 方法中我們可以添加如下方法手動(dòng)插入數(shù)據(jù):

/**
 * 運(yùn)行數(shù)據(jù)庫填充揖赴。
 *
 * @return void
 */
public function run()
{
    DB::table('users')->insert([
        'name' => str_random(10),
        'email' => str_random(10).'@gmail.com',
        'password' => bcrypt('secret'),
    ]);
}

這只是個(gè)樣例寫法馆匿,很顯然我們每次都要一條條的插入測試數(shù)據(jù)會(huì)不方便,當(dāng)我們需要填充很多測試數(shù)據(jù)時(shí)燥滑,我們可以利用填充數(shù)據(jù)的模型工廠來建立數(shù)據(jù)模板渐北。

數(shù)據(jù)模板

打開 database/factories/ModelFactory.php 文件,可以看到默認(rèn)存在了 User 模型的數(shù)據(jù)模板铭拧,構(gòu)建用戶數(shù)據(jù)時(shí)就可以很方便的生成相應(yīng)的數(shù)據(jù)∏幌。現(xiàn)在讓我們來構(gòu)建 Post 模型的數(shù)據(jù)模版盆昙,在文件中添加如下內(nèi)容:

$factory->define(App\Post::class, function (Faker\Generator $faker) {
    return [
        'title' => $faker->sentence(6),
        'content' => $faker->text(600),
        'image' => $faker->randomElement(['beach.jpg', 'misdirection.jpg', 'one_or_zero.jpg', 'pool_leak.jpg', 'the_grid.jpg']),
        'author' => $faker->name,
        'tags' => join(',', $faker->words(rand(3, 6)))
    ];
});

在這里,我們定義了一個(gè) Post 模型的數(shù)據(jù)模板焊虏,接下來我們會(huì)在填充數(shù)據(jù)時(shí)根據(jù)數(shù)據(jù)模板來生成特定數(shù)量的數(shù)據(jù)淡喜。

數(shù)據(jù)模板中有很多數(shù)據(jù)生成的方法這是通過集成的組件完成的.
Faker is a PHP library that generates fake data for you.
你可以通過這里了解它 Faker

更新我們的文件 database/seeds/PostsTableSeeder.php,修改 run 方法的內(nèi)容:

public function run()
{
    factory(App\Post::class, 50)->create();
}

修改 database/seeds/DatabaseSeeder.php诵闭,同樣修改 run 方法:

public function run()
{
    Model::unguard();

    $this->call(PostsTableSeeder::class);

    Model::reguard();
}

這里炼团,數(shù)據(jù)填充器將會(huì)調(diào)用文章填充類通過文章模型數(shù)據(jù)模板生成 50 個(gè)樣板數(shù)據(jù)到數(shù)據(jù)庫。

命令

最終的數(shù)據(jù)填充需要執(zhí)行命令來完成疏尿,讓我們?cè)诿钚邢逻M(jìn)入項(xiàng)目所在目錄執(zhí)行 php artisan db:seed:

?  larablog php artisan db:seed
Seeded: PostsTableSeeder

命令執(zhí)行完成瘟芝,我們可以通過 http://localhost/phpmyadmin 來查看生成的填充數(shù)據(jù)。

有了填充數(shù)據(jù)褥琐,我們的博客內(nèi)容可以顯示了锌俱。打開瀏覽器訪問 http://localhost:8000/posts/1 即可查看編號(hào)為 1 的博客內(nèi)容(當(dāng)然你還可以試試別的編號(hào))。

至此敌呈,我們完成了博客內(nèi)容的顯示贸宏,并通過填充測試數(shù)據(jù)很輕松的就讓顯示效果得以展現(xiàn)。

總結(jié)

在本章的內(nèi)容中我們提及了一些 Eloquent 的概念和基本用法磕洪,我們也看到了填充數(shù)據(jù)可以讓我們可以快速的為應(yīng)用添加測試數(shù)據(jù)吭练。

接下來,我們會(huì)試著通過添加評(píng)論來延伸更多模型功能析显,我們會(huì)開始建立首頁鲫咽,將繼續(xù)探討數(shù)據(jù)遷移的使用以及如何通過 Eloquent 模型將評(píng)論發(fā)布到博客中。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末谷异,一起剝皮案震驚了整個(gè)濱河市分尸,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌歹嘹,老刑警劉巖寓落,帶你破解...
    沈念sama閱讀 206,723評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異荞下,居然都是意外死亡伶选,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門尖昏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來仰税,“玉大人,你說我怎么就攤上這事抽诉≡纱兀” “怎么了?”我有些...
    開封第一講書人閱讀 152,998評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵迹淌,是天一觀的道長河绽。 經(jīng)常有香客問我己单,道長,這世上最難降的妖魔是什么耙饰? 我笑而不...
    開封第一講書人閱讀 55,323評(píng)論 1 279
  • 正文 為了忘掉前任纹笼,我火速辦了婚禮,結(jié)果婚禮上苟跪,老公的妹妹穿的比我還像新娘廷痘。我一直安慰自己,他們只是感情好件已,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評(píng)論 5 374
  • 文/花漫 我一把揭開白布笋额。 她就那樣靜靜地躺著,像睡著了一般篷扩。 火紅的嫁衣襯著肌膚如雪兄猩。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,079評(píng)論 1 285
  • 那天鉴未,我揣著相機(jī)與錄音枢冤,去河邊找鬼。 笑死歼狼,一個(gè)胖子當(dāng)著我的面吹牛掏导,可吹牛的內(nèi)容都是我干的享怀。 我是一名探鬼主播羽峰,決...
    沈念sama閱讀 38,389評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼添瓷!你這毒婦竟也來了梅屉?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,019評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤鳞贷,失蹤者是張志新(化名)和其女友劉穎坯汤,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體搀愧,經(jīng)...
    沈念sama閱讀 43,519評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡惰聂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了咱筛。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片搓幌。...
    茶點(diǎn)故事閱讀 38,100評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖迅箩,靈堂內(nèi)的尸體忽然破棺而出溉愁,到底是詐尸還是另有隱情,我是刑警寧澤饲趋,帶...
    沈念sama閱讀 33,738評(píng)論 4 324
  • 正文 年R本政府宣布拐揭,位于F島的核電站撤蟆,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏堂污。R本人自食惡果不足惜家肯,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望敷鸦。 院中可真熱鬧息楔,春花似錦、人聲如沸扒披。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽碟案。三九已至愿险,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間价说,已是汗流浹背辆亏。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評(píng)論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留鳖目,地道東北人扮叨。 一個(gè)月前我還...
    沈念sama閱讀 45,547評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像领迈,于是被迫代替她去往敵國和親彻磁。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容