ThinkPHP 提供多種多表查詢方式,各有適用場景。本文系統整理 `table()`、`join()`、原生查詢、多表查詢四大方法的用法與優缺點。
適用於簡單的多表關聯,需手寫 WHERE 條件:
$list = $user->table('user_status stats, user_profile profile')
->where('stats.id = profile.typeid')
->field('stats.id as id, stats.display as display, profile.title as title, profile.content as content')
->order('stats.id desc')
->select();
ThinkPHP 封裝的 JOIN 語法,支援 LEFT/RIGHT/INNER:
$user = new Model('user');
$list = $user->join('RIGHT JOIN user_profile ON user_stats.id = user_profile.typeid')
->select();
// 多重 JOIN
$list = $user
->join('LEFT JOIN user_profile ON user.id = user_profile.user_id')
->join('LEFT JOIN user_status ON user.status_id = user_status.id')
->field('user.*, user_profile.realname, user_status.name as status_name')
->where('user.is_delete=0')
->select();
// 使用 table 陣列格式指定別名
$list = $user
->table(array('user' => 'u', 'user_profile' => 'p'))
->join('LEFT JOIN user_status s ON u.status_id = s.id')
->field('u.*, p.realname, s.name as status')
->select();
複雜查詢、存儲過程、特定資料庫功能時使用:
$Model = new Model();
$sql = 'SELECT a.id, a.title, b.content
FROM think_test1 AS a, think_test2 AS b
WHERE a.id = b.id ' . $map . '
ORDER BY a.id ' . $sort . '
LIMIT ' . $p->firstRow . ',' . $p->listRows;
$voList = $Model->query($sql); // 查詢返回陣列
// $Model->execute($sql); // 執行 INSERT/UPDATE/DELETE
$sql = 'SELECT * FROM user WHERE status = ? AND create_time > ?';
$list = $Model->query($sql, array(1, strtotime('-7 days')));
// 字串格式
$Model->field('user.name, role.title')
->table('think_user user, think_role role')
->limit(10)
->select();
// 陣列格式(推薦:清晰指定別名)
$Model->field('user.name, role.title')
->table(array('think_user' => 'user', 'think_role' => 'role'))
->limit(10)
->select();
在 Model 中定義關聯,實現鏈式操作:
class User extends Model
{
protected $_link = array(
'profile' => array(
'mapping_type' => self::HAS_ONE,
'class_name' => 'UserProfile',
'foreign_key' => 'user_id',
'mapping_fields' => 'realname,avatar,bio',
),
'posts' => array(
'mapping_type' => self::HAS_MANY,
'class_name' => 'Post',
'foreign_key' => 'author_id',
'mapping_order' => 'create_time DESC',
'mapping_limit' => 10,
),
'roles' => array(
'mapping_type' => self::MANY_TO_MANY,
'class_name' => 'Role',
'foreign_key' => 'user_id',
'relation_table' => 'user_role',
'relation_foreign_key' => 'role_id',
),
);
}
// 預載入關聯(避免 N+1)
$users = User::model()->with('profile,posts')->select();
// 動態關聯條件
$users = User::model()->with(array(
'posts' => array('condition' => 'status=1', 'limit' => 5),
))->select();
// 關聯統計
$user = User::model()->withCount('posts')->find(1);
echo $user->posts_count;
| 場景 | 推薦方法 | 理由 |
|---|---|---|
| 固定簡單多表 | table() | SQL 可見、易除錯 |
| 標準 JOIN 關聯 | join() | 框架封裝、可讀性好 |
| 複雜/特殊查詢 | 原生 SQL | 完全控制、效能最優 |
| ORM 風格開發 | 關聯模型 | 物件導向、自動預載、程式碼複用 |
| 動態條件組合 | join() + where() | 鏈式調用、靈活構建 |
根據業務複雜度選擇合適的查詢方式,善用關聯模型簡化代碼,關鍵路徑用原生 SQL 確保效能。