orm 系列 之 Eloquent使用2

上一篇介紹了Eloquent的migrations和Scheme Builder功能冤馏,本文介紹Eloquent最重要的Model。

本文會(huì)按照下面的順序介紹:

  • Model的創(chuàng)建
  • CRUD操作
  • 查詢和聚合操作
  • Hydrate
  • 組合查詢

Model創(chuàng)建

在laravel中梢褐,創(chuàng)建一個(gè)model非常簡(jiǎn)單调煎,我們可以通過(guò)下面的命令創(chuàng)建

php artisan make:model Book

默認(rèn)在app目錄下生成一個(gè)Book.php文件捞附,打開(kāi)后看到:

class Book extends Model
{
    //
}

就這么簡(jiǎn)單的幾行泛释,我們就可以使用了,從這個(gè)model出發(fā)甚带,我們可能想要知道Book是在哪個(gè)表中的她肯,這個(gè)時(shí)候佳头,我們可以設(shè)置$table屬性,同時(shí)晴氨,我們想要設(shè)置主鍵及其類型康嘉,我們就設(shè)置$primaryKey,$keyType,同時(shí)籽前,我們可能還想要指定數(shù)據(jù)庫(kù)連接亭珍,當(dāng)然也行,通過(guò)設(shè)置$connection即可聚假,于是我們的Book就變?yōu)椋?/p>

class Book extends Model
{
    protected $connection = 'mysql';
    protected $table = 'books';
    protected $primaryKey = 'id';
    protected $keyType = 'int';
}

當(dāng)然块蚌,上面這些屬性不設(shè)置也行闰非,就使用這些值的默認(rèn)值就可以膘格。

CRUD操作

有了模型,讓我們來(lái)完成基本的CRUD操作财松,先是創(chuàng)建動(dòng)作瘪贱,

Route::get( 'book_create', function () {
    $book              = new Book;
    $book->title       = 'My First Book!';
    $book->pages_count = 230;
    $book->price       = 10.5;
    $book->description = 'A very original lorem ipsum dolor sit amet...';
    $book->save();
    echo 'Book: ' . $book->id;
} );

我們通過(guò)save就可以完成insert操作,此處有幾個(gè)tricky方法辆毡,首先是我們的Model中不存在title這些字段菜秦,那是怎么設(shè)置的呢?然后就是save操作的時(shí)候舶掖,怎么知道是insert Or update呢球昨?

先回答第一個(gè)屬性問(wèn)題

// class model
public function __set($key, $value)
{
    $this->setAttribute($key, $value);
}
public function __get($key)
{
    return $this->getAttribute($key);
}

model中通過(guò)magic method,可以正確的設(shè)置和獲取屬性眨攘。接著回答第二個(gè)問(wèn)題主慰,save怎么知道是insert還是update呢?

if ($this->exists) {
    $saved = $this->isDirty() ?
    $this->performUpdate($query, $options) : true;
}
else {
    $saved = $this->performInsert($query);
}

我們可以看到Model中有個(gè)屬性exists表明記錄是否在數(shù)據(jù)庫(kù)中鲫售,此處還有個(gè)有意思的函數(shù)isDirty共螺,看下實(shí)現(xiàn)

public function getDirty()
{
    $dirty = [];

    foreach ($this->attributes as $key => $value) {
      if (! array_key_exists($key, $this->original)) {
        $dirty[$key] = $value;
      } elseif ($value !== $this->original[$key] &&
                ! $this->originalIsNumericallyEquivalent($key)) {
        $dirty[$key] = $value;
      }
    }

    return $dirty;
}

此處會(huì)存儲(chǔ)一個(gè)從數(shù)據(jù)庫(kù)中加載出來(lái)的數(shù)據(jù)original,然后通過(guò)現(xiàn)在的attributesoriginal比較來(lái)知道哪些字段需要更新情竹,在執(zhí)行更新操作的時(shí)候藐不,自然就是下面的操作了,只會(huì)跟新dirty字段秦效。

$dirty = $this->getDirty();

if (count($dirty) > 0) {
    $this->setKeysForSaveQuery($query)->update($dirty);

    $this->fireModelEvent('updated', false);
}

下面是讀取操作雏蛮,我們可以執(zhí)行在命令行中執(zhí)行php artisan tinker進(jìn)入命令中,然后通過(guò)下面的方法阱州,返回一些數(shù)據(jù):

>>> App\Book::all()
=> Illuminate\Database\Eloquent\Collection {#711
     all: [
       App\Book {#713
         id: 1,
         title: "My First Book!",
         pages_count: 230,
         price: "10.50",
         description: "A very original lorem ipsum dolor sit amet...",
         created_at: "2016-12-01 15:13:35",
         updated_at: "2016-12-01 15:13:35",
       },
     ],
   }

查詢方法有很多底扳,我們不做過(guò)多的介紹,我們此處來(lái)看下贡耽,all方法的執(zhí)行衷模,all在Model中是不存在的鹊汛,那怎么調(diào)用的呢?這也是php的magic method實(shí)現(xiàn)的阱冶,

public function __call($method, $parameters)
{
    if (in_array($method, ['increment', 'decrement'])) {
      return call_user_func_array([$this, $method], $parameters);
    }

    $query = $this->newQuery();

    return call_user_func_array([$query, $method], $parameters);
}
public static function __callStatic($method, $parameters)
{
    $instance = new static;

    return call_user_func_array([$instance, $method], $parameters);
}

其實(shí)現(xiàn)都是一致的刁憋,都是通過(guò)調(diào)用Eloquent/Builder來(lái)實(shí)現(xiàn)的。

下面我們來(lái)看更新操作怎么做的

>>> $book1 = App\Book::find(1);
=> App\Book {#709
     id: 1,
     title: "My First Book!",
     pages_count: 230,
     price: "10.50",
     description: "A very original lorem ipsum dolor sit amet...",
     created_at: "2016-12-01 15:13:35",
     updated_at: "2016-12-01 15:13:35",
   }
>>> $book1->price = 12;
=> 12
>>> $book1->save();

上面的步驟就好木蹬,save通過(guò)之前的分析至耻,會(huì)自動(dòng)更新price。

查詢和聚合

Eloquent提供了豐富的查詢方式镊叁,通過(guò)前面的__call方法分析尘颓,我們知道,這些最終調(diào)用的都是Eloquent/Builder方法晦譬,where方法也不例外疤苹,where其最簡(jiǎn)單的形式如下:

where('field_name', 'operator', 'term')

然后通過(guò)連貫操作,我們可以任意的組合where條件敛腌,此處term的含義就是我們?cè)趺粗vwhere條件組裝卧土,是condition1 AND condition2 還是 condition1 OR condition2.

聚合操作如'count', 'min', 'max', 'avg', 'sum',這些操作在實(shí)現(xiàn)上都是通過(guò)下面一段類似的代碼實(shí)現(xiàn):

public function max($column)
{
    return $this->aggregate(__FUNCTION__, [$column]);
}

通過(guò)_FUNCTION_來(lái)闖入方法名像樊。

Hydrate

這個(gè)功能其實(shí)我們?cè)谥?a href="http://www.reibang.com/p/d867ced4c2fe" target="_blank">The Clean Architecture in PHP 讀書筆記(十)就提到過(guò)這個(gè)問(wèn)題尤莺,如何能在數(shù)據(jù)庫(kù)中記錄和我們的Model之間進(jìn)行轉(zhuǎn)換,此處有轉(zhuǎn)換有兩個(gè)方向生棍,先看數(shù)據(jù)記錄怎么變?yōu)镸odel颤霎,此處有幾個(gè)方法

  1. Model::create新建,
  2. Model::hydrate將數(shù)據(jù)庫(kù)數(shù)據(jù)轉(zhuǎn)換為Model

當(dāng)時(shí)遇到的問(wèn)題有字段對(duì)應(yīng)涂滴,另一個(gè)是安全問(wèn)題友酱,具體來(lái)說(shuō)就是怎么知道數(shù)組中的key和Model的attribute對(duì)應(yīng),Eloquent的方法是直接將屬性存儲(chǔ)為一個(gè)$attributes數(shù)組氢妈,然后由用戶自己根據(jù)字段名進(jìn)行獲取粹污,但是,其實(shí)這也會(huì)有個(gè)問(wèn)題首量,就是一旦字段名更改了壮吩,我們必須要去更改所有直接使用字段名的地方。

當(dāng)然這個(gè)問(wèn)題存在了加缘,Eloquent就嘗試著去解決了鸭叙,這就用到了Accessors and mutators,直接看代碼:

public function getPriceAttribute($value)
{
    return '$ ' . $value;
}

public function setTitleAttribute( $value )
{
    $this->attributes['title'] = strtolower($value);
}

通過(guò)將值截?cái)嗉鸷辏覀兛梢栽诶锩孀鑫覀兿胱龅娜魏尾僮魃虮矗瑢?shí)現(xiàn)屬性的轉(zhuǎn)換。

另一個(gè)是安全問(wèn)題勋乾,我們?cè)趺粗滥男┳侄问荕odel的屬性宋下,這是通過(guò)可以被賦值屬性的“白名單”$fillable和可以被賦值屬性的$guarded“黑名單”完成的嗡善,在白名單里面的就是可以設(shè)置的屬性,黑名單里面的是不能的学歧。

組合查詢

組合查詢也是非痴忠酷的一個(gè)功能,我們?cè)陂_(kāi)發(fā)中時(shí)常會(huì)寫出各種各樣的名字查詢枝笨,如getLongBook,getCheapBook,getLongAndCheapBook等等袁铐,每次這種查詢我們都必須要去寫個(gè)方法,苦不堪言横浑,那有什么好的方法呢剔桨?這個(gè)時(shí)候Eloquent提供了一個(gè)很酷的功能。

public function scopeLong(  Query $query, $long = 700)
{
    return $query->where( 'pages_count', '>', $long );
}
public function scopeCheap(  Query $query, $price = 500)
{
    return $query->where( 'price', '<', $price );
}
>>> App\Book::cheap()->long()->toSql()
=> "select * from `books` where `price` < ? and `pages_count` > ?"
>>>

我們通過(guò)Model的scope功能徙融,我們就能快速實(shí)現(xiàn)組合查詢洒缀,以后再也不用煩惱的寫查詢了。

以上就是Eloquent的Model操作的基本介紹张咳,下節(jié)將會(huì)介紹Eloquent的關(guān)系帝洪。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末似舵,一起剝皮案震驚了整個(gè)濱河市脚猾,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌砚哗,老刑警劉巖龙助,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異蛛芥,居然都是意外死亡提鸟,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門仅淑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)称勋,“玉大人,你說(shuō)我怎么就攤上這事涯竟∩南剩” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵庐船,是天一觀的道長(zhǎng)银酬。 經(jīng)常有香客問(wèn)我,道長(zhǎng)筐钟,這世上最難降的妖魔是什么揩瞪? 我笑而不...
    開(kāi)封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮篓冲,結(jié)果婚禮上李破,老公的妹妹穿的比我還像新娘宠哄。我一直安慰自己,他們只是感情好嗤攻,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布琳拨。 她就那樣靜靜地躺著,像睡著了一般屯曹。 火紅的嫁衣襯著肌膚如雪狱庇。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天恶耽,我揣著相機(jī)與錄音密任,去河邊找鬼。 笑死偷俭,一個(gè)胖子當(dāng)著我的面吹牛浪讳,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播涌萤,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼淹遵,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了负溪?” 一聲冷哼從身側(cè)響起透揣,我...
    開(kāi)封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎川抡,沒(méi)想到半個(gè)月后辐真,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡崖堤,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年侍咱,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片密幔。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡楔脯,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出胯甩,到底是詐尸還是另有隱情昧廷,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布蜡豹,位于F島的核電站麸粮,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏镜廉。R本人自食惡果不足惜弄诲,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧齐遵,春花似錦寂玲、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至伶授,卻和暖如春断序,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背糜烹。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工违诗, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人疮蹦。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓诸迟,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親愕乎。 傳聞我的和親對(duì)象是個(gè)殘疾皇子阵苇,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

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