使用PHP与Notion API进行数据库查询:正确实现过滤功能
Notion 作为一款强大的笔记和知识管理工具,其 API 的开放为开发者提供了丰富的集成可能。在众多功能中,对数据库进行查询并根据特定条件过滤数据是最核心的需求之一。本文将详细介绍如何使用 PHP 与 Notion API 交互,重点阐述如何正确构建查询请求体,特别是实现复杂的过滤功能。

一、前期准备
在开始编写代码之前,需要完成以下准备工作:
在
https://www.notion.so/my-integrations创建一个新的集成(Integration),并获取其Internal Integration Token。将你的集成分享(Share)到你需要查询的 Notion 数据库页面。
获取目标数据库的 ID。数据库 ID 通常是其页面 URL 中
https://www.notion.so/workspace/之后、问号之前的那一串字符。
二、基础查询:获取数据库所有条目
首先,我们实现一个基础的查询,获取数据库中的所有条目。这有助于理解 API 的基本调用方式。
<?php
// 配置信息
$databaseId = 'YOUR_DATABASE_ID_HERE';
$notionToken = 'YOUR_NOTION_INTEGRATION_TOKEN_HERE';
// API 端点
$url = "https://api.notion.com/v1/databases/{$databaseId}/query";
// 准备请求头
$headers = [
'Authorization: Bearer ' . $notionToken,
'Content-Type: application/json',
'Notion-Version: 2022-06-28' // 使用最新的稳定API版本
];
// 初始化 cURL
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([])); // 空对象表示无过滤条件
// 执行请求
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode == 200) {
$data = json_decode($response, true);
echo "查询成功,共获取到 " . count($data['results']) . " 条结果。n";
// 处理 $data['results']...
} else {
echo "查询失败,HTTP状态码: {$httpCode}n";
echo "响应内容: {$response}n";
}
?>三、实现过滤功能
Notion API 的过滤功能通过在 POST 请求体中添加 filter 对象来实现。过滤条件可以基于数据库中的属性(Property)。
1. 单条件过滤
假设我们有一个名为“任务”的数据库,其中有一个“状态”属性。我们想查询所有状态为“进行中”的任务。
<?php // ... 前面的配置代码与上面相同 ... // 构建过滤条件 $filterPayload = [ 'filter' => [ 'property' => '状态', // 数据库中的属性名称 'select' => [ // 属性类型为“Select” 'equals' => '进行中' ] ] ]; $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); // 将过滤条件编码为JSON curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($filterPayload)); $response = curl_exec($ch); // ... 后续处理代码 ... ?>
2. 多条件组合过滤(与、或逻辑)
Notion API 使用 & 和 or 数组来组合多个条件。
与逻辑(AND):所有条件必须同时满足。使用
and键,其值为一个包含多个条件对象的数组。或逻辑(OR):至少一个条件满足。使用
or键,其值为一个包含多个条件对象的数组。
示例:查询状态为“进行中”且优先级为“高”的任务。
$filterPayload = [ 'filter' => [ 'and' => [ [ 'property' => '状态', 'select' => [ 'equals' => '进行中' ] ], [ 'property' => '优先级', 'select' => [ 'equals' => '高' ] ] ] ] ];
示例:查询状态为“已完成”或截止日期在今天之后的任务。
$filterPayload = [
'filter' => [
'or' => [
[
'property' => '状态',
'select' => [
'equals' => '已完成'
]
],
[
'property' => '截止日期',
'date' => [
'after' => date('Y-m-d') // 使用今天日期
]
]
]
]
];3. 不同属性类型的过滤操作符
不同的属性类型支持不同的过滤操作符。以下是一些常见类型的示例:
| 属性类型 | 操作符示例 | 说明 |
|---|---|---|
title, rich_text | contains, equals, starts_with | 文本匹配 |
number | equals, greater_than, less_than | 数值比较 |
select, multi_select | equals, does_not_equal, contains (仅 multi_select) | 选择匹配 |
date | before, after, on_or_before, is_empty | 日期比较 |
checkbox | equals (true/false) | 布尔值判断 |
示例:查询标题中包含“报告”且数字“进度”大于50的页面。
$filterPayload = [ 'filter' => [ 'and' => [ [ 'property' => '名称', // 数据库的标题属性通常叫“Name”或“标题” 'title' => [ 'contains' => '报告' ] ], [ 'property' => '进度', 'number' => [ 'greater_than' => 50 ] ] ] ] ];
四、完整示例与分页处理
Notion API 的查询结果可能分页返回。如果结果集很大,需要处理 has_more 和 next_cursor 来获取所有数据。
<?php
function queryNotionDatabase($databaseId, $notionToken, $filter = [], $startCursor = null) {
$url = "https://api.notion.com/v1/databases/{$databaseId}/query";
$headers = [
'Authorization: Bearer ' . $notionToken,
'Content-Type: application/json',
'Notion-Version: 2022-06-28'
];
$payload = ['filter' => $filter];
if ($startCursor) {
$payload['start_cursor'] = $startCursor;
}
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode != 200) {
throw new Exception("API请求失败: HTTP {$httpCode} - {$response}");
}
return json_decode($response, true);
}
// 使用示例
$allResults = [];
$hasMore = true;
$nextCursor = null;
$myFilter = [ // 这里放置你的过滤条件,例如:
'property' => '状态',
'select' => ['equals' => '已完成']
];
try {
while ($hasMore) {
$responseData = queryNotionDatabase($databaseId, $notionToken, $myFilter, $nextCursor);
$allResults = array_merge($allResults, $responseData['results']);
$hasMore = $responseData['has_more'];
$nextCursor = $responseData['next_cursor'] ?? null;
}
echo "总共获取到 " . count($allResults) . " 条记录。n";
} catch (Exception $e) {
echo "错误: " . $e->getMessage() . "n";
}
?>五、常见错误与排查
400 Bad Request:通常意味着请求体(特别是
filter对象)的 JSON 结构或属性名有误。仔细检查属性名称和类型是否与数据库中的完全一致(包括大小写和空格)。401 Unauthorized:Token 无效或未正确分享数据库给集成。
404 Not Found:数据库 ID 错误或集成无权访问该数据库。
过滤无效:确保为属性指定了正确的类型键(如
select,date,number)。使用 Notion API 的“检索数据库”端点(GEThttps://api.notion.com/v1/databases/{database_id})可以查看数据库属性的精确架构。
通过以上步骤,你可以在 PHP 应用中有效地利用 Notion API 的过滤功能,实现对数据库数据的精准查询和检索。关键在于正确构建代表过滤逻辑的嵌套 JSON 结构,并理解不同属性类型所支持的操作符。