>  기사  >  PHP 프레임워크  >  ThinkPHP: 데이터 쿼리의 기본 원칙

ThinkPHP: 데이터 쿼리의 기본 원칙

爱喝马黛茶的安东尼
爱喝马黛茶的安东尼앞으로
2019-12-16 17:46:263055검색

ThinkPHP: 데이터 쿼리의 기본 원칙

이 기사에 포함된 데이터 쿼리의 몇 가지 기본 원칙을 프로젝트 사양에 통합하도록 노력하세요. 이는 공식이 옹호하는 모범 사례이기도 합니다. 그 전에 이전 블로그 "Db 클래스와 모델의 올바른 사용 자세를 정말 이해하고 계신가요?"를 읽어보셨기를 바랍니다.

배열 조건부 쿼리를 사용하지 마세요

헷갈리는 쿼리 구문의 대부분은 배열 쿼리 사용으로 인해 발생하며, 5.1의 배열 조건부 쿼리 사용법은 5.0과 완전히 다릅니다. 5.0 메서드에서 배열 쿼리를 사용하려면 "5.1 배열 개체 쿼리 사용 방법을 알려주세요"라는 기사를 읽어 보시기 바랍니다.

다음은 많은 초보자들이 저지르는 쿼리 실수일 수 있습니다.

$where['id'] = ['in', '1,2,3'];
User::where($where)->select();

분명히 이 쿼리적 사고는 이전 버전의 영향을 많이 받았습니다. 5.0과 비교할 때 버전 5.1의 쿼리 구문은 보다 객체 지향적입니다. 올바른 사용법은 다음과 같습니다.

$where['id'] = [1,2,3];
User::where($where)->select();

PHP 배열은 사용하기 매우 쉽기 때문에 많은 사람들이 배열 쿼리 조건을 좋아합니다(또는 객체에 대해 걱정하고 있습니까?). 그러나 쿼리 빌더를 올바르게 사용하고 모델의 관련 기능과 협력하면 쿼리 논리가 더 명확해지고 유지 관리가 쉬워질 수 있습니다.

또한 좀 더 복잡한 쿼리 조건에서는 다음 쿼리 사용법과 같이 배열을 사용하여 쿼리를 완료할 수 없습니다.

User::where('id', '>', 100)
    ->whereOr(&#39;id&#39;, &#39;<&#39;, 10)
    ->where(&#39;name&#39;, &#39;like&#39;, &#39;think%&#39;)
    ->whereColumn(&#39;name&#39;, &#39;nickname&#39;)
    ->when(&#39;80&#39;== $condition, function ($query) {
        $query->where(&#39;score&#39;, &#39;>&#39;, 80)->limit(10);
    })->select();

그러므로 5.1에서 배열 쿼리의 사용법을 모르신다면 배열 조건 쿼리를 사용하지 마세요.

문자열 쿼리 조건을 안전하게 사용하세요

문자열 쿼리 조건을 사용할 때 외부 변수가 있는 경우 반드시 매개변수 바인딩을 사용하고, 다른 쿼리 생성자 메서드와 결합할 수 있는 whereRaw 메서드를 사용하는 것이 좋습니다.

User::whereRaw("id = :id AND name = :name", [
        &#39;id&#39; => [$id, \PDO::PARAM_INT] , 
        &#39;name&#39; => $name
    ])->where(&#39;status&#39;, 1)
    ->order(&#39;id&#39;, &#39;desc&#39;)
    ->select();

성능이 더 우려되는 일부 쿼리의 경우 쿼리나 실행 메서드를 직접 사용할 수도 있지만, 매개변수의 안전성에 주의하고 다양한 데이터베이스의 이식 문제도 고려해야 합니다.

Db::query("select * from think_user where id=? AND status=?", [8, 1]);
Db::execute("update think_user set name=:name where status=:status", [&#39;name&#39; => &#39;thinkphp&#39;, &#39;status&#39; => 1]);

SQL 함수를 사용하는 쿼리에 원시 메커니즘 사용

쿼리에 SQL 함수가 포함된 경우 whereRaw(또는 whereExp), orderRaw 또는 fieldRaw 메서드를 사용하세요.

User::whereExp(&#39;nickname&#39;, "= CONCAT(name, &#39;-&#39;, id)")
    ->orderRaw("field(name,&#39;thinkphp&#39;, &#39;kancloud&#39;)")
    ->fieldRaw(&#39;id,SUM(score)&#39;)
    ->select();

클로저를 적절하게 사용하되 남용하지 마세요.

클로저 쿼리는 쿼리 생성자에서 특별한 용도로 사용되지만 필요하지 않은 한 남용할 필요는 없습니다.

클로저 쿼리의 일반적인 사용 시나리오는 다음과 같습니다.

클로저는 일반적으로 조건부 쿼리 집합을 나타내기 위해 조건부 쿼리에 사용됩니다.

User::when($condition, function ($query) {
    // 满足条件后执行
    $query->where(&#39;score&#39;, &#39;>&#39;, 80)->limit(10);
}, function ($query) {
    // 不满足条件执行
    $query->where(&#39;score&#39;, &#39;>&#39;, 60);
})->select();

클로저는 일부 하위 쿼리에서 자주 사용됩니다.

User::whereIn(&#39;id&#39;, function ($query) {
    $query->table(&#39;profile&#39;)
        ->where(&#39;name&#39;, &#39;like&#39;, &#39;think%&#39;)
        ->field(&#39;id&#39;);
})->select();

닫힌 쿼리 조건 집합 생성

User::where(&#39;id&#39;, &#39;>&#39;, 100)
    ->whereOr(function($query) {
        $query->where(&#39;name&#39;, &#39;like&#39;, &#39;think%&#39;)
        ->whereColumn(&#39;name&#39;, &#39;nickname&#39;);
    })->select();

이 쿼리 사용법에서는 클로저의 쿼리 조건을 양쪽에 괄호와 함께 추가하여 닫힌 쿼리 조건이 됩니다.

많은 관련 사전 로드 쿼리에서 클로저를 사용하여 관련 데이터를 필터링할 수 있습니다.

User::with([&#39;profile&#39; => function($query) {
$query->field(&#39;user_id,email,phone&#39;);
}])->select([1,2,3]);

쿼리 조건을 최대한 재사용하세요

모든 쿼리 조건은 한 곳에서 정의하고 이를 모델 메서드에 캡슐화하는 등 여러 곳에서 재사용해야 합니다. 특히 복잡한 쿼리를 잔뜩 작성하지 마세요. 조건을 컨트롤러 코드에 직접 입력하지 않으면 비즈니스가 조정된 후 전 세계 검색 코드로 쿼리 조건을 변경하는 것은 악몽이 될 것입니다.

공식 매뉴얼이나 일부 튜토리얼에서 컨트롤러의 쿼리 조건을 직접 캡슐화하는 방법을 많이 보셨겠지만 이는 단지 사용법을 보여주기 위한 편의일 뿐이며 권장되지 않습니다.

일부 중대형 애플리케이션 아키텍처 설계에서 모델은 일반적으로 데이터 계층, 논리 계층 및 서비스 계층으로 나뉘며 컨트롤러는 서비스 계층 메서드만 호출합니다. 쿼리 로직은 기본적으로 로직 레이어에 캡슐화되어 있으며, 데이터 레이어는 모델에 대한 다양한 정의만 수행합니다.

간단한 애플리케이션에서는 PHP의 특성 메커니즘을 사용하여 코드 재사용 메커니즘을 구현할 수도 있습니다.

쿼리 범위 또는 검색기를 사용하여 쿼리 단순화

모델 쿼리를 사용하는 경우 쿼리 조건을 쿼리 범위 또는 검색기 메서드로 캡슐화해 보세요. 쿼리 범위와 검색기의 주요 차이점은 쿼리 범위가 더 넓다는 것입니다. 적합 (여러 필드) 쿼리 조건 집합을 정의합니다. 여러 쿼리 범위를 호출하려면 여러 번 호출해야 합니다. 검색기는 하나의 필드에 대한 쿼리 조건을 정의하는 데 더 적합합니다(실제로는 절대적인 것은 아닙니다). . withSearch 메소드는 한 번만 호출하면 됩니다.

쿼리 범위 및 검색기를 사용하는 예입니다.

<?php
namespace app\index\model;
use think\Model;
class User extends Model
{
    public function scopeVip($query)
    {
        $query->where(&#39;user_type&#39;, &#39;vip&#39;)
            ->where(&#39;status&#39;, 1)
            ->field(&#39;id,name&#39;);
    }
    
    public function searchAgeAttr($query, $age)
    {
        $query->where(&#39;age&#39;,&#39;>&#39;,$age);
    }    
    
    public function searchScoreAttr($query, $score)
    {
        $query->where(&#39;score&#39;,&#39;<=&#39;,$score)->where(&#39;score&#39;, &#39;>&#39; ,0);
    }    
}

컨트롤러 코드

<?php
namespace app\index\controller;
use think\Controller;
use think\Request;
class index extends Controller
{
    public function index(Request $request)
    {
        // 查询VIP会员
        User::vip()->select();
        // 查询年龄和分数
        User::withSearch([&#39;age,&#39;score&#39;&#39;], $request->param())->select();
    }
}

컨트롤러 코드에서는 비즈니스 로직 자체에만 집중하고 이 로직 내부의 쿼리 조건에는 주의를 기울일 필요가 없습니다. 검색자 및 검색어 범위에 대한 자세한 내용은 공식 매뉴얼을 참고하시기 바랍니다.

PHP 중국어 웹사이트에는 무료 ThinkPHP 입문 튜토리얼이 많이 있습니다. 누구나 배울 수 있습니다!

이 기사는 https://blog.thinkphp.cn/833794

에서 복제되었습니다.

위 내용은 ThinkPHP: 데이터 쿼리의 기본 원칙의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 thinkphp.cn에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제