20190530のMySQLに関する記事は2件です。

Laravel-Eloquent(Mysql)で、select結果に固定値カラムを追加する方法(使用例)

mysql

select '1'  as sample;

Laravel

$list = SampleModel::select('id', DB::raw("'1'  as sample"))->get();

真偽値なんかを扱いたいときは

$list =SampleModel::select('id', DB::raw("1 = status  as sample"))->get();

trueは1が入り、falseの場合は0が入る。

どういったときに便利か

Sampleテーブルのカラムにstatusカラムが存在し、そのstatusの中身が1,2,3だった場合、1の時はこのボタンを表示したいんだけどなぁとか思ったときに、カラムを足さない場合は、

blade
@foreach($list as $item)
@if((int)$item->status === 1)

といったような文を書くことがあるとします。この形は、Viewのほうには、なるべくロジックを加えたくないし、1は何を示しているのかわかりません。そのために、SampleModelに定数を定義します。

SampleModel.php
const STATUS_HAPPY = 1;
const STATUS_SAD   = 2;

bladeを修正します。

blade
@if((int)$item->status === \App\Models\SampleModel::STATUS_HAPPY)

これで、statusがHappyの時は、なにかするんだなとわかりやすくなりましたが、if分の中が長くなってしまいました。そのため、データにstatusがhappyかどうかのフラグを持たせる処理を作ってみます。

$list = SampleModel::select('id', 'status')->map(function ($row){
            $row->is_happy = ((int)$row->status === SampleModel::STATUS_HAPPY);
        });
blade
@if($item->is_happy)

先ほどより、bladeのほうの処理は、短くなりよくなりました。ただ、phpの処理のほうをis_happyだけのために、mapを回したく無く感じますので、selectでとっちゃいます。

$list = SampleModel::select('id', 'status', DB::raw(SampleModel::STATUS_HAPPY. ' = status as is_happy'))->get();

これで、statusカラムの中身とSampleModel::STATUS_HAPPYが一致した場合はis_happyは1で、一致しない場合は0が入りますので、
bladeでそのまま使えます。

blade
@if($item->is_happy)

アクセサを使った書き方

ありがたいコメントをいただきましたので、追記させていただきます。
Laravelには、アクセサ(カラム定義)機能がありまして、getカラム名Attribute()で取得するカラムのフォーマットを定義したり、もともと存在しないカラムを追加することができます。

// SampleModel
public function getIsHappyAttribute() {
    return (int)$this->status === static::STATUS_HAPPY;
}

// controller
$list = SampleModel::select(['id', 'status'])->get();

// blade
@foreach ($list as $item)
@if ($item->is_happy)

注意点としましては、SampleModel::select(['id', 'status'])->get()をforeachで回した際は、is_happyは取得できますが、toArray()を使ってしまうと、is_happyを取得できなくなります。

まとめ

アクセサを使う方法が1番、それでもダメな特殊ケースの場合のみ、DB::rawを使って、カラムを付け加える方針で今後やってこうと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel 2つの異なるテーブルを合わせて、ページネーションをかける

Apple・Lemonテーブル

public function test(Request $request)
{
    $subQuery = Apple::from('apples as A')
        ->select('A.id', 'A.name');

    $list = Lemon::from('lemons as L')
        ->select('L.id', 'L.name')
        ->UnionAll($subQuery)
        ->orderBy('name', 'asc')
        ->paginate(10);

    return view('test',
        [
            'paginate' => $list,
        ]
    );
}

unionは、重複を削除します。UnionAllは重複を削除しません。
union allコストについて参考記事

異なるDBを見たい場合

public function test(Request $request)
{
    $subQuery = Apple::from('sample1.apples as A')
        ->select('A.id', 'A.name');

    $list = Lemon::from('sample2.lemons as L')
        ->select('L.id', 'L.name')
        ->UnionAll($subQuery)
        ->orderBy('name', 'asc')
        ->paginate(10);

    return view('test',
        [
            'paginate' => $list,
        ]
    );
}

テーブルの前にDB名.で指定すると別々のDBを見に行ってくれます。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む