首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

ThinkPHP 關聯查詢完整指南:table、join、原生 SQL 多表查詢實戰

     編輯:PHP 綜合知識

關聯查詢方法對比

ThinkPHP 提供多種多表查詢方式,各有適用場景。本文系統整理 `table()`、`join()`、原生查詢、多表查詢四大方法的用法與優缺點。

方法一:table() 多表查詢

適用於簡單的多表關聯,需手寫 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();

特點

  • SQL 直觀,接近原生寫法
  • 需手動指定表別名、關聯條件
  • 適合固定、簡單的多表查詢

方法二:join() 關聯查詢

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();

方法三:原生 SQL 查詢

複雜查詢、存儲過程、特定資料庫功能時使用:

$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')));

方法四:多表查詢(table 陣列格式)

// 字串格式
$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();

關聯模型關係定義(ThinkPHP 3.2+ 推薦)

在 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()鏈式調用、靈活構建

效能優化技巧

  1. 只選需要欄位:`field('id,name')` 避免 `SELECT *`
  2. 索引覆蓋:WHERE/JOIN/ORDER BY 欄位建立複合索引
  3. 避免大表 JOIN:考慮冗余字段、Redis 快取、資料庫 View
  4. 分頁優化:大偏移量改用 `WHERE id > last_id LIMIT 20`
  5. EXPLAIN 分析:定期檢查慢查詢執行計劃

常見錯誤避坑

  • `field()` 中關聯表欄位需加表別名:`user.name` 而非 `name`
  • `join()` 條件中使用模型名而非表名:`user.id` 而非 `think_user.id`
  • MANY_TO_MANY 需正確設定 `relation_table` 與 `relation_foreign_key`
  • 原生 SQL 中表名需手動加前綴:`think_user` 或使用 `C('DB_PREFIX')`

根據業務複雜度選擇合適的查詢方式,善用關聯模型簡化代碼,關鍵路徑用原生 SQL 確保效能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved