プログラム言語 データベース操作 ORM

データ取得

全件
use App\Models\Test;
$tests = Test::all();

クエリビルダ
$tests = DB::table('テーブル物理名')->get();

from models.user import User

users = User.query.all()

from inventory.models import Test

tests = Test.objects.all()

protected $modelClass = ‘Tests’;
$tests = $this->Tests->find()->all();

$testsTable = $this->getTableLocator()->get('Tests');
$tests = $testsTable->find()->all();

tests = Test.scan();
db = require(‘〜/models/index’);

db.Model.findAll()
 .then(models => {
  console.log(models);
 });

主キー指定
use App\Models\Test;
$tests = Test::find(999);
$tests = Test::where('id', 999)->first() と同じ;
$tests = Test::findOrFail(999);
tests = Test.get(999);
先頭
$tests = Test::first();
$tests = $this->Tests->find()
 ->first();
末尾
$tests = Test::last();
$tests = $this->Tests->find()
 ->last();
N件
$tests = Test::take(10);
$tests = $this->Tests->find()
 ->limit(10);
存在チェック
$isExist = Test::exists();
ture/false

$isEmpty = Test::all()->isEmpty();
$isNotEmpty = Test::all()->isNotEmpty();

COUNT
$tests = Test::count();

結合先テーブルのレコード数
->withCount('モデルクラス名');

$tests = $this->Tests->find()
 ->count();
SUM
$tests = Test::get->sum(列名);
$query = $this->Tests
 ->find()
 ->where([
  
 ]);

$test = $query->select([
 '定義名' => $query->func()->sum('列名'),
])
->first();

MAX
$max = Test::max('列名');
$max:5
値のみ
$tests = Test::all()->pluck('列名');

結果 $tests = [1, 2, 3, 4, 5];

リレーション先の列名指定
$tests = Test::all()->pluck('リレーション名.列名');

$tests = $this->Tests->find()
 ->select(['列名'])
 ->enableHydration(false)
 ->all()
 ->extract('列名')
 ->toList();

結果 $tests = [1, 2, 3, 4, 5];

SELECT
$tests = Test::select(['列名', '列名'])
 ->addSelect(〜)

FROM

テーブル指定
use App\Models\Test;
$tests = Test::all();

モデルクラスのインスタンスを要素とするコレクションを取得

protected $modelClass = ‘Tests’;
$tests = $this->Tests->find()->all();

モデルクラスのインスタンスを要素とするコレクションを取得

別名
use App\Models\Test;
$tests = Test::all();

別名
$tests = Test::from('tests as t')->all();

WHERE

=
$tests = Test::where('列名', 100)
 ->where('列名', XXX) And条件
 ->orWhere('列名', XXX) Or条件
 ->get();

$tests = Test::where('列名', '<>', 100) 否定 ※!=はダメ
 ->get();

$tests = Test::whereRaw(‘列名 = 100’)->get();

from models.user import User
entries = User.query.filter_by(id=1).all()
$tests = $this->Tests->find()
 ->where([
  '列名' => 100,
  '列名' => XXX, And条件
 ]);
 ->andWhere([
  '列名' => 100,
 ]);
 ->orWhere([
  '列名' => 100,
 ]);
 ->all();
db = require(‘〜/models/index’);

db.Model.findAll({
  where: {
   id: 〜
  }
 }).then(models => {
  console.log(models);
 });

db.Model.findByPk(〜)
 .then(model => {
  console.log(model);
 });

IN/NotIN
$tests = Test::whereIn('列名', [100, 200, 300])
 ->whereNotIn('列名', [100, 200, 300])
 ->get();
$tests = $this->Tests->find()
 ->where([
  '列名 IN' => [100, 200, 300],
 ]);
 ->all();
BETWEEN
$tests = Test::whereBetween('列名', [100, 200])
 ->get();
$tests = $this->Tests->find()
 ->where(function ($exp) {
  $timestamp = FrozenTime::now()->subDay(1);

  return $exp->between(
   'Tests.created',
   $timestamp->startOfDay()->toDateTimeString(),
   $timestamp->endOfDay()->toDateTimeString()
  );
 })
 ->all();

NULL判定
$tests = Test::whereNull(列名)
->orWhereNull(列名); OR条件
->whereNotNull(列名); AND条件
->orWhereNotNull(列名); OR条件
->get();
A AND (B OR C)
$tests = Test::where(function($query){
 return $query
  ->where(〜)
  ->orWhere(〜);
})
->get();
LIKE
 $tests = Test::where('列名', 'LIKE', "%検索語%")
  ->get();

 $tests = Test::where('列名', 'NOT LIKE', "%検索語%")
  ->get();

GROUPBY

 $tests = Test::groupBy('列名')
  ->get();

JOIN

INNER JOIN
use App\Models\Test;
$tests = Test::with('結合先テーブルクラス名')->all();

$tests = Test::with(['結合先テーブルクラス名' => function($query){
 $query->where('結合先テーブル列名', 'LIKE', '%〜%');
}])->get(),

↓は可能だがEager Loadingを使用しない為にメリット無し
$tests = Test::join(
 '結合先テーブル物理名',
 '結合先テーブル物理名.列名', '=', 'テーブル物理名.列名'
)
->get();

結果
foreach($tests as $t){
 $t->結合先テーブルクラス名->〜;
}

from .models import Test
from .models import Other

tests = Test.objects.select_related('other').all()

tests = Other.objects.prefetch_related('test').all()

リレーション定義済の場合
$tests = $this->Tests
 ->contain([
  '結合先テーブルクラス名1',
  '結合先テーブルクラス名2',
  結合先と更に結合
  '結合先テーブルクラス名3' => [
   '結合先テーブルクラス名4',
  ],
  結合条件指定
  '結合先テーブルクラス名5' => function (Query $query) use ($test) {
   return $query->where(['結合先テーブルクラス名5.列名' => $test->id]);
  },
 ])
 ->find()->all();

結果
foreach($tests as $t){
 $t->結合先テーブル名->〜;
}

結合先テーブルのデータは取得しない場合1
$tests = $this->Tests
 ->innerJoinWith('結合先テーブルクラス名6')
 ->innerJoinWith('結合先テーブルクラス名7', function ($q) use ($test) {
  return $q
   ->where(['結合先テーブルクラス名7.列名' => $test->id]);
 })
 ->find()->all();

結合先テーブルのデータは取得しない場合2
$tests = $this->Tests
 ->join()
  'table' => 'テーブル物理名',
  'alias' => 'テーブル別名',
  'type' => 'INNER',
  'conditions' => 'テーブル別名.列名 = 結合元テーブル名.列名',
 ->find()->all();

LEFT JOIN
use App\Models\Test;
$tests = Test::leftJoin(
  '結合先テーブル物理名',
  '結合先テーブル物理名.列名', '=', 'テーブル物理名.列名'
 )
 ->get();

結果
foreach($tests as $t){
 $t->結合先テーブルクラス名->〜;
}

リレーション定義済の場合
$tests = $this->Tests
 ->contain([
  〜
 ])
 ->find()->all();

結合先テーブルのデータは取得しない場合1
$tests = $this->Tests
 ->leftJoinWith('結合先テーブルクラス名6')
 ->leftJoinWith('結合先テーブルクラス名7', function ($q) use ($test) {
  return $q
   ->where(['結合先テーブルクラス名7.列名' => $test->id]);
 })
 ->find()->all();

結合先テーブルのデータは取得しない場合2
$tests = $this->Tests
 ->join()
  'table' => 'テーブル物理名',
  'alias' => 'テーブル別名',
  'type' => 'LEFT',
  'conditions' => 'テーブル別名.列名 = 結合元テーブル名.列名',
 ->find()->all();

結合先テーブルのデータも取得する場合
$tests = $this->Tests
 ->matching('結合先テーブルクラス名8')
 ->matching('結合先テーブルクラス名8', function ($q) use ($test) {
  return $q
   ->where(['結合先テーブルクラス名8.列名' => $test->id]);
 })
 ->find()->all();

結果
foreach($tests as $t){
 $t->_matchingData['結合先テーブルクラス名']->〜;
}

has/doesnt
use App\Models\Test;

結合先テーブルのレコードがあるもののみ取得
$tests = Test::has('リレーション名') ※結合先テーブル物理名ではない
 ->orHas('リレーション名') ※結合先テーブル物理名ではない
 ->whereHas(function($query){
  return $query->where(〜);
 })
 ->get();

hasの条件指定も可
$tests = Test::has('リレーション名', function($query) { ※結合先テーブル物理名ではない
 検索条件
 return $query->where(〜);
})〜

結合先テーブルのレコードがないもののみ取得
$tests = Test::doesntHave('リレーション名') ※結合先テーブル物理名ではない
 ->orDoesntHave('リレーション名') ※結合先テーブル物理名ではない
 ->whereDoesntHave(function($query){
  return $query->where(〜);
 })
 ->get();

ORDER BY

$tests = Test::orderBy(列名, 'ASC')
 ->orderBy(列名, 'DESC')
 ->get();

サブクエリ

SELECT句
use App\Models\Test;
$tasks = Test::leftJoin(〜)
 ->leftJoin(〜)
 ->select()
 ->selectSub(
   use App\Models\TestMany;
  TestMany::selectRaw('count(*)')
   ->whereRaw('副問い合わせ先テーブル名.列名 = 〜.id')
  , 'SubCount')
 ->get();

※with(EargerLoading)を用いてのサブクエリは調査中

FROM句
<span class=”gray”>use App\Models\Test;
$subquery = Test::select([
 DB::raw('IFNULL(col1, id) AS col1'),
 'col2',
])
->toSql();

$counts = DB::table(DB::raw("(${subquery}) AS counts"))
 ->select([
  'counts.col1',
  DB::raw('SUM(counts.col2) AS col2'),
 ])
 ->groupBy('counts.col1')
 ->get();

JOIN
use App\Models\TestSub;
$subQuery = TestSub->where(〜, 555);

use App\Models\Test;
$tasks = Test::joinSub($subQuery->getQuery(), 'サブクエリテーブル別名', function ($join) {
  $join->on('サブクエリテーブル別名.列名', '=', 'tests.列名');
 });
)

getQuery()メソッド=Eloquentのクエリビルダー化関数
これを利用せずにjoinSubしている参考サイト多数あり(要調査)

use App\Models\TestMany;
$subQuery = DB::table(〜)
 ->where(〜, 555);

use App\Models\Test;
$tasks = Test::leftJoin(
  DB::raw("($subQuery->toSql()) AS SubTable", 'SubTable.列名', '=', 'tests.id')
 )
 サブクエリのバインディングをここで指定(過去バージョンのLaravelのみ)
 ->mergeBindings($subQuery)
 ->get();

Loop

use App\Models\Test;

collectionの中身を変更しない場合に利用
Test::all()->each(function ($test) {

   continue
   return true;

   break
   return false;

   $test->aaa = 555;
   $test->save();
});

collectionの中身を変更する場合に利用
Test::all()->mapfunction ($test) {
   $test->aaa = 555;
   return $test;
});

データ更新

INSERT
【方法1 インスタンス作成→保存】
$user = new User();
$user->fill([
 'name' => 'Laravel',
 'email' => 'laravel@php.com'
]);

↓も可
$user->name = ‘Laravel’;
$user->email = ‘laravel@php.com’;

$user->save();

【方法2 インスタンス作成&保存】
$user = User::create([
 'name' => 'Laravel',
 'email' => 'laravel@php.com'
]);

【複数件INSERT】
User::createMany(
 [
  'name' => 'Laravel',
  'email' => 'laravel@php.com'
 ],
 [
  〜
 ]
);

from database import db

product = Product.query.filter_by(id=5).first()
product.name = “aaa”
db.session.add(product)
db.session.commit()

db = require(‘〜/models/index’);

db.Model.create({
 col1: 〜,
 col2: 〜,
 col3: 〜
})
.then(model => {
 console.log(model); 
});

UPDATE
$user = User::findOrFail(10);

$user->name = 'Laravel';
$user->email = 'laravel@php.com';

$user->save();

User::where(〜)
 ->update([
  '列名' => 値,
  '列名' => 値,
 ]);

from database import db

product = Product.query.filter_by(id=5).first()
product.name = “aaa”
db.session.commit()

db = require('〜/models/index');

db.Model.update({
 col1: 〜,
 col2: 〜,
 col3: 〜
},
{
 where: {
  id: 〜
 }
})
.then(model => {
 console.log(model); 
});

db.Model.findByPk(〜)
 .then(model => {
  model.col1 = 〜;
  model.col2 = 〜;
  model.col3 = 〜;
  model.save()
   .then(model => {
    console.log(model); 
   });
 });

UpdateOrInsert
User::UpdateOrCreate(
 [
  ’更新対象検索条件列名’ => 値,
  ’更新対象検索条件列名’ => 値,
 ],
 [
  ’更新列名’ => 値,
  ’更新列名’ => 値,
 ],
);
await prisma.test_table.upsert(
 where: {
  id: 5
 },
 update: {
  where対象がある場合の処理
  column: 10
 },
 以下もOK
 update: {},
 create: {
  where対象がない場合の処理
  column: 10
 },
);

DELETE
【1件削除】
User::destroy(1);

【複数件削除】
User::where('name', 'Laravel')->delete();

【全件削除】(クエリビルダ)
User::query()->delete();

from database import db

product = Product.query.filter_by(id=5).first()
db.session.delete(product)
db.session.commit()

db = require(‘〜/models/index’);

db.Model.destroy({
 where: {
  id: 〜
 }
})
.then(model => {
 console.log(model); 
});

ATTACH / DETTACH
【ATTACH】
多対多のリレーションレコードを挿入
$user = User::find(1);

usersとrolesとの中間テーブルにroles.id=999のレコードを挿入
$user->roles()->attach(999);

挿入時の中間テーブルレコードを作成
$user->roles()->attach(999, ['expires' => $expires]);

【DETTACH】
usersとrolesとの中間テーブルからroles.id=999のレコードを削除
$user->roles()->detach(999);

全て削除
$user->roles()->detach();

updateExistingPivot
中間テーブルの値を更新(主キー=999)
$user->roles()->updateExistingPivot(999, ['expires' => $expires]);

中間テーブルの値がない場合は作成後、ある場合は更新(主キー=999)
$user->roles()->syncWithPivotValues(999, ['expires' => $expires], false);

SQL利用

DB::select('select * from users where active = ?', [1000]);

DB::User
 ->select(DB::raw('sum(〜) as actcnt'))
 ->selectRaw('price * ? as price_with_tax', [1.0825])
 ->whereRaw('price > IF(state = 1, ?, 100)', [200])
 ->orWhereRaw('price > IF(state = 1, ?, 100)', [200])
 ->get();

SQL生成
$sql = Test::toSql();

パラメータ付き
$query = Test::where(〜);
$sql = preg_replace_array('/\?/', $query->getBindings(), $query->toSql());