はじめに
Java(Spring)での開発経験がある状態で、PHP(Laravel)の現場に入ることになりました。
事前にサンプルコード等で学習を進めようと奮闘しているところです![]()
まず感じたのが、
「DBアクセスの書き方が違う」
という違和感でした。
DBアクセスは開発にかかせない要素のため、
学習がてらこの記事で整理したいと思いました![]()
前提
この記事は以下の方を対象とした内容になります![]()
- PHP Laravel 初心者
Java(Spring)のDBアクセス方法
Springについておさらいします。
Springでは、DBアクセスは基本的に「Repository」という層で行います。
① Repositoryを定義
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
User findById(Long id);
}
② Serviceから呼び出す
RepositoryをServiceクラスから呼び出し、処理を実行します。
(Repository直接使用せずにServiceクラスを経由)
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public User getUser(Long id) {
return userRepository.findById(id).orElse(null);
}
}
PHP(Laravel)のDBアクセス方法
Laravelでは、非常にシンプルに書くことができます。
これだけでDBからデータが取れます![]()
$user = User::find(1);
Laravelでは「Eloquent(ORM)」という仕組みを使っています。
これは「Active Recordパターン」と呼ばれるもので、
モデル自身がDB操作を持つのが特徴です。
例) データ取得・更新
$user = User::find(1);
$user->name = "Taro";
$user->save();
User というモデルがそのままDBとつながっているイメージのため、
Repositoryを定義してget, updateメソッドを呼ぶ...といった書き方と異なります。
複雑なSQL(JOINなど)はどうするのか
単一テーブルについてはModelで完結しそうですが、他テーブルとの結合等、
実務ベースのSQLを組む場合はどうするのか疑問に思いましたので、
書き方を整理してみます。
主に4つの書き方がある
Laravelでは用途に応じて、以下のように使い分けができます。
| 方法 | 用途 |
|---|---|
| リレーション | テーブルの関連を扱うとき |
| クエリビルダ | 複雑なJOINや条件 |
| モデルメソッド | 再利用したい処理 |
① リレーション
Laravelでは「JOINを書く」のではなく、
テーブル同士の関係を定義するのが基本の書き方になります。
モデルに定義
users と posts テーブルの結合
class User extends Model {
public function posts() {
return $this->hasMany(Post::class);
}
}
呼び出し
$user = User::with('posts')->find(1);
この書き方で、JOINのような処理をしてくれます。
② クエリビルダ
JOINや条件が複雑な場合やSQLっぽく書きたいときに使用します。
$users = DB::table('users')
->join('posts', 'users.id', '=', 'posts.user_id')
->where('posts.created_at', '>', now()->subDays(7))
->select('users.*', 'posts.title')
->get();
見た目的にはかなりSQLに近い感覚で書けそうな文法です。
③ Modelにメソッドとしてまとめる
同じクエリを何度も使う場合は、ScopeとしてModelに定義することを推奨します。
class User extends Model {
public function scopeActiveUsersWithPosts($query) {
return $query->join('posts', 'users.id', '=', 'posts.user_id')
->where('posts.is_active', true)
->select('users.*');
}
}
ポイント
- Scopeでは
get()を書かない のが重要 - あくまで「クエリの一部」を定義しているだけ
- 最後に
get()を呼ぶことでデータを取得する
呼び出し
$users = User::activeUsersWithPosts()->get();
呼び出し側で条件を追加することも可能。
$users = User::activeUsersWithPosts()
->where('users.age', '>', 20) // 年齢の条件を追加
->get();
設計の考え方について
Spring(Repositoryパターン)
- DB操作はRepositoryクラスに集約している
- エンティティは「データを持つだけのクラス」のため、設計としてはっきり分かれている
Laravel(Active Record)
- Model自身がDB操作を持つ
- シンプルではあるが、密結合のため将来的なメンテナンス負荷が想定される
思想の違いについてまとめ
Java(Spring)
- 設計重視(しっかり分ける)
- レイヤー構造(Controller / Service / Repository)
- 安全で拡張しやすい
PHP(Laravel)
- シンプルで直感的
- モデルから直接DB操作
- とにかく書くのが速い
JavaもPHPもそれぞれメリットがあり、
そもそも比較対象とするのは誤りなのかとも思うようになってきました。
一部の文法は書き方が似ているところもありますが、
静的型付けと動的型付けで根本的に異なる言語だと意識しながら歩み寄る必要ありそうです![]()
おわりに
最初はLaravelの自由さに戸惑いましたが、開発スピードの速さは魅力的だと感じました。
最終的には現場のソースコードがどのように書かれているかというお作法次第でもあるので、そこでのやり方を踏襲しつつ、「こんな方法もあったな」という記憶の棚を引き出すきっかけになると円滑に業務が進みそうだと思いました。
雑多な内容になりましたが、PHP, Laravelへの理解をより深めたいと思う良い機会でした![]()