丸山 ひかる
本書をお⼿に取ってくださり、ありがとうございます。Drupal Meetup 豊田のメンバーで、3冊目のDrupal書籍を発行することができました。最初のきっかけは「技術書典にDrupal本がないから、自分たちで作ろう!」から始まったことがここまで継続するとは、当初は考えられませんでした。これもひとえに、本を購入し、読んでくださる読者の皆様のおかげです。
今回も、Drupal LOVEな7名のメンバーのとっておきのレシピを1冊にまとめ上げました。最後までごゆっくりとお楽しみいただけたら幸いです。
Drupalをインストールして簡単なサイトを作ったことがあるDrupalビギナーを想定として、
・settings.php探訪
・Webformをアンケート収集に活用しよう
・Feedsモジュールの活用とDrupalから記事配信まで
・Geofieldモジュールで位置情報を可視化
・Drupalで理解するOAuth 2.0
・インストールプロファイルを作ってみよう
・Drushの独自コマンドを作ってみよう
といった、Drupalをもっと深く使っていくためのトピックスを取り上げています。
各章の末尾には4コマ漫画も時折登場しますので、肩に力を入れず、ぜひ楽しみながら内容の理解を深めていただけたらと思います。
本書のタイトルが「Drupal 9 おいしいレシピ集 2」となっているように、各章は今すぐ使える実践的なテクニックが、それぞれ独立した1章完結のオムニバス形式の構成となっています。すべての章を順番に読んでいただいても、お好きな章から読んでいただいても大丈夫です。著者それぞれに思い入れのあるトピックを選んで書き上げた渾身の一冊ですので、最終的にはぜひすべての章に目を通していただけたら幸いです。
本書を読むにあたり、次のような知識があるとより理解が深まります。
・Drupalの基礎知識
・Linux コマンドの基礎知識
・WordPress、concrete5、Joomlaなどの他CMSの利用経験
・Web開発の基礎知識
まだDrupalを触ったことがないという場合には、ぜひ既刊の商業誌「Drupal 9 Web開発ことはじめ」(株式会社インプレスR&D)1と併せて、お手に取っていただけましたら幸いです。Drupalの概要から基本まで丁寧に解説していますので、一緒に読んでいただけると、理解がより一層深まることと思います。
また、所々、既刊の「Drupal 9 おいしいレシピ集」(株式会社インプレスR&D)2で取り上げた内容を参照する部分もあります。まだお読みになっていない方は、こちらもぜひご一読いただけると幸いです。
本書は執筆時点の最新版Drupal 9.3.xにて動作確認を行っています。各章のトピックに固有なソフトウェアおよびハードウェアの要件については、章内の本文にてご確認ください。
同人誌・商業誌を手に取ってくださり、SNSやMeetupをはじめとして、各所でお寄せてくださったご意見・ご感想が執筆の原動力となっています。今回も執筆を応援してくださった方々に、この場を借りて心より感謝を申し上げます。
そして、これまでDrupalをよりよくするために様々な形で貢献してくださった世界中の方々に、心より感謝を申し上げます。こうして私たちがDrupalと出会い、同人誌を執筆できているのも、今までに貢献してくださった方々の足跡があってこそです。本当にどうもありがとうございます。
本書は、Drupal Meetupに集まっているコミュニティーメンバーで執筆し、相互に原稿のレビューを行いました。普段のお仕事がある中で、貴重な時間を捻出しながら執筆活動にコミットしてくださったことは、きっと今後のDrupalの発展に寄与するものと思います。末筆ではありますが、各執筆メンバーのDrupalに対する貢献という不断の努力に感謝いたします。
本書籍は、技術系同人誌即売会「技術書典12」で頒布されたものを底本としています。
本章では、サイト固有の設定ファイルであるsettings.phpを読み進めながら、一緒にコードリーディングを擬似体験します。
小松 高廣
みなさんはコードを読むことが好きですか?
「はい、好きです。」と胸を張って言える人には、この章はあまり役に立たないかもしれませんが、「うーん...」と少しでも考えてしまった人にとっては、本章が何かのきっかけになるかもしれません。
世の中には様々なプログラミング言語で書かれた、非常に膨大な量のソフトウェアが存在しています。Drupalは、GPLv2以降のライセンス1で配布されているOSS(オープンソース・ソフトウェア)で、その一番のメリットは何といっても「ソースコードを読もうと思ったら読めること」だと筆者は思っています。2
どんな作品であろうと「できあがった完成作品を五感で堪能して、その機能や美しさに感動する」という楽しみ方があります。一方で、人(あるいは機械)が作品を作っている過程を見る、アイデアや思考プロセスが映し出された設計図を見る、作る行為や思考を自分で再現(トレース)してみる、といった楽しみ方もあります。
料理でたとえるならば、お店へ行ってシェフが作るおいしい料理に舌鼓を打つ、という楽しみ方だけでなく、料理番組やレシピを見てみる、自分でレシピに沿って作ってみる、というのも料理の楽しみ方のひとつです。
ふと、本から目を上げて自分の周りを見渡してみると、目に映るありとあらゆる人工物は、ひとつひとつすべて誰かが設計し、作り上げたものであることに気づきます。世の中の誰かが作りたいものを発想し、作り方を考え、原材料を採掘し、加工して作り上げる。そして、いろんな流通経路をたどる、というプロセスを経て、最終的にやっと自分の目の前にやってくる。そこに至るまでの膨大な時間や労力に思いを馳せると、人類の叡智による営みにただただ圧倒されます。
ソフトウェアであれ、ハードウェアであれ、それらの人工物を作るための背後には、ソースコードやレシピ、回路図、楽譜、原稿、原画、型紙、原型、金型など、作り手が時間とお金を費やして作り上げた努力の結晶とも言うべき設計図3が存在しています。
普段使っているデバイスのソフトウェア(たとえば、パソコンやスマホのOSや電子機器のファームウェアなど)は、必ずしもすべてのソースコードが公開されているわけではなく、残念ながら読むことができないものも多いです。そして、そういったソフトウェアにもし何らかのバグがあった場合、ユーザーとしては製造メーカーが直してくれるまで待ち続ける必要があります。
でもOSSの場合、直そうと思えば、自分でソースコードを読み、そのバグを直すことができます。そして、必要があれば、自分でコードを書いて機能を追加し、それを使う自由が与えられているのも、OSSの魅力です。
OSSのソースコードを読んでいると、コメントや変数名のスペリングミスにもよく出会います。そういったところを見かけると、筆者はコードを書いた人にとても人間味を感じてしまいます。
OSSは世界中のコントリビュータが作り上げ、寛大な心で利用を許してくれている人類共通の財産です。そんな人類の叡智が詰まったソースコードがオープンになっているにもかかわらず、それを読まないことはすごくもったいないです。ソースコードを読むことは、何も「よーし、これからがんばって読むぞ!」と気合いを入れて行うのではなく、本を読んだり、テレビを見たり、SNSを確認するのと同じぐらいの軽い気持ちで行うと長続きします。まずはコーヒーを入れて、気軽にブラウザーやテキストエディターを開き、ソースコードを読むことから始めてみましょう。
息を吸うようにソースコードを読むコツ、それは「自分が読もうと思った瞬間に、すぐ読める環境を整えること」です。
DrupalのソースコードはGitリポジトリーhttps://git.drupalcode.org/project/drupalで管理されています。まずはこのURLをブラウザーで開いてみましょう。
どうでしょう?開いてみましたか?
では、このサイトをブラウザーにブックマークして、いつでも読めるようにおきましょう。ついでにSNSにURLも投稿しておけば、ふと次に気が向いたときにコードを読む自分へのリマインダにもなります。
単にDrupalのソースコードを読むだけであれば、ブラウザーからでも十分可能です。しかし、ソフトウェアなので、やっぱりコードを動かしてみたくなります。料理の場合、レシピを読むだけではなく、レシピ通りに自分でも作ってみると、レシピに書かれている内容や意図をより深く理解できます。同じように、コードも読みながら実際に動かしてみると、コードを書いた人の気持ちや意図が少しずつわかってきます。それがコードリーディングをもっともっと楽しくするための秘訣です。
本章執筆時での筆者オススメのDrupal向けローカル開発環境は、Lando4またはDDEV-Local5です。
どちらもDrupalが動作するために必要なLAMP(Linux/Apache/MySQL/PHP)環境を手元のPC内に簡単に構築できるソフトウェアです。今回は、Landoを使ってみます。6
Landoの導入については、公式ドキュメント7を参考にしながら、ご自身のCPUおよびOSに適したインストーラーをダウンロードして導入してみてください。
また、macOSを利用している人は、以下のコマンドでHomebrewおよびComposerをインストールしておきましょう。
% cd ~/
% /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
% brew install composer
それでは、Landoを使ってDrupalが動作するプロジェクトを作成してみます。
% cd ~/
% composer create-project drupal/recommended-project drupal
% cd drupal
% lando init --source cwd --recipe drupal9 --webroot web --name my-lando-app
? From where should we get your app's codebase? current working directory
? What recipe do you want to use? drupal9
? Where is your webroot relative to the init destination? web
? What do you want to call this app? my-lando-app
Your app has been initialized!
Go to the directory where your app was initialized and run lando start to get rolling.
Check the LOCATION printed below if you are unsure where to go.
Oh... and here are some vitals:
NAME my-lando-app
LOCATION /Users/takahiro/drupal
RECIPE drupal9
DOCS https://docs.lando.dev/config/drupal9.html
ここでDrupal 9.3.0から正式対応したPHP 8.1を使うように、Landoの設定ファイルに追記します。
% vi .lando.yml
name: my-lando-app
recipe: drupal9
config:
php: 8.1
webroot: web
Drupalのインストール時に必要なデータベースの情報は、以下のように確認できます。
% lando info
[ { service: 'appserver',
urls: [ 'http://my-lando-app.lndo.site/', 'https://my-lando-app.lndo.site/' ],
type: 'php',
healthy: true,
via: 'apache',
webroot: 'web',
config: { php: '/Users/takahiro/.lando/config/drupal9/php.ini' },
version: '8.1',
meUser: 'www-data',
hasCerts: true,
hostnames: [ 'appserver.mylandoapp.internal' ] },
{ service: 'database',
urls: [],
type: 'mysql',
healthy: true,
internal_connection: { host: 'database', port: '3306' },
external_connection: { host: '127.0.0.1', port: true },
healthcheck: 'bash -c "[ -f /bitnami/mysql/.mysql_initialized ]"',
creds: { database: 'drupal9', password: 'drupal9', user: 'drupal9' },
config: { database: '/Users/takahiro/.lando/config/drupal9/mysql.cnf' },
version: '5.7',
meUser: 'www-data',
hasCerts: false,
hostnames: [ 'database.mylandoapp.internal' ] } ]
service: 'database' 以降がデータベース接続に関する項目で、internal_connectionおよびcredsの情報を後ほど使用します。それでは、Drupalを動作させるための各サーバーを起動してみましょう。8
% lando start
Let's get this party started! Starting app my-lando-app...
Starting landoproxyhyperion5000gandalfedition_proxy_1 ... done
Starting mylandoapp_appserver_1 ... done
Starting mylandoapp_database_1 ... done
Scanning to determine which services are ready... Please standby...
Your app has started up correctly.
Here are some vitals:
NAME my-lando-app
LOCATION /Users/takahiro/drupal
SERVICES appserver, database
APPSERVER URLS https://localhost:63403
http://localhost:63404
http://my-lando-app.lndo.site/
https://my-lando-app.lndo.site/
次に、手元にあるテキストエディター(またはIDE)で、Drupalのソースコードを開いてみましょう。テキストエディターも、世の中には本当に多種多様なものがあります。最近は Visual Studio Code、Atom、PhpStormなどが人気ですが、ご自身が好きなものを使ってください。9
PHPに対してシンタックスハイライトが効くと、構文や変数が見やすくなるので、もっとコードを読むのが楽しくなります。もしシンタックスハイライトが有効化されていないテキストエディターであれば、設定や拡張機能を確認してみてください。
では、試しにブラウザーがサイトへアクセスした際に、最初に実行されるdrupal/web/index.phpを見てみましょう。
% cat ~/drupal/web/index.php
<?php
/**
* @file
* The PHP page that serves all page requests on a Drupal installation.
*
* All Drupal code is released under the GNU General Public License.
* See COPYRIGHT.txt and LICENSE.txt files in the "core" directory.
*/
use Drupal\Core\DrupalKernel;
use Symfony\Component\HttpFoundation\Request;
$autoloader = require_once 'autoload.php';
$kernel = new DrupalKernel('prod', $autoloader);
$request = Request::createFromGlobals();
$response = $kernel->handle($request);
$response->send();
$kernel->terminate($request, $response);
...あまりに抽象化されたコードで、そしてコメントもほとんどないため、正直なところ読んでいても全く親近感が湧かないのではないかと思います。
Drupalは多くのエンジニアによって書かれた非常に膨大なコードの集積により作られている10ため、メリハリをつけて読まないと、時間がいくらあっても足りなくなりそう11というのは容易に想像がつきます。
DrupalはSymfonyフレームワークをベースに開発されているので、そのコードは抽象化されている部分も多いです。ですので、Drupalのコードリーディングに関していえば、index.phpから順に読み進めるよりも、もっと身近な設定ファイルなどから読み始めるのがいいと思います。
筆者がコードリーディングをするときのオススメの読み方は、「まず全体を見て、どんな区画に分かれていて、そこに何が書かれているかを意識して読み始める」というアプローチです。12
本でいえば「まず本の章構成を意識しながら目次を読む」ということに該当するでしょう。まずは大枠を掴むことができる地図を自分で作ることから始め、それから少しずつ自分の興味が持てるところを読み進めると、徐々に「ここ、前に見たことがある!」と安心できる空間を広げていくことができます。
もちろん本当に重要なコードであれば、2周目、3周目と読む機会は必ずやってきます。そして、そのときになって、さらにじっくりと時間をかけて深く読み進めればよいです。いずれ理解としての点と点がつながって、線となる瞬間がやってきます。
最初はあまり気負って精読するのではなく、まずは少し俯瞰してから、森の探索に向かいましょう。
それではコードリーディングのはじめの一歩として、まずはDrupalにおけるサイト固有の設定ファイルsettings.phpを一緒に探訪してみたいと思います。
さっそくsettings.phpの中身を見ていきましょう!...といいたいところですが、そもそもsettings.phpは一体どこにあるのでしょうか?まずは、テキストエディターでsettings.phpの在りかを探してみましょう。どうでしょう?見つかりましたか?
前節のように、composerコマンドでdrupal/recommended-projectパッケージを利用してプロジェクトを作成した場合、drupalプロジェクトのディレクトリーおよびファイル構造はリスト1.2のようになっています。13
drupal/
|-- composer.json
|-- composer.lock
|-- example.gitignore
|-- vendor
| |-- autoload.php
| `-- composer
`-- web
|-- index.php
|-- autoload.php
|-- update.php
|-- core
| |-- profiles
| |-- themes
| `-- modules
|-- profiles
|-- themes
|-- modules
`-- sites
|-- default
| `-- default.settings.php
|-- example.settings.local.php
`-- example.sites.php
実は、Drupalをダウンロードした段階では、settings.phpはそもそも存在していません。でも、なんだか似た名前のファイル drupal/web/sites/default/default.settings.php という名前のファイルがありますね。実はDrupalをインストールすると、このファイルを雛形にしたsettings.phpが同じ階層に生成されます。
なので、まずは先に、Drupalをインストールしてみましょう。もう一度
% lando info
を実行してみてください。そして、service: 'appserver' のurlsに書かれたURLに対して、どれか好きなものにブラウザーでアクセスしてみてください。ブラウザーによってはTLS証明書のエラーが出てしまうかもしれませんが、今回はテストなので、そのまま進めてアクセスして大丈夫です。
インストール時に唯一注意が必要なのは、先ほど確認したデータベース接続情報を入力する画面です。「データベース名」「データベースのユーザー名」「データベースのパスワード」に対しては、すべて共通のdrupal9を入力します。「高度なオプション」の「ホスト」項目に対して、先ほどコマンドlando infoで確認した際にservice: 'database'のinternal_connectionに書かれていたホスト名databaseを入力します。
ここで、ソースコードや付随するドキュメントを読んでいく上で、押さえておきたいDrupalの用語・概念をいくつかご紹介します。
ドキュメントルート(document root/docroot)
ブラウザーがアクセス可能なHTTPサーバーの公開ディレクトリーで、index.phpが存在している場所です。HTTPサーバーの設定ファイル内で、ドキュメントルートとして指定する14ディレクトリーです。リスト1.2では、ディレクトリー drupal/web/ になります。
コードベース
開発時にGitリポジトリーで管理するコードの一式です。リスト1.2では、ディレクトリー drupal/ 以下にあるすべてになります。必ずしもすべてのディレクトリーやファイルをGitリポジトリーにコミットする必要はないため、drupal/web/example.gitignoreを参考にして
% cp example.gitignore .gitignore
のようにファイルをコピーして、必要なものだけをGitの管理対象としてください。15
サイト
Drupalでサイトを作るときに必要な要素として、以下のものがあります。
・コードベース(codebase)
・データベース(database)
・構成(configuration)
・ファイル(files)
・URL
コードベースには、Drupalコア、テーマ、モジュールが含まれます。基本的にひとつのサイトには、上記に挙げた要素をサイトごとにそれぞれひとつずつ用意して、独立したサイトとして作ることが多いです。
一方、Drupalにはマルチサイトという機能もあります。マルチサイトはさきほど挙げた要素のうち、「各サイトのコードベースを可能な限り共有して、複数のサイトを効率よく管理する」というものです。16
テーマおよびモジュールは、マルチサイトの各サイトで個別のものを利用することが可能ですが、マルチサイトの趣旨を考えると、モジュールを共通化できる性質のサイト群をマルチサイトとしてまとめ、構築・運用するのがいいプラクティスだと思います。