Laravel Notion APIについて

[Laravel Advent Calendar 2021 19日目](https://qiita.com/advent-calendar/2021/laravel)の投稿です。

[Notion API](https://developers.notion.com/)を最近使った時に、Laravel用のAPIラッパーを利用したので使い方を書いていきます！


# Notion APIについて

Notionではdatabase、page、blocks、usersに対するAPIが提供されています。
詳細は以下ドキュメントがあります。

https://developers.notion.com/

# Laravel-Notion-APIについて

2021年12月現在で[ver0.6](https://5amco.de/docs/0.6.0)がリリースされています。
Githubは[こちら](https://github.com/5am-code/laravel-notion-api)です。

# 実装例

## Notion APIのインテグレーション作成

まずはNotionAPIを使うために[インテグレーションを作成](https://www.notion.so/my-integrations)します。

日本語設定にしているとちょっとレイアウト崩れしてますね。。。
![スクリーンショット 2021-12-19 11.49.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207269/182781ba-41c5-afa5-38b0-5f4b09142562.png)

新規作成で名前を入力し、利用する機能を設定します。

![スクリーンショット 2021-12-19 11.50.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207269/d34f096b-f7a2-31e5-69eb-ccfcbb8d7344.png)

これで送信するとトークンが発行されます。

このトークンを操作したいページに対して設定する必要があります

ページの[共有]設定から、[招待]をクリックすると以下が表示されインテグレーション選択出来ます。
![スクリーンショット 2021-12-19 13.13.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207269/93513a75-9b99-ec2b-8f55-87b686b0aa21.png)

今回は私が以前公開した[読書リスト](https://charming-antimatter-5a2.notion.site/b3faf77a97124b4f8c1f242085f1d2e3?v=a1413e285972481e8483c894152047ff)を使ってやっていきます。このリストはNotionで言うdatabaseに当たるもので、その配下にページが追加されていくイメージです。

Notionの構造を理解する上で、以下の記事がとても参考になりました
[現在のNotion API（2021/7/13）で何がどこまでできるか](https://zenn.dev/st43/articles/7982e6d371f8b8#notion-api%E3%81%AE%E5%85%A8%E4%BD%93%E5%83%8F)

今回のURLでは、
`https://charming-antimatter-5a2.notion.site/b3faf77a97124b4f8c1f242085f1d2e3?v=a1413e285972481e8483c894152047ff`
このURLにおける`b3faf77a97124b4f8c1f242085f1d2e3`の部分が`database_id`になります。

今回はこの`database_id`も'.env'で管理してコードを書きます

``````.env
NOTION_DATABASE_ID="b3faf77a97124b4f8c1f242085f1d2e3"
```

## Laravel-Notion-APIの設定

composerで追加します。

```ssh
composer require fiveam-code/laravel-notion-api
```
`.env` に先程取得したアクセストークンを設定します

```.env
NOTION_API_TOKEN="$YOUR_ACCESS_TOKEN"
```

Laravel-Notion-APIの設定はこれで完了です。

## configでenvの値を取るように設定

app/config配下に'notion.php'を作ります

```notion.php
<?php

return [
    'token' => env('NOTION_API_TOKEN'),
    'database' => env('NOTION_DATABASE_ID'),
];

```

## ページ作成
では早速ページを作ってみます

```php
<?php

use FiveamCode\LaravelNotionApi\Entities\Page;
use FiveamCode\LaravelNotionApi\Exceptions\NotionException;
use FiveamCode\LaravelNotionApi\Notion;
use Illuminate\Support\Facades\Log;

// 以下実装

        $token = config("notion.token");
        $notion = new Notion($token);

        $databaseId = config("notion.database");
        $page = new Page();

        // タイトル指定
        $page->setTitle("Name", "こち亀200巻");

        try {
            $page = $notion->pages()->createInDatabase($databaseId, $page);
            // ページID
            Log::info($page->getId());
        } catch (NotionException $e) {
            Log::error($e->getMessage());
        }

```

さて、これで...とやってみたらエラーが出ました！

```
local.ERROR: Bad Request: (validation_error) (Name is not a property that exists.) 
```

Nameというプロパティはないよ！と言われました。
確かに今回対象にしている[読書リスト](https://charming-antimatter-5a2.notion.site/b3faf77a97124b4f8c1f242085f1d2e3?v=a1413e285972481e8483c894152047ff)には`Name`のプロパティはありませんでした。

![スクリーンショット 2021-12-19 14.08.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207269/b5e2bd5c-e2d5-766c-43db-8a1e461741ca.png)


"タイトル"でいけそうですね

```php

use FiveamCode\LaravelNotionApi\Entities\Page;
use FiveamCode\LaravelNotionApi\Exceptions\NotionException;
use FiveamCode\LaravelNotionApi\Notion;
use Illuminate\Support\Facades\Log;

// 以下実装

        $token = config("notion.token");
        $notion = new Notion($token);

        $databaseId = config("notion.database");
        $page = new Page();

        // タイトル指定
        $page->setTitle("タイトル", "こち亀200巻");

        try {
            $page = $notion->pages()->createInDatabase($databaseId, $page);
            // ページID
            Log::info($page->getId());
        } catch (NotionException $e) {
            Log::error($e->getMessage());
        }

```

これでやってみると...追加されました！！

![スクリーンショット 2021-12-19 14.15.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207269/d46f06c8-4a8b-7f37-59b2-52ee044b4d60.png)

他のタグも設定してみます！

```php

use FiveamCode\LaravelNotionApi\Entities\Page;
use FiveamCode\LaravelNotionApi\Exceptions\NotionException;
use FiveamCode\LaravelNotionApi\Notion;
use Illuminate\Support\Facades\Log;

// 以下実装

        $token = config("notion.token");
        $notion = new Notion($token);

        $databaseId = config("notion.database");
        $page = new Page();

        // タイトル指定
        $page->setTitle("タイトル", "こち亀200巻");
        // URL
        $page->setUrl("Amazonなどのリンク", "https://www.amazon.co.jp/dp/B01KJGD54C/ref=cm_sw_em_r_mt_dp_BJCRXMKNGAM913PDKZR6");

        // 選択リスト
        $page->setMultiSelect("本の種類", ["物理本"]);
        $page->setMultiSelect("カテゴリ", ["技術書","歴史"]);

        // チェックボックス
        $page->setCheckbox("既読", false);
        $page->setCheckbox("お気に入り", true);
        $page->setCheckbox("読書中", true);

        try {
            $page = $notion->pages()->createInDatabase($databaseId, $page);
            // ページID
            Log::info($page->getId());
        } catch (NotionException $e) {
            Log::error($e->getMessage());
        }

```

これで綺麗に入りました！
![スクリーンショット 2021-12-19 14.25.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207269/3cf7b85d-f94f-b1be-5e12-2564379c33a8.png)

## ページ更新

ページ更新はページIDを指定して更新が出来ます
ページ作成の際は、戻り値でページIDが取得できます。`$page->getId()`の部分です。
このIDを使って更新ができます。

ページのURLでみると `https://www.notion.so/200-` 以下がページIDになります。(ここで200-と付いているのはこち亀200巻の200ですね。タイトルの中の英数字で変わるみたいです。)
`https://www.notion.so/200-c2ea522a427f4966b774e0fd14a69642`

ページIDの詳細はこちらになります。
https://www.notion.so/200-c2ea522a427f4966b774e0fd14a69642

https://developers.notion.com/docs/working-with-page-content#creating-a-page-with-content

```php

use FiveamCode\LaravelNotionApi\Entities\Page;
use FiveamCode\LaravelNotionApi\Exceptions\NotionException;
use FiveamCode\LaravelNotionApi\Notion;
use Illuminate\Support\Facades\Log;

// 以下実装

        $token = config("notion.token");
        $notion = new Notion($token);
        $page = new Page();

        $page->setId("c2ea522a-427f-4966-b774-e0fd14a69642");
        $page->setCheckbox("読書中", false);

        try {
            $page = $notion->pages()->update($page);
            // ページID
            Log::info($page->getId());
        } catch (NotionException $e) {
            Log::error($e->getMessage());
        }

```
これで、読書中のフラグが落ちました！

## データベース情報取得
データ取得系のAPIも確認してみます！

データベースに紐づく情報を取得を取ります。

```php

use FiveamCode\LaravelNotionApi\Entities\Page;
use FiveamCode\LaravelNotionApi\Exceptions\NotionException;
use FiveamCode\LaravelNotionApi\Notion;
use Illuminate\Support\Facades\Log;

// 以下実装

        $token = config("notion.token");
        $notion = new Notion($token);
        $databaseId = config("notion.database");

        try {
            $database = $notion->databases()
                ->find($databaseId);

            Log::info($database->getTitle());
            // 読書リスト
            
            Log::info($database->getProperties());
            // [{"id":"AIrg","responseData":{"id":"AIrg","name":"\u65e2\u8aad","type":"checkbox","checkbox":[]},"title":"\u65e2\u8aad","type":"checkbox","rawContent":[],"content":[]},{"id":"Cl>z","responseData":...(省略) 
            
            Log::info($database->getPropertyKeys());
            // array (
            //                0 => '既読',
            //                1 => 'カテゴリ',
            //                2 => 'お気に入り',
            //                3 => '読書中',
            //                4 => '本の種類',
            //                5 => 'Amazonなどのリンク',
            //                6 => 'タイトル',
            //            )
            
            Log::info($database->getIcon());
            // 📕
            Log::info($database->getIconType());
            // emoji
            Log::info($database->getUrl());
            // https://www.notion.so/b3faf77a97124b4f8c1f242085f1d2e3
            Log::info($database->toArray());
            //array ( ... )
            
        } catch (NotionException $e) {
            Log::error($e->getMessage());
        }

```
`toArray()` で全部取れるのは使いやすいですね

## データベース配下のページ情報を取る

```php
use FiveamCode\LaravelNotionApi\Exceptions\NotionException;
use FiveamCode\LaravelNotionApi\Notion;
use FiveamCode\LaravelNotionApi\Query\Filters\Filter;
use FiveamCode\LaravelNotionApi\Query\Filters\Operators;
use FiveamCode\LaravelNotionApi\Query\Sorting;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;

// 以下実装

        $token = config("notion.token");
        $notion = new Notion($token);
        $databaseId = config("notion.database");
        $sorting = new Collection();
        $filters = new Collection();

        // こち亀をタイトルに含むものだけ取る
        $filters
            ->add(
                Filter::textFilter("タイトル", Operators::CONTAINS, "こち亀")
            );

        // お気に入りを昇順でソートする (降順は"descending")
        $sorting
            ->add(Sorting::propertySort("お気に入り", "ascending"));

        try {
            $pages = $notion->database($databaseId)
                ->filterBy($filters)// フィルター
                ->sortBy($sorting) // ソート
                ->limit(5) // リミット5件で設定
                ->query()
                ->asCollection();

            // 取得ページ
            foreach ($pages as $page) {
                $array = $page->toArray();
                Log::info($array['title']);
            }
        } catch (NotionException $e) {
            Log::error($e->getMessage());
        }

```
このデータの状態だった場合
![スクリーンショット 2021-12-19 16.32.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207269/9deb1081-68fa-d307-13d1-0c84929a2236.png)

以下の結果で返ってきます！お気に入りの昇順が効いていますね。

```
local.INFO: こち亀201巻  
local.INFO: こち亀200巻  
```

pageの詳細情報も`$page`に入っています。

# 最後に
簡単にお問い合わせ管理する時とか今の機能でも十分できそうですね。
Notion APIも、Laravel-Notion-APIもまだ出来たばっかりの進化中なので今後の機能追加を楽しみです。