Laravel教程 四:數據庫和Eloquent
此文章為原創文章,未經同意,禁止轉載。
上一篇寫了一些Laravel Blade的基本用法和給視圖傳遞變量的幾種方式,
這一節我們來說說跟數據庫打交道的數據庫配置和Laravel強大的Eloquent。
Laravel的數據庫配置
本部分內容為下節做准備
Laravel的配置文件都是在項目目錄的config/
文件夾之下,這里也就是在blog/config
文件夾之下,你可以打開這個文件夾看看,你面有很多配置文件:如mail.php(配置郵件發送服務的)
和database.php(配置數據庫的)
,我們這里就是來看看這個database.php
配置文件:
'connections' => [ 'mysql' => [ 'driver' => 'mysql', 'host' => env('DB_HOST', 'localhost'), 'database' => env('DB_DATABASE', 'forge'), 'username' => env('DB_USERNAME', 'forge'), 'password' => env('DB_PASSWORD', ''), 'charset' => 'utf8', 'collation' => 'utf8_unicode_ci', 'prefix' => '', 'strict' => false, ] //... ]
打開文件,你可以看到里面只是返回簡單地php數組而已,我們目前只是關心connections
這個數組。上面的代碼並沒給出所有的數據庫配置,你可以自己看,由於博主使用的是mysql,所以這里會給出mysql的配置,其他數據庫你可以參照着來,后續的教材博主也會依舊使用mysql。
那這里說到的配置,基本上就是對下面四個變量的配置:
'host' => env('DB_HOST', 'localhost'), //如果.env文件沒有DB_HOST配置,則取localhost,后面的一樣 'database' => env('DB_DATABASE', 'forge'), 'username' => env('DB_USERNAME', 'forge'), 'password' => env('DB_PASSWORD', ''),
這里的env()方法是讀取到.env (位於blog/.env)
這個文件里面的配置項
打開這個文件,你可以看到一些常用的配置,包括debug模式和開發環境,你也可以看到我們下面這幾個需要操作的選項:
DB_HOST=localhost DB_DATABASE=homestead DB_USERNAME=homestead DB_PASSWORD=secret
由於這里我使用的是Homestead的開發環境,所以才有了上面的配置(Homestead的默認用戶名和密碼為homestead和secret)
,如果你是直接使用php artisan serve
這種方式開啟服務來開發的話,相應地修改你的配置。
Laravel為什么要采取這樣的配置呢?很大的一個原因可能就是考慮到文件的安全性和便捷性,這樣我們在需要將代碼推送到coding或者Github的時候,我們可以直接ignore這個.env
文件,不必擔心我們的核心信息唄泄露。在部署應用的時候,我們可以直接在服務器創建一個.env
文件,寫上對應的配置項就OK了。
就這樣,只要我們正確配置信息,我們就連接上數據庫了,當然,你得首先創建一個homestead數據庫。
使用Migration
連接好數據庫之后,我們就需要創建相對應的數據表了,在沒有使用Laravel之前,你可能都是直接手動創建數據表的,比如我們這個blog項目,你會到數據庫中手動創建一個articles
數據表,但是在Laravel的項目中,我極力推薦你使用Migration,這樣有什么好處呢?其實你可以將Migration看做一個數據庫的版本管理工具,就如git對於我們的項目文件的版本管理,你可以rollback
,你可以reset
等,它給予你一種代碼實現和命令行結合的方式來管理你的數據庫,如果你在blog/
目錄下,命令行執行 php artisan
,你可以看到很多命令行,下面這幾個就是我們這里談到的rollback
和reset
等:
紅色框框這幾個基本就是比較常用的,如果這里我還沒有說服使用migration,那么我們來將這個過程走一遍:
首先,我們創建一個migration
文件,也就是定義一張表的schema
,命令行執行:
php artisan make:migration create_articles_table --create='articles'
順利執行之后,我們會得到一個migration文件,這個文件位於database/migrations/
下面,打開這個文件夾,你可以看到Laravel本來就有兩個migration文件,users
表和password-reset
表,我們在這個項目中目前還不用這兩個文件。所以可以直接刪掉,然后打開我們剛剛生成的migration文件:create_articles_table
這個文件
public function up() { Schema::create('articles', function (Blueprint $table) { $table->increments('id'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::drop('articles'); }
這里有兩個方法:up()
和down()
。up()
方法是執行php artisan migrate
的時候調用的,這個方法會創建一個articles
數據表,而down()
方法則是在php artisan migrate:rollback
的使用執行的,這里會直接刪除articles
這個數據表。
但是,這里先不要急着執行php artisan migrate
,我們還需要為articles的增加幾個字段:
public function up() { Schema::create('articles', function (Blueprint $table) { $table->increments('id');// 主鍵 自增 $table->string('title'); $table->text('intro'); $table->text('content'); $table->timestamp('published_at'); $table->timestamps(); // 自動創建的兩個字段:created_at 和 updated_at }); }
這里我們的intro
字段是文章的簡介,published_at
字段是文章的發表日期,這樣做對我們寫博客有很大的好處,你可以將博客的發表日期控制起來,因為有一些我寫好的但是還沒有到發表日期的,還不想讓用戶看到的文章我就可以用published_at
來控制了。這樣之后,我們來執行一下php artisan migrate
:
然后,articles這個表就創建成功了。
這個時候你可能還沒有體會到migration的好處,想象下面兩個場景:
1. 在進行團隊開發的時候,團隊成員將我們的代碼pull下來之后,怎么可以拿到一樣的數據庫表設計呢?難道要我們將表 export 出來,給每一個成員import一次?這顯然不夠明智,如果使用的migration,就一行命令,直接`php artisan migrate`,就可以拿到一樣的數據庫表了。 2. 如果這個時候我們發現articles這個表的有一個字段寫錯了,比如我們的intro字段寫錯,它應該命名為introduction的,這個時候,我們怎么辦?直接手動改數據庫的表?那么回到第一個場景,你的團隊成員也需要手動改?這顯然也不是我們喜歡的方式,這個時候,migration的優勢就來了
比如我們這里演示一下怎么解決第二個場景:
我們只需要命令行執行:
php artisan migrate:rollback
然后修改up()方法的intro字段:
$table->text('introduction');
然后再執行php artisan migrate
:
大工告成,更多特性請看文檔:
http://laravel.com/docs/5.1/migrations
使用Eloquent
上面我們創建好了articles數據表之后,我們就可以為這個表寫一個Model類了,你可以手動創建,也可以使用artisan命令行來創建一個model,比如你在命令行敲php artisan
,你會看到make
下面會有很多命令,而make:model
就是我們需要使用的命令:
就像解釋的一樣:Create a new Eloquent model class
很多時候,在Laravel中,我們在創建一個model的時候都會有一些約定俗成的命名方法:
如果說我們有一個articles數據表,我們的model相對應就命名為Article;
如果說我們有一個users的數據表,我們的model對應就命名為User;
就是基本上遵守數據表復數而model單數大寫
就可以了。
所以根據這個規律我們來創建我們的Article Model,使用的是make:model
命令:
php artisan make:model Article
這樣一來,我們的Article Model就創建成功了,這個文件位於blog/app/Article.php
,打開之,可以看到我們Laravel為我們生成的內容:
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Article extends Model { // }
注意到Article這個類是繼承與我們的Eloquent\Model
類,由於這個Eloquent\Model
類實現了很多非常棒的方法供我們使用,我們可以來愉快地玩耍了。
首先開始玩耍的是,使用 php artisan tinker
這個工具來play around,tinker提供了一個Eloquent跟數據庫表交互的命令行界面,你可以在上面寫一些簡單地php操作,比如:
所以,我們來實例化一個Article吧:
$article = new App\Article
這樣就相當於我們實例化了一個Article類了,我們可以在后面的操作中進行字段具體化。
在上面我們創建表的時候,我們有以下幾個字段:
$table->increments('id'); $table->string('title'); $table->text('intro'); $table->text('content'); $table->timestamp('published_at'); $table->timestamps();
於是我們可以用tinker
來設置以下上面的$article
的各個字段,就如設置屬性一樣簡單。
比如設置$article
的title
可以這樣:
$article->title = 'Router Views Controllers';
同理,我們也可以將intro
和content
字段設置:
$article->intro = 'Article 1 Intro'; $article->content = 'Article 1 Content';
不過這里需要注意的是published_at
這個字段,這里我推薦使用一個很棒的時間處理庫Carbon,因為像created_at
和 updated_at
這兩個字段也是使用的Carbon
類,這樣在后面的處理中,我們會有很多好處,這里我們先直接使用Carbon:
$article->published_at = Carbon\Carbon::now();
而對於$table->timestamps()
這個,Laravel會在我們插入數據的時候自動完成的,所以這里我們每個字段都賦值完畢之后,我們可以使用Eloquent
的save()
方法來向數據庫的articles
表插入一條數據了:
$article->save();
返回一個true的時候,表示我們成功插入數據了,我們來看看數據庫:
以上,就是一個簡單而完整的使用tinker給Eloquent賦值的玩耍過程。
下面我們再來玩耍一會:
all()方法
all()
方法會返回Article的所有記錄:
$articles = App\Article::all();
find()
,接受一個參數$id,比如查找id為1的一條記錄:
$article = App\Article::find(1);
你也可以傳入一個$id的數組,查找多條記錄,不過這里我們只有一條數據,所以就這樣了。不過我們也可以這樣玩玩:
toArray()方法:
將一個Eloquent的對象轉為數組:
$article = App\Article::find(1)->toArray();
toJson()方法
將一個Eloquent的對象轉為json字串:
$article = App\Article::find(1)->toJson();
如果就簡簡單單這樣的話,Eloquent也不能算很強大,我們在寫代碼過程中的where語句呢,這個也沒有么?
不用擔心,這個馬上就有:
where()方法
$article = App\Article::where('title','=','Router Views Controllers')->get();
在使用where()
的時候,往往需要用get()
來獲取記錄集,這個返回的是一個Eloquent\Collection
結果集,但是如果我就是想要滿足條件的第一天記錄呢,不需要結果集呢?
使用first()
方法,在上面的基礎上,get()
換成first()
:
$article = App\Article::where('title','=','Router Views Controllers')->first();
到這里,一些簡單地查找工作就可以告一段落了,而對於update呢,我們可以這樣:
$article = App\Article::find(1); $article->intro = 'Article 1 Intro Update!'; $article->save();
我們來看看有沒有更新:
$article = App\Article::find(1);
也可以使用update()
方法:
$article->update(['content'=>'Article 1 Content Update']);
正常情況下我們會得到一個MassAssignmentException with message
:
文檔看這里: http://laravel.com/docs/5.1/eloquent#mass-assignment
這個是因為Eloquent默認是不允許我們直接更新我們的數據的,這是出於可能出現數據覆蓋的情況,但是如果我們確實是先要實現這樣的功能,我們可以在Article這個model文件里面加一個$fillable
數組:
class Article extends Model { protected $fillable = ['content']; }
然后再執行一次看看:
這里需要Ctrl + C 退出tinker在重新進來一次。
查找,更新之后,借着我們在聊到MassAssignmen
t這個概念的時候,我們可以來聊聊create()
這個方法了,這個方法可以在不用聲明new Article()
的情況下創建一條數據,比如:
App\Article::create(['title'=>'Article 2','intro'=>'intro 2','content'=>'Article 2 content','published_at'=>Carbon\Carbon::now()]);
然后我們會看到一個奇怪的現象,我們並沒有得到我們想要的結果:
我們只有content這個字段正確有了值,title
,intro
,published_at
都沒有值,這是為什么了?其實也是因為MassAssignment
的緣故,我們可以參照content的時候,在Article里面的$fillable
設置我們的可以填充的字段:
class Article extends Model { protected $fillable = [ 'title', 'intro', 'content', 'published_at' ]; }
然后再執行一次:
成功創建了一條數據,然后我們發現第二條其實並不是我們想要的,我們來刪除它:
使用delete()
方法:
$article = App\Article::find(2); $article->delete();
我們用all()來檢查一下:
這里也可以使用destroy()
,這個方法可以接受一個$id或者一個數組$ids:
App\Article::destroy(3);
最后還是放一下官方文檔:http://laravel.com/docs/5.1/eloquent
下一節
到這里基本的Eloquent也就介紹到這里了,鑒於這一節說了Model,前面也都接觸過Views和Controllers,下一節打算說說Model Views Controllers的基本流程。
Happy Hacking