laravel中查询语句

1 常见的数据库表关系

One-To-One //一对一
One-To-Many //一对多
Many-To-Many //多对多

在刚刚开始接触到这些概念的时候,其实我是不太理解的。但是一旦你将这些概念应用到生活中,理解起来就很简单了,就举一个与我们在网上经常见到的例子:

User-To-Profile // One-To-One
User-To-Articles // One-To-Many
Articles-To-Tags // Many-To-Many

翻译过来就是:

  • 一个用户对应一个用户档案
  • 一个用户可以发表多篇文章
  • 文章和标签确实多对多的关系,一篇文章可以有多个标签;一个标签可以属于多篇文章

在这些关系模型中,最难实现的就是Many-To-Many这种多对多的关系,不过借助Laravel的强大的Eloquent,实现这个功能还是比较顺心的。

2 创建数据库表

创建Question.php数据库模型时,同时也创建一个Questions迁移文件

php artisan make:model Question -m

Quesrtions.php
2017_02_02_072801_create_questions_table.php

创建questions表

Schema::create('Questions', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title');
            $table->text('content');
            $table->timestamps();
        });

创建Topic.php数据库模型,同时也创建一个Topics数据库迁移文件

php artisan make:model Topic -m

Topics.php
2017_02_02_072801_create_Topics_table.php

创建topics表

Schema::create('tags', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->timestamps();
        });

当然,解决这个经典问题单单靠这两张表还不足够,需要在这两张表之外再建立一个关系表,用来将article和tag联系起来,在Laravel中,如果你遵循官方的标准规则,第三张表应该是这样的:

创建 question_topic迁移文件

php artisan make:migration create_articles_tags_table --create=question_topic

生成一个迁移文件
2017_06_08_235159_create_questions_topics_table.php

创建question_topic

       Schema::create('question_topic', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('question_id')->unsigned()->index();
            $table->integer('topic_id')->unsigned()->index();
            $table->timestamps();
        });

如果你没有按照官方的规范来,你需要在模型中指定外键。

3. 创建模型并指定关系

在Topic.php中:

class Topic extends Model
{
    protected $fillable = ['name','questions_count'];

    public function questions()
    {
        //这里的数据库模型为Question数据模型
        return $this->belongsToMany(Question::class)->withTimestamps()
    }

在Question.php中:

class Question extends Model
{
    protected $fillable = ['title','body', 'user_id'];

    public function topics()
    {
        //这里的数据库模型为Topic数据模型
        return $this->belongsToMany(Topic::class)->withTimestamps()
    }

这里注意两点:

你可以在声明关系的时候指定外键,如

$this->belongsToMany(Topic::class,'foreign_key', 'other_key');

或者传递第二个数据库表的表名作为第二个参数(your_table_name)

return $this->belongsToMany(Topic::class,'your_table_name')->withTimestamps()

如果在article_tag表中你添加了timestamps(),即表中出现created_at和updated_at这两个字段,在Article中声明关系的时候需要这样:

return $this->belongsToMany(Topic::class)->withTimestamps();

4 在Controller中使用

如果我们想查看某个提问含有哪些话题,我们可以这样:

$question= Question::find($id);
dd($question->topic);

如果我们想通过某个话题下面有多少个提问:

public function showArticleByTagName($name)
    {
        $topic= Topic::where('value','=',$name)->first();
        dd($topic->questions);
    }

以上,就实现了在Laravel中的Many-To-Many

转自https://segmentfault.com/a/1190000002982984

<think>我们参考了用户提供的多个引用,这些引用主要介绍了在Laravel框架中记录或输出SQL语句的不同方法。用户的问题集中在“如何输出SQL语句”,因此我们需要综合这些方法,给出清晰的步骤和说明。 根据引用内容,我们可以归纳出以下几种方法: 1. 使用Laravel自带的`dd()`或`dump()`方法(引用[2]提到)。 2. 使用事件监听(引用[1]和引用[5]提到,通过监听查询事件并记录)。 3. 使用日志记录(引用[3]提到,将SQL语句打印到日志)。 4. 使用第三方扩展包(如引用[1]提到的`laravelsql`扩展)。 由于用户要求输出SQL语句,我们重点介绍几种常用方法,并给出具体步骤。 ### 方法1:使用`dd()`或`dump()`方法 在查询构造器链式调用末尾使用`dd()`(打印并终止执行)或`dump()`(打印不终止)可以输出SQL语句和绑定参数。 ```php // 使用dd()输出并终止 User::where('id', 1)->dd(); // 使用dump()输出不终止 User::where('id', 1)->dump(); ``` 输出结果会包含完整的SQL语句(已经替换了绑定参数)以及执行时间等信息[^2]。 ### 方法2:监听查询事件 在Laravel中,每次数据库查询都会触发`QueryExecuted`事件。我们可以通过创建一个事件监听器来记录SQL语句。 **步骤:** 1. 创建监听器: ```bash php artisan make:listener QueryListener --event=Illuminate\\Database\\Events\\QueryExecuted ``` 2. 在生成的监听器文件`app/Listeners/QueryListener.php`中编写逻辑: ```php <?php namespace App\Listeners; use Illuminate\Database\Events\QueryExecuted; use Illuminate\Support\Facades\Log; class QueryListener { public function handle(QueryExecuted $event) { // 获取SQL语句和绑定参数 $sql = $event->sql; $bindings = $event->bindings; $time = $event->time; // 将绑定参数替换到SQL语句中 $sql = vsprintf(str_replace('?', "'%s'", $sql), $bindings); // 输出到日志 Log::info("[SQL] {$sql} | Time: {$time}ms"); } } ``` 3. 注册事件监听:在`app/Providers/EventServiceProvider.php`中: ```php protected $listen = [ \Illuminate\Database\Events\QueryExecuted::class => [ \App\Listeners\QueryListener::class, ], ]; ``` 这样,每次执行SQL语句都会记录到日志文件中(默认在`storage/logs`目录下)[^5]。 ### 方法3:使用第三方扩展包 引用[1]提到使用`laravelsql`扩展包。安装后可以方便地输出完整SQL。 1. 安装扩展包: ```bash composer require rap2hpoutre/laravel-log-viewer ``` 注意:这里引用[1]提到的扩展包名称可能是错误的,实际上常用的扩展包是`barryvdh/laravel-debugbar`或`rap2hpoutre/laravel-log-viewer`?但根据引用[1]描述,可能是`laravelsql`,但实际搜索可能没有这个包,所以这里可能需要更正。不过,更常用的是`barryvdh/laravel-debugbar`,它可以显示所有查询。 以`barryvdh/laravel-debugbar`为例: ```bash composer require barryvdh/laravel-debugbar --dev ``` 安装后,在开发环境中会自动在页面底部显示一个调试栏,其中包含执行的SQL语句。 ### 方法4:直接获取查询SQL 对于单个查询,可以直接使用`toSql()`方法获取未替换绑定参数的SQL语句: ```php $query = User::where('id', 1); $sql = $query->toSql(); $bindings = $query->getBindings(); // 手动替换绑定参数 $sql = vsprintf(str_replace('?', "'%s'", $sql), $bindings); echo $sql; ``` ### 总结 根据不同的场景,可以选择不同的方法: - 快速调试单个查询:使用`dd()`或`dump()`。 - 记录所有SQL到日志:使用事件监听。 - 开发阶段实时查看SQL:使用Debugbar扩展包。 以上方法在Laravel框架中都是常用的输出SQL语句的方式[^1][^2][^3][^5]。 §§相关问题§§ 1. Laravel中如何将SQL语句记录到文件而不是页面输出? 2. 如何在Laravel中优化慢查询? 3. 如何配置Laravel的日志系统以按日期分割日志文件? </think>在 Laravel 框架中输出 SQL 语句有以下几种常用方法,结合引用内容为您整理: --- ### 一、直接调试方法(适合快速查看) 1. **使用 `dd()` 或 `dump()`** 在查询构造器后调用内置方法,输出完整 SQL 和结果: ```php // 输出 SQL 并终止执行(dd = dump and die) User::where('id', 1)->dd(); // 输出 SQL 不终止执行 User::where('id', 1)->dump(); ``` **效果**:直接显示绑定了参数的完整 SQL(如 `SELECT * FROM users WHERE id = 1`)[^2]。 2. **使用 `toSql()` 获取未绑定参数的 SQL** ```php $sql = User::where('id', 1)->toSql(); dd($sql); // 输出:select * from `users` where `id` = ? ``` > ✅ 需手动替换参数占位符 `?`[^3]。 --- ### 二、全局记录 SQL(适合长期调试) 1. **通过事件监听记录到日志** **步骤**: ```php // 步骤1: 创建监听器 php artisan make:listener QueryListener --event=QueryExecuted // 步骤2: 在 app/Listeners/QueryListener.php 中编写逻辑 public function handle(QueryExecuted $event) { $sql = vsprintf( str_replace('?', "'%s'", $event->sql), $event->bindings ); Log::channel('sql')->debug("SQL: {$sql} | Time: {$event->time}ms"); } // 步骤3: 在 app/Providers/EventServiceProvider.php 注册事件 protected $listen = [ 'Illuminate\Database\Events\QueryExecuted' => [ 'App\Listeners\QueryListener' ] ]; ``` **效果**:所有 SQL 会记录到 `storage/logs/sql.log`[^1][^5]。 2. **简化版中间件记录** 在 `App\Http\Middleware` 中创建中间件: ```php public function handle($request, Closure $next) { DB::listen(function ($query) { Log::debug("SQL: " . $query->sql, $query->bindings); }); return $next($request); } ``` --- ### 三、使用扩展包(推荐) 安装 **Laravel Debugbar** 或 **Laravel SQL Monitor**: ```bash composer require barryvdh/laravel-debugbar --dev ``` **效果**:页面底部自动显示所有执行的 SQL、耗时及调用位置[^1]。 --- ### 四、复杂场景处理 ```php // 示例:复杂查询输出(引用[4]) $query = DB::table('a') ->leftJoin('b', 'a.x', '=', 'b.y') ->where('col', 0) ->where('col1', 1) ->where(function ($q) { $q->where('col2', 2)->orWhere('col3', 3); }) ->dd(); // 直接输出完整 SQL ``` --- ### 💡 关键区别总结 | **方法** | 适用场景 | 是否显示参数 | 是否记录时间 | |-------------------|----------------|-------------|------------| | `dd()`/`dump()` | 单次调试 | ✅ 是 | ✅ 是 | | 事件监听日志 | 全局监控 | ✅ 是 | ✅ 是 | | `toSql()` | 获取原始 SQL 结构| ❌ 否 | ❌ 否 | | Debugbar 扩展 | 开发环境集成 | ✅ 是 | ✅ 是 | > 建议:开发调试用 Debugbar 扩展,生产环境排查用事件监听日志[^1][^3][^5]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值