> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Laravel Telescope 实战技巧

> 介绍在本地开发中充分利用 Telescope 的实战模式。涵盖 N+1 检测、通过标签追踪、自定义 watcher、Dump watcher 的活用等官方文档没有讲到的经验。

基本的安装与配置请参考[指南页面](/zh/telescope)。本文介绍官方文档没有覆盖的、在本地开发中的实战模式。

Telescope 是**只用于本地开发**的工具。生产环境的监控请使用 [Laravel Pulse](/zh/pulse) 或 [Laravel Nightwatch](/zh/blog/nightwatch-introduction)。

***

## 有条理地发现 N+1 问题

下面介绍用 Telescope 排查 N+1 的实战流程。不是简单地“注意到同样的 SELECT 反复出现”,而是把修复后的确认也串成一条完整的工作流。

```mermaid theme={null}
sequenceDiagram
    participant 浏览器
    participant Laravel
    participant Telescope
    participant DB

    浏览器->>Laravel: GET /posts
    Laravel->>DB: SELECT * FROM posts(1 条查询)
    loop 每个 post
        Laravel->>DB: SELECT * FROM users WHERE id = ?(N 条查询)
    end
    Laravel-->>浏览器: 响应
    Laravel-->>Telescope: 记录查询历史
    Note over Telescope: 同一 SELECT 出现 N 次<br>被打上 slow 标签
```

<Steps>
  <Step title="在 Requests 中找出慢请求">
    打开 `/telescope`,在 Requests 标签中锁定执行时间较长的请求。
  </Step>

  <Step title="在 Queries 中查看发生的 SQL">
    打开请求详情,会显示该请求期间执行的所有 SQL。如果看到形状相同的 SELECT 反复出现,那就是 N+1。
  </Step>

  <Step title="加上 Eager Loading 修复">
    在代码里加 `with()`,再次确认查询。查询数量大幅减少就说明修复完成。
  </Step>
</Steps>

```php theme={null}
// 会发生 N+1 的代码
$posts = Post::all();
foreach ($posts as $post) {
    echo $post->user->name; // 每个 post 都追加一条查询
}

// 用 Eager Loading 解决
$posts = Post::with('user')->get();
```

不用往代码里加 `dd()` 或日志,这一整套流程都能在浏览器里完成。

***

## 用标签追踪特定请求

Telescope 有**标签**功能。用 `Telescope::tag()` 给条目打上任意标签,再在面板的过滤器里就能快速筛出带该标签的条目。

在只想追踪特定用户 ID、订单 ID 相关的处理时非常有效。

```php theme={null}
use Laravel\Telescope\IncomingEntry;
use Laravel\Telescope\Telescope;

// 覆盖 TelescopeServiceProvider 的 tags 方法
Telescope::tag(function (IncomingEntry $entry) {
    if ($entry->type === 'request') {
        return array_filter([
            'status:' . $entry->content['response_status'],
            auth()->check() ? 'user:' . auth()->id() : null,
        ]);
    }

    return [];
});
```

之后在 `/telescope/requests` 页面的 Search 里输入 `user:42`,就能只看用户 ID=42 的请求。

### 自动给模型打标签

在 `TelescopeServiceProvider` 的 `tags` 方法中,可以给所有条目附加特定模型的 ID 标签。

```php theme={null}
// TelescopeServiceProvider
Telescope::tag(function (IncomingEntry $entry) {
    return $entry->tags();
});
```

只要给模型实现 `HasTags` 契约,该模型被记录时会自动带上标签。

```php theme={null}
use Laravel\Telescope\Contracts\EntriesRepository;

class Order extends Model implements \Laravel\Telescope\Contracts\HasTags
{
    public function telescopeTags(): array
    {
        return ['order:' . $this->id];
    }
}
```

***

## 用好 Dump watcher

用 `dump()` 时输出可能混进 HTML 响应,导致 API 调试变得困难。Telescope 的 Dump watcher 可以把 `dump()` 的输出从浏览器响应里剥离,记录到面板里。

用法很简单:在 `/telescope` 的 “Dump” 标签保持打开,然后调用 `dump()` 就行。

```php theme={null}
// 控制器
public function index()
{
    $users = User::with('posts')->get();
    dump($users->first()->toArray()); // 会显示在 Telescope 的 dump 标签
    return response()->json($users);
}
```

只有当页面处于打开状态时才会捕获,所以按需监视即可。它不像 `dd()` 会让程序停下来,连续多次请求也能持续调试。

***

## 与 Mailpit 配合让邮件调试更顺手

把 Mail watcher 和本地 SMTP 服务器 [Mailpit](https://mailpit.axllent.org/) 组合起来,邮件开发流程会舒服很多。

```ini theme={null}
# .env
MAIL_MAILER=smtp
MAIL_HOST=127.0.0.1
MAIL_PORT=1025
```

Telescope 的 Mail 标签能预览已发送邮件的 HTML 和文本两种格式。在 Mailpit 中可以在浏览器里查看已收邮件,还能看附件和垃圾评分。

<Tip>
  为了避免测试时把邮件误发到外部,本地一定要使用 Mailpit 或 Mailhog 这类本地 SMTP。
</Tip>

***

## 调试事件与监听器

事件驱动的实现往往难以调试。“事件到底触发没?”、“到底哪个监听器被调用了?”光看日志追这些非常麻烦。

Telescope 的 Events watcher 会把已经派发的事件和监听器都列出来。

如果监听器没被调用,可以在 Events 标签查看事件条目。

* 事件已派发但没有显示监听器 → 监听器没注册(检查 `EventServiceProvider`)
* 事件本身就没派发 → 检查 `event()` 的调用点

```php theme={null}
// 在本地代替测试的确认流程
event(new OrderShipped($order));
// → 在 /telescope/events 里看 OrderShipped 是否出现
// → 确认 SendShippingConfirmation 监听器有没有被调用
```

***

## 调试队列作业

异步处理只靠看日志很难定位原因。Telescope 的 Jobs watcher 会记录作业从 dispatch 到执行结果的全过程。

点击失败作业的条目,能看到堆栈跟踪和异常信息。除了 `queue:failed` 表以外,Telescope 也能查看,排查失败原因很快。

```php theme={null}
// 调试作业时用 sync 驱动同步执行更容易追踪
// .env
QUEUE_CONNECTION=sync
```

改成 sync 驱动后,作业会在请求内同步执行,Requests watcher 里也能看到作业的执行结果。

***

## 调试 HTTP 客户端

调试与外部 API 的通信时,HTTP Client Watcher 很有用。它会记录通过 `Http::` 门面发起的请求及其响应。

```php theme={null}
$response = Http::get('https://api.example.com/users');
// → 在 /telescope/client-requests 里可以查看
```

响应内容、状态码、执行时间一目了然。不需要写 `dd($response->json())`,直接在面板里就能看。

***

## 总结

| 技巧             | 效果                       |
| -------------- | ------------------------ |
| N+1 工作流        | 不需要 dd() 就能有条理地发现并修复查询问题 |
| 打标签            | 快速筛选特定用户 / 模型的记录         |
| Dump watcher   | 不污染 API 响应就能确认 dump 输出   |
| Mailpit 集成     | 让本地邮件开发更舒服               |
| Events watcher | 直观确认事件/监听器的触发            |
| Jobs + sync    | 用同步执行来调试异步处理             |
| HTTP 客户端       | 记录并查看外部 API 通信           |

<Columns cols={2}>
  <Card title="Laravel Telescope 指南" icon="telescope" href="/zh/telescope">
    详细的安装和 watcher 配置请参考指南页面。
  </Card>

  <Card title="Laravel Nightwatch" icon="moon" href="/zh/blog/nightwatch-introduction">
    生产环境的监控用 Nightwatch。
  </Card>
</Columns>


## Related topics

- [Laravel Nightwatch 入门](/zh/blog/nightwatch-introduction.md)
- [Laravel Pennant 实战用例](/zh/blog/laravel-pennant.md)
- [Laravel Telescope](/zh/telescope.md)
- [队列与任务](/zh/queues.md)
- [文件存储](/zh/filesystem.md)
