AlfredのWorkflowをコードを書いて作成する方法

最近自分のブログの検索結果をAlfredで表示させるWorkflowを作成してみました。
そこで必要になった事に関してメモしておきます(AlfredのPower Pack必須)。
やりたかったこと
今回はAlfredのWorkflowとWP REST APIを使って、自分のブログを検索するWorkflowを作成してみました。

ざっくりした流れは下記の通りです。
- Alfredでキーワードを入力する
- WP REST APIでブログの検索結果をJSONで取得する
- Script Filterで指定した形のJSONに整形し直す
- Open URLに結果を引き渡す
- Open URLで指定URLのブラウザを開く

WP REST APIに関しては以前の記事を参照してください。
WordPress専用の機能になりますが、JSONで記事の取得さえできればいいのでWP REST APIにこだわる必要はありません。
コードを書く前の準備
まずはScriptを書かずにできるところまでひと通りワークフローを作成してみます。
新規Workflowの作成
Alfredの[環境設定]→[Workflows]の下の方にある「+」ボタンをクリックします。

いくつか選択肢が出てきますが[Blank Workflow]を選択します。
![[Blank Workflow]の選択](https://webrandum.net/mskz/wp-content/uploads/2019/04/image_2.png)
Workflowの情報を入力するモーダルが出てくるので、それぞれ必要な情報を入力します。

| 項目 | 内容 |
|---|---|
| Name | Workflowの名前 |
| Description | Workflowの説明 |
| Category | Workflowをグルーピングしたい時に設定 |
| Drop workflow icon above | Workflowのアイコン画像(ドラッグもしくは選択してペーストで設定) |
| Bundle id | Workflowの保存場所を指定したい場合はこのIDを登録する |
| Created By | 作者の名前 |
| Website | 作者のサイト もしくはWorkflowのサイト |
とりあえず名前だけ設定すれば「Create」ボタンが押せるようになるので、クリックして作成します。
Script Filderの追加
Workflowが作成されるので、黒い背景部分で右クリック→[Inputs]→[Script Filter]を選択します(コードを書いて情報の取得をしたい場合は基本的にこれを選択します)。

Script Filderでは、Workflowを呼び出すキーワードの設定を行うのと、使いたい言語やコードを書いていきます。
今回はひとまずコードは書かずに、Script Filterの最低限の設定だけしてしまいます。

| 項目 | 内容 |
|---|---|
| Keyword | Workflowを呼び出すキーワード |
| Argument | キーワードの後に付ける引数が必要かどうか選択 |
| Placeholder Title | Workflowを呼び出した時のタイトル |
| Placeholder Subtext | タイトル下にあるグレーのテキスト |
| “Please Wait” Subtext | 引数入力中などの結果が出てない時にに表示されるテキスト |
| Language | 使いたい言語を選択する。 今回の場合はPHPで書こうと思うので「/user/bin/php」を選択します。 |
| with input | 「with input as argv」と「with input as {query}」があり、 引数をどちらで取得するか選択します。 今回は「with inpu as {query}」の方を選択します。 |
| Script | ここにコードを書いていきます。 今回はひとまず後回しにするのでそのまま置いておきます。 |
ひと通り設定し終えたら、「Save」を選択します。
Open URLの追加
次にScript Filterの右側についているポッチを右クリックして[Actions]→[Open URL]を選択します。

今度はOpen URLの設定モーダルが表示されますが、「URL」には{query}が入っている状態で「Save」をクリックします。

通常、この{query}には引数が入りますが、Script Filterを使ってここにURLを代入します。
要するに「引数を使って得た値(URL)をブラウザで開く」ということですね。
workflow.phpの準備
ここまででひと通りのWorkflowの流れは作成して、残りはコードを書くだけになりました。
コードを書く前に、PHPでAlfredのWorkflowを作成する時にあると便利な「workflow.php」が使える状態にしておきます。
まずはGitHubのjdfwarrior/Workflows: Alfred Workflows Utility Classからworkflow.phpをダウンロードします。
ダウンロードしたら、次は設置です。
AlfredのWorkflowを右クリックして「Open in Finder」を選択します。
![[Open in Finder]の選択](https://webrandum.net/mskz/wp-content/uploads/2019/04/image_8.png)
Finderで「info.plist」というファイルのあるフォルダが開くので、そこにダウンロードした「workflow.php」を設置します。
「workflow.php」に限らず、AlfredのWorkflow作成時に使いたいファイルは全てこのフォルダに入れていきます。
コードを書く
ここからはいよいよコードを書いていきます。コードを書く場所はScript Filterの「Script:」の中です。
まずは自分の書いたPHPを見せておきます。
require('workflows.php');
$w = new Workflows();
$q = "{query}";
$json = $w->request("http://webrandum.net/wp-json/wp/v2/posts/?search=" . urlencode( $q )."&_embed");
for($i=0; $i < 10; $i++){
$array = json_decode( $json , true ) ;
$title = $array[$i]["title"]["rendered"];
$link = $array[$i]["link"];
$w->result(
$i,
$link,
$title,
'',
$icon
);
}
echo $w->toxml();いくつか普通のAlfredのPHPならではの注意点があります。
- 開始と終了の
<?php ?>は不要(「with input as {query}」を選択している時のみ) {query}で引数の取得が可能- 最終的に
toxml();で整形したJSONをXMLにしてechoする(Alfred3からはXML化する必要がないのですが、workflow.phpを使う場合は最終的にこれが必要みたいです)
そして、resultの中に入れた情報がAlfredにリストとして表示されるようになります。
result(
$i, //uid:リストごとに別の値を持つ必要がある
$link, //arg:次のアクションに渡される値(Open URLで開かれる値)
$title, //title:リストに表示されるタイトル
'', //sub:リストに表示されるサブタイトル
$icon //icon:リストに表示されるアイコン画像($iconにすると、Workflowのアイコン画像が入る)
)特徴的なコードは以上になります。
ある程度コードが分かる人であれば、これでもうWorkflowが作れそうですが、ここから更に細かくコードを見ていきます。
必要情報の読み込み
require('workflows.php');
$w = new Workflows();
$q = "{query}";
$json = $w->request("http://webrandum.net/wp-json/wp/v2/posts/?search=" . urlencode( $q )."&_embed");require('workflows.php');でworkflow.phpを呼び出して、$wにオブジェクトを代入しています。
あとは{query}で引数の取得ができるので、扱いやすいように変数に代入しています。
そして$w->request("url")の形で、URLからJSONを取得しています。
WP REST APIで記事の検索結果を取得するには「example.com/wp-json/wp/v2/posts/?search=キーワード&_embed」にアクセスすれば取得できるので、キーワードの部分にはurlencodeをした{query}を書いています。
ループでJSONの内容を抽出する
for($i=0; $i < 10; $i++){
$array = json_decode( $json , true ) ;
$title = $array[$i]["title"]["rendered"];
$link = $array[$i]["link"];
//ここにresultが入る
}次にループの中で、取得したJSONからタイトルとリンクの取得を行っています。
JSONが長いと処理が重くなってしまうので、自分は10回で終わるようにしています。
後は先ほど言った通り、$w->resultの中に取得した情報を入れています。
ちなみに、本当はforeach文を使いたかったのですが、自分のJSONの扱い方が下手なのか、うまくできなかったので断念してfor文にしました。
XML形式にする
echo $w->toxml();最後にXML形式にするためのtoxml();を使用してechoすれば完了です。

エラーログの表示方法
Workflowの右上にある「虫のようなアイコン」をクリックすると画面下の方にエラーログが表示されます。

エラーログを開く前のエラーに関しては表示してくれないので注意しましょう。
まとめ
もっとキレイに書けそうですが、とりあえずJSONで取得できるものに関してはこの方法で、Alfredに表示できそうです。



Delay StartでMac起動後にアプリを遅延起動する
Hazelで「ゴミ箱」の中身を空にする作業を自動化してしまう
Macのアプリインストールとアンインストール方法まとめ
Path Finderのデュアルブラウザで、別枠へのファイル移動とコピーを使いやすくする
Biscuitで普段はブラウザでリンクを開きつつ、ダウンロードリンクはBiscuitで開く方法
Mac版GoodNotes 5でiPadで書いたノートをMacでも閲覧したり編集する
Macのファイル拡張子に紐づいているアプリケーションの管理方法
Google Chromeの別ユーザーへの切り替えを簡単に行うKeyboard Maestroマクロ
Path Finderの情報パネルにある「作成日」「更新日」「追加日」の違い
刷新されたAlfred 4のテーマエディタでエディタのカスタマイズと、公開テーマのインポート方法
iTerm2で「Use System Window Restoration Setting」を設定しているとアラートが表示されて機能しない
Google Chromeのサイト内検索(カスタム検索)機能を別のプロファイルに移行する方法
iPadで入力モードを切り替えずに数字や記号をすばやく入力する方法
iPhoneやiPadでYouTubeの再生速度を3倍速や4倍速にする方法
Keynoteで有効にしているはずのフォントが表示されない現象
MacのKeynoteにハイライトされた状態でコードを貼り付ける方法
AirPodsで片耳を外しても再生が止まらないようにする方法
iTerm2でマウスやトラックパッドの操作を設定できる環境設定の「Pointer」タブ
DeepLで「インターネット接続に問題があります」と表示されて翻訳できないときに確認すること
Ulyssesの「第2のエディタ」表示を使って2つのシートを横並びに表示する
1つのノートアプリにすべて集約するのをやめた理由|2025年時点のノートアプリの使い分け
Notionログイン時の「マジックリンク」「ログインコード」をやめて普通のパスワードを使う
AlfredでNotion内の検索ができるようになるワークフロー「Notion Search」
Gitで1行しか変更していないはずのに全行変更した判定になってしまう
Macでアプリごとに音量を調節できるアプリ「Background Music」
Macのターミナルでパスワード付きのZIPファイルを作成する方法
MacBook Proでディスプレイのサイズ調整をして作業スペースを広げる
SteerMouseの「自動移動」機能で保存ダイアログが表示されたら自動でデフォルトボタンへカーソルを移動させる
iPhoneでタッチが一切効かなくなった場合に強制再起動する方法