少しややこしい表現になりますが、
リレーション先の複数のカラムをソートする のではなく、
リレーション先のカラムを使って親データをソート します
\App\Shirt::with('size')
->select('shirts.*', \DB::raw('(SELECT sort FROM sizes WHERE shirts.size_id = sizes.id limit 1 ) as sort'))
->orderBy('sort', 'ASC')
->get(); // または paginate( $limit );
limit 1 をつけないと、複数行ある時に 「Subquery returns more than 1 row」エラーが返ります
Laravel 5.6.19 から は DB::raw を使用する代わりに joinSub()、leftJoinSub()、rightJoinSub()が追加されたようです。
DB::table('table')->joinSub('select * from "subtable"', 'sub', ...);
DB::table('table')->leftJoinSub(function ($q) { $q->from('subtable'); }, 'sub', ...);
DB::table('table')->rightJoinSub(DB::table('subtable')->where('foo', 'bar'), 'sub', ...);
引用元 : https://goo.gl/2UPi1E
$insert_data = [
'id' => 1001 ,
'user_name' => 'テスト太郎'
];
IDがガードされている場合、次のようにすると user_name のみ INSERTするSQL文が実行されます。
$model = new MyModel();
$model->fill($insert_data)->save();
↓ 明示的に ID にも値を入れて INSERT する場合はこのようにします。
$model = new MyModel();
$model->insert($insert_data);
ただし この方法では自動的に created_at にインサート時刻が入りません。 そこで明示的に現在時刻を渡してあげます。
$insert_data['created_at'] = new \Carbon\Carbon();
モデルファイルに $appends プロパティをセットします
// SELECTされるデータセットに次の独自カラムを追加する
protected $appends = ['_editable_flag' , '_email_aisatsu' ];
任意のタイミングで appends に追加したいときにはメソッドを使用します。
return $user->append('is_admin')->toArray();
Laravelのモデル(Eloquent)の結果セット(Collection)に手動で任意のカラムを追加するには map() を使用します。
// コレクションのすべてのデータにurl = http://your.url/here を追加
$collection->map(function ($v) {
$v['url'] = 'http://your.url/here';
return $v;
});
// コレクションそれぞれに count=xxx (任意の値) を追加
$collection->map(function ($v) {
$v['count'] = <計算ロジック>;
return $v;
});
user_code カラムを隠して結果セットをjsonで返します
$collection->setHidden(['user_code'])->toJson(JSON_UNESCAPED_UNICODE)
getCollection() で コレクションを取り出してから行います
$paginator->getCollection()->map(function ($v) {
$v['count'] = <計算ロジック>;
return $v;
});
少し書式を変えたいときは Accessor /Mutator を使いましょう
モデルファイルに以下を記述
/**
* ● アクセサー : ->_star_mark で is_starred=1 の時に ☆ を表示する
*
*/
public function getStarMarkAttribute()
{
if ($this->attributes['is_starred'] == 1){
return '<div class="text-warning">★</div>';
}
}
呼び出し方
$model->star_mark
/**
* アクセサー : 「->dispatch_date_ja」 で 値「dispatch_date」が存在する時にフォーマットして表示する。存在しない場合は未発送を返す。
*/
public function getDispatchDateJaAttribute()
{
if ( $this->attributes['dispatch_date'] != null ){
$c = new \Carbon\Carbon($this->attributes['dispatch_date']);
return $c->format('m/d');
} else {
return '<span class="text-danger">未発送</span>';
}
}
呼び出し方
$model->dispatch_date_ja
LaravelでEloquentを使ってリレーションを設定し、リレーション先のテーブルを取得する方法です。
次のような2つのテーブルがあるとします
・「チーム」(teams)
・「ユーザー」(users)
このようにチームの中に複数のユーザーが所属するとします
─── マイチーム
├── 鈴木 一郎
├── 山田 太郎
├── 中村 二郎
モデル /app/Team.php
/**
* 1対多リレーション
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function users() // 複数形(users)にする
{
// 「is_deleted = 0」のデータを「idの大きい順」で取得する
return $this->hasMany('App\User')->where('is_deleted', 0)->orderBy('id', 'DESC');
}
(取得条件やソート順を指定することができます。)
モデル /app/User.php
public function team() // 単数形(team)にする
{
return $this->belongsTo('App\Team');
}
use App\Team;
$all_teams = Team::with('users')->get();
dd( $all_teams->toArray() );
(実は with() メソッドを指定しなくても、Bladeテンプレートの中で リレーションオブジェクトを呼び出そうとすると自動取得されます。 ただ、自動取得が100回あると100回SQLクエリが投げられるので非効率です。with()メソッドだと in句 で一撃で取得してきます。)
方法1: with() を使ったやり方
$user = User::with('team')->find( Auth::user()->id );
dd( $user->toArray() );
実行されるSQL文
select * from `users`";
select * from `teams` where `teams`.`id` in (?); // ? は プレースホルダ
方法2: LEFT JOIN を使ったやり方
$user = User::leftJoin('teams','teams.id','=','users.team_id')->find( Auth::user()->id );
Mydump::dump( $user->toArray() );
実行されるSQL文
select * from `users` left join `teams` on `teams`.`id` = `users`.`team_id` where `users`.`id` = ? limit 1
$all_users = DB::table('users')
->leftJoin('teams','teams.id','=','users.team_id')
->get();
Mydump::dump( $all_users );
その他リレーションの参考: https://laravel-news.com/eloquent-tips-tricks
マイグレーションをやり直した時に、DBデータも自動で登録できるようにシーダーを使ってデータを作成しておくと マイグレーションのやり直しがとても楽にできます。
テーブル名「clients」の場合「ClientsSeeder」や「ClientsTableSeeder」といった名前をつけて作成します。
(例: clients テーブル用のシーダーファイルを作成する )
php artisan make:seeder ClientsSeeder
( database/seeds/ClientsSeeder.php が作成されます )
database/seeds/ClientsSeeder.php
<?php
use Illuminate\Database\Seeder;
class ClientsSeeder extends Seeder
{
/**
* Run the database seeds.
* @return void
*/
public function run()
{
DB::table("clients")->insert([
'id' => 1 ,
'client_name' => 'テスト商事' ,
'tel_name' => '012-345-6789' ,
'fax_name' => '012-345-6780',
]);
DB::table("clients")->insert([
'id' => 2 ,
'client_name' => 'てすとの商事' ,
'tel_name' => '112-345-6789' ,
'fax_name' => '112-345-6780',
]);
}
}
database/seeds/DatabaseSeeder.php に作成したシーダーファイルを記述して呼び出します
<?php
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
* @return void
*/
public function run()
{
$this->call([
ClientsSeeder::class , // 追加
]);
}
}
php artisan db:seed
composer の autoload を再読み込みしてから実行するとうまく実行できます。
composer dump-autoload
php artisan db:seed