Laravel學習筆記七-建立博客

本節將使用用戶建立博文來學習數據模型關聯的有關知識。php

1、Laravel經常使用知識總結

1.提示信息漢化

若是用Laravel原生的表單提示錯誤信息,則是英文的,若是須要中文,則須要修改resources/lang/en的英文,這樣比較麻煩,不過,咱們可使用github開源的漢化包,而後引入該文件夾,在config/app.php配置文件裏邊修改語言包引入便可使用。laravel

2.Carbon日期友好化處理

<span class="timestamp">
    {{ $status->created_at->diffForHumans() }}
  </span>

該方法的做用是將日期進行友好化處理,咱們可使用 tinker 來查看該方法的具體輸出狀況。git

$ php artisan tinker

在 tinker 中輸出第一位用戶的建立時間以下。github

>>> $created_at = App\Models\User::first()->created_at
=> Carbon\Carbon {#704
     +"date": "1998-12-06 03:15:31.000000",
     +"timezone_type": 3,
     +"timezone": "UTC",
   }

在 tinker 中調用 diffForHumans 方法來輸出,結果以下。數據庫

>>> $created_at->diffForHumans()
=> "17 years ago"

咱們發現 diffForHumans 爲咱們生成的時間是英文的,若是要使用中文時間,則須要對 Carbon 進行本地化設置。Carbon 是 PHP DateTime 的一個簡單擴展,Laravel 將其默認集成到了框架中。app

3、Eloquent:關聯

數據表之間常常會互相進行關聯。例如,一篇博客文章可能會有多條評論,或是一張訂單可能對應一個下單客戶。Eloquent 讓管理和處理這些關聯變得很容易,同時也支持多種類型的關聯。框架

定義關聯

你可在 Eloquent 模型類內將 Eloquent 關聯定義爲函數。由於關聯像 Eloquent 模型同樣也能夠做爲強大的 查詢語句構造器(數據庫:查詢構造器),定義關聯爲函數提供了強而有力的鏈式調用及查找功能。例如:函數

$user->posts()->where('active', 1)->get();

不過,在深刻了解使用關聯以前,先讓咱們來學習如何定義每一個類型:post

1.一對一

一對一關聯是很基本的關聯。例如一個 User 模型也許會對應一個 Phone。要定義這種關聯,咱們必須將 phone 方法放置於 User 模型上。phone 方法應該要返回基類 Eloquent 上的 hasOne 方法的結果:學習

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * 獲取與指定用戶互相關聯的電話紀錄。
     */
    public function phone()
    {
        return $this->hasOne('App\Phone');
    }
}

傳到 hasOne 方法裏的第一個參數是關聯模型的類名稱。定義好關聯以後,咱們就可使用 Eloquent 的動態屬性來獲取關聯紀錄。動態屬性讓你可以訪問關聯函數,就像他們是在模型中定義的屬性:

$phone = User::find(1)->phone;

Eloquent 會假設對應關聯的外鍵名稱是基於模型名稱的。在這個例子裏,它會自動假設 Phone 模型擁有 user_id 外鍵。若是你想要重寫這個約定,則能夠傳入第二個參數到 hasOne 方法裏。

return $this->hasOne('App\Phone', 'foreign_key');

此外,Eloquent 的默認外鍵在上層模型的 id 字段會有個對應值。換句話說,Eloquent 會尋找用戶的 id 字段與 Phone 模型的 user_id 字段的值相同的紀錄。若是你想讓關聯使用 id 之外的值,則能夠傳遞第三個參數至 hasOne 方法來指定你自定義的鍵:

return $this->hasOne('App\Phone', 'foreign_key', 'local_key');

定義相對的關聯

因此,咱們能夠從 User 訪問到 Phone 模型。如今,讓咱們在 Phone 模型上定義一個關聯,此關聯可以讓咱們訪問擁有此電話的 User。咱們能夠定義與 hasOne 關聯相對應的 belongsTo 方法:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Phone extends Model
{
    /**
     * 獲取擁有此電話的用戶。
     */
    public function user()
    {
        return $this->belongsTo('App\User');
    }
}

2. 一對多

一個「一對多」關聯使用於定義單個模型擁有任意數量的其它關聯模型。例如,一篇博客文章可能會有無限多個評論。就像其它的 Eloquent 關聯同樣,能夠經過放置一個函數到 Eloquent 模型上來定義一對多關聯:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    /**
     * 獲取博客文章的評論。
     */
    public function comments()
    {
        return $this->hasMany('App\Comment');
    }
}

切記,Eloquent 會自動判斷 Comment 模型上正確的外鍵字段。按約定來講,Eloquent 會取用自身模型的「蛇形命名」後的名稱,並在後方加上 _id。因此,以此例來講,Eloquent 會假設 Comment 模型的外鍵是 post_id

一旦關聯被定義,則能夠經過 comments 屬性來訪問評論的集合。切記,由於 Eloquent 提供了「動態屬性」,所以咱們能夠對關聯函數進行訪問,就像他們是在模型中定義的屬性同樣:

$comments = App\Post::find(1)->comments;

foreach ($comments as $comment) {
    //
}

定義相對的關聯

如今咱們已經能訪問到全部文章的評論,讓咱們來接着定義一個經過評論訪問上層文章的關聯。若要定義相對於 hasMany 的關聯,可在下層模型定義一個叫作 belongsTo 方法的關聯函數:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Comment extends Model
{
    /**
     * 獲取擁有此評論的文章。
     */
    public function post()
    {
        return $this->belongsTo('App\Post');
    }
}

3. 多對多

多對多關聯要稍微比 hasOnehasMany 關聯複雜。如一個用戶可能擁有多種身份,而一種身份能同時被多個用戶擁有。舉例來講,不少用戶都擁有「管理者」的身份。要定義這種關聯,須要使用三個數據表:usersrolesrole_userrole_user 表命名是以相關聯的兩個模型數據表來依照字母順序命名,幷包含了 user_id 和 role_id 字段

多對多關聯經過編寫一個在自身 Eloquent 類調用的 belongsToMany 的方法來定義。舉個例子,讓咱們在 User 模型定義 roles 方法:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * 屬於該用戶的身份。
     */
    public function roles()
    {
        return $this->belongsToMany('App\Role');
    }
}

定義相對的關聯

要定義相對於多對多的關聯,只需簡單的放置另外一個名爲 belongsToMany 的方法到你關聯的模型上。讓咱們接着以用戶身份爲例,在 Role 模型中定義 users 方法:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Role extends Model
{
    /**
     * 屬於該身份的用戶。
     */
    public function users()
    {
        return $this->belongsToMany('App\User');
    }
}

如你所見,此定義除了簡單的參考 AppUser 模型外,與 User 的對應徹底相同。由於咱們重複使用了 belongsToMany 方法,當定義相對於多對多的關聯時,全部經常使用的自定義數據表與鍵的選項都是可用的。

關聯總結

1.一對一

$this->hasOne('App\Phone');
$this->belongsTo('App\User');

hasOne 關聯相對應的 belongsTo 方法

2.一對多

$this->hasMany('App\Comment');
$this->belongsTo('App\Post');

hasMany 關聯相對應的 belongsTo 方法

3.多對多

$this->belongsToMany('App\Role');
$this->belongsToMany('App\User');

belongsToMany 關聯相對應的 belongsToMany 方法

4.查找關聯

你能夠查找 posts 關聯並增長額外的條件相當聯,像這樣:

$user = App\User::find(1);
$user->posts()->where('active', 1)->get();

關聯方法與動態屬性

若是你不須要增長額外的條件至 Eloquent 的關聯查找,則能夠簡單的像訪問屬性同樣來訪問關聯。例如咱們剛剛的 User 及 Post 模型示例,咱們能夠像這樣來訪問全部用戶的文章:

$user = App\User::find(1);

foreach ($user->posts as $post) {
    //
}

預加載

當經過屬性訪問 Eloquent 關聯時,該關聯數據會被「延遲加載」。意味着該關聯數據只有在你使用屬性訪問它時纔會被加載。不過,Eloquent 能夠在你查找上層模型時「預加載」關聯數據。預加載避免了 N + 1 查找的問題。要說明 N + 1 查找的問題,可試想一個關聯到 Author 的 Book 模型,以下所示:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Book extends Model
{
    /**
     * 獲取編寫該書的做者。
     */
    public function author()
    {
        return $this->belongsTo('App\Author');
    }
}

如今,讓咱們來獲取全部書籍及其做者的數據:

$books = App\Book::all();

foreach ($books as $book) {
    echo $book->author->name;
}

上方的循環會運行一次查找並取回全部數據表上的書籍,接着每本書會運行一次查找做者的操做。所以,若存在着 25 本書,則循環就會執行 26 次查找:1 次是查找全部書籍,其它 25 次則是在查找每本書的做者。

很幸運地,咱們可使用預加載來將查找的操做減小至 2 次。可在查找時使用 with 方法來指定想要預加載的關聯數據:

$books = App\Book::with('author')->get();

foreach ($books as $book) {
    echo $book->author->name;
}

對於該操做則只會運行兩次查找:

select * from books

select * from authors where id in (1, 2, 3, 4, 5, ...)
相關文章
相關標籤/搜索