Drupal 安裝

Drupal 8 安裝

先完成 www 目錄維護 的指示;再繼續。

安裝 Drupal 條件

PHP 7.3.x

安裝 Drupal 8
FileName=drupal-8.9.7 (1)
site=drupal (2)

cd /var/www
wget https://ftp.drupal.org/files/projects/$FileName.tar.gz

tar -xzf $FileName.tar.gz

# 改名為 $site
mv $FileName /var/www/$site

# 別忘了要修正權限
chwww $site

# 如果要建立資料庫
mysqlpw='MySQL root 密碼'
webdbpw='站台資料庫密碼'

mysql -uroot -p$mysqlpw --host=localhost --port=3306 --protocol=tcp -N << EOF
drop database if exists $site; (3)
create database $site;
grant all privileges on $site.* to '$site'@'localhost' identified by '$webdbpw';
use mysql;
update user set plugin='mysql_native_password' where user='$site';
EOF
1 查出 Drupal 8.9 之後的版本 Drupal 7.7 之後的版本
2 site 為站台目錄及資料庫名稱亦為 Apache 的 .conf 檔名。
3 注意!刪除站台資料庫。
$site.conf
site=drupal

sudo a2dissite 000-default.conf (1)

sudo bash -c "cat > /etc/apache2/sites-available/$site.conf" << EOF
<VirtualHost *:80>
  ServerAdmin webmaster@localhost
  DocumentRoot /var/www/$site
  RewriteEngine on
</VirtualHost>

<Directory /var/www/$site>
  AllowOverride None
  Include /var/www/$site/.htaccess
</Directory>
EOF

sudo a2ensite $site
sudo service apache2 reload
1 取消 Apache 安裝時建立的 000-default.conf 站台。

安裝 Composer 及 Drupal Console (重要),再來就可以進入站台安裝,安裝英文 (別裝中文)!

Composer

安裝 Composer
sudo apt update
sudo apt install curl

# 會安裝最新版, 可能跟目前的 drupal 8/9 不相容
# curl -sS https://getcomposer.org/installer | php
# Composer (version 2.0.4) successfully installed to: /var/www/composer.phar
# sudo mv composer.phar /usr/local/bin/composer

# 採用指定版本
curl -sS https://getcomposer.org/download/1.10.17/composer.phar > composer.phar
sudo chmod +x composer.phar
sudo mv composer.phar /usr/local/bin/composer

composer --version
# Composer version 1.10.17 2020-10-30 22:31:58
Composer 常用指令 (除非是 global 否則在執行前必須將目錄切換至 $site)
# composer 自我更新 (跟目前路徑無關)
composer self-update (1)
# Use composer self-update --rollback to return to version <current version>

cd /var/www/$site

# 列出已下載的模組。
composer show | grep drupal

# 下載 drupal/pathauto,會自動下載相關模組。
composer require drupal/pathauto

# 指定版本下載
composer require drupal/pathauto:^1.8 (2)

# 移除模組 (Drupal 要先解除安裝,否則會造成 Drupal 當掉)
drush pmu pathauto
composer remove drupal/pathauto
1 執行 Composer 若出現 Killed 表示記憶體不足,Composer 執行時需要大量的記憶體。
2 實際檔名為 pathauto-8.x-1.8.tar.gz,8.x 表示 Drupal 8,這可忽略,1.8 即為版號。
:^1.8 下載 1.8 版本,:^1 下載 1.x 最新版,可能會比 1.8 還新。

Drupal Console

Composer 安裝 console,安裝的路徑是站台目錄,安裝後會在 vendor/bin 建立一個 drupal 的連結檔,為了方便執行, 可將 PATH 納入該路徑 vendor/bin (採用相對路徑)。

安裝 Drupal Console 常常出狀況,在安裝任何模組之前,先安裝 Drupal Console,甚至在沒有建置站台之前安裝。
使用 Composer 在每個站台目錄中安裝 Drupal Console
# 將目錄切換至 Drupal 站台目錄
cd /var/www/$site

# Install Drupal Console Using Composer
composer require drupal/console --prefer-dist --optimize-autoloader

vendor/bin/drupal --version
# Drupal Console version 1.9.5
# [ERROR] The specified database connection is not defined: default (1)
1 因為還沒有建置站台。

Drush 安裝

Composer 安裝 Drush,安裝的路徑是站台目錄。安裝後會在 vendor/bin 建立一個 Drush 的連結檔, 為了方便執行,可將 PATH 納入該路徑 vendor/bin,採用相對路徑如 export PATH="vendor/bin:…​"

安裝 Drush
# php -v
# PHP 7.3.x (1)
cd /var/www/$site
composer require drush/drush (2)
1 確定 PHP CLI 的版本為 7.3,執行 sudo update-alternatives --config php 切換。
2 不指定版本表示會安裝最新版本,可指定版本如下
composer require drush/drush:10.x
composer require drush/drush:9.x
composer require drush/drush:8.x

Drupal 8 應採用 drush 版本 10,如果是 drush 8.x,drush 的命令會缺少。如果出問題再指定版本安裝即可。
在安裝的過程中若出現黃底的警告,如 Failed to download symfony/polyfill-ctype from dist: The zip extension and unzip command are both missing, skipping. 別怕!已說明缺少 zip unzip,就按指示安裝套件 (apt install)。

Drush 7 安裝

安裝 Drush 7
site=drupal7
cd /var/www/$site
composer require drush/drush:7.x

# 執行 drush, 會出現下列訊息
# count(): Parameter must be an array or an object that implements Countable Table.php:789
# 安裝 新版的 console_table
# 實際的 drush 7 目錄是在 $site/vendor/drush/drush
cd /var//www/$site/vendor/drush/drush
composer require pear/console_table

cd /var/www/$site
drush

Drupal 更新

更新前應看一下 <site>/admin/reports/updates 中的 Release notes 或者是 Update Drupal core via Composer , 不過如果是測試站台或者是 VM 可以 snapshot,那麼出錯再找文件吧。

事先得知 composer 會更新什麼
cd /var/www/$site
composer update --dry-run
更新 Drupal
cd /var/www/$site
chwww .

# composer 自我更新 (別在更新 Drupal 時執行)
# composer self-update (1)
# Use composer self-update --rollback to return to version <current version>

# 依據依賴項目更新核心及模組
composer update --with-dependencies

# 執行資料庫更新
# 別一起貼,可能詢問,另外也不要加入 -y,應看一下提示或錯誤!
drush updb

drush cr
chwww .
1 如果更新成 Composer version 2.x 若無法繼續執行,參閱 Composer 安裝指定版本。

Drupal 8 配置

安裝後,Drupal 相關設置在 $site/sites/default/settings.php,進入網頁,如果網域不符則會出現 The provided host name is not valid for this server.

Trusted Host
$settings['trusted_host_patterns'] = [
  '^yoursite\.com$',
  '^.+\.yoursite\.com$',
];
logo.svg 及 favicon.ico

logo.svg 放在主題根目錄,favicon.ico 放在網站根目錄 (/var/www/$site),sitemap.xml 是讀取網站根目錄的 favicon.ico。

如何檢查網頁是否支援 gzip

採用 Firefox 或 Chrom 按下 Ctrl+Shift+I, 打開「開發人員工具」,點擊 網絡(Network),然後刷新頁面,將列出該頁面的所有響應標題。在列表中找到 Content-Encoding: gzip,則表示該頁面進行 gzip 壓縮。

Firefox 檢查支援 gzip 圖例
Screenshot of the Firefox inspector

Drupal 啟用偵錯

採用 drupal 切換
cp sites/default/default.services.yml sites/default/services.yml (1)
drupal site:mode dev (2)
drupal site:mode prod (3)
1 第一次執行時,services.yml 不存在;將 default.services.yml 複製到 services.yml。
2 Drupal 啟用偵錯模式。
3 Drupal 回復成一般模式。

會啟用 Twig 偵錯的站台表示為測試站台,在切換是可能出現下列錯誤:
[ERROR] Error copying file : $site/sites/default/services.yml
可參考後文的「權限強化」來解決。

啟用偵錯模式
  • 在網頁中顯示 FILE NAME SUGGESTIONS。

  • 網頁出錯時除了顯示「網站遇到非預期錯誤。請稍後再試」之外,也會顯示 PHP 的錯誤訊息。

權限強化

Druapl 在進入管理頁面 <site>/admin/config 時,會將下列檔案改變權限為 555。
stat -c "%a %n" $(find -type d -not -perm 775 -o -type f -not -perm 775)
555 ./sites/default
555 ./sites/default/services.yml
555 ./sites/default/settings.php
可在 $sites/default/settings.php 中加入下列,取消權限強化。
$settings['skip_permissions_hardening'] = TRUE;
<site>/admin/structure/menu/item/1/edit
  • Show as expanded 在選單項目中啟用展開

還有一個重點在 Block layout  Main navigation 項目中配置顯示階層,每個主題都要配置。

<site>/admin/structure/block/manage/bootstrap_custom_main_menu (改為 主題名稱_main_menu)
Configure block
MENU LEVELS

Initial visibility level
1
Number of levels to display
1 修改為 Unlimited

搜尋字元由 3 個字改為 2 個字

<site>/admin/config/search/pages
Search pages
DEFAULT INDEXING SETTINGS

Minimum word length to index
3 修改為 2

Drupal 8 多國語言

開始安裝站台時只安裝英文,而且站台的預設語言及管理者語言必須為英文,在運作期間不可更改。

English (original) 變成 English (英文) (original) 可能是更新或其他不明原因。 Configuration language being overwritten during module install 提到可能預設語言是非英文造成的, 實測的情況除了站台預設語言外也跟管理者語言有關,管理者在非英文的情況下安裝模組或主題

安裝語言模組
<site>/admin/modules

安裝 Content Translation 及 Configuration Translation (自動安裝 language/Interface Translation)。

增加語言
<site>/admin/config/regional/language
Languages

+Add language 安裝語言 Chinese, TraditionalChinese, Simplified

站台必須預設為英文。
註:在安裝 Language 時由網路重新下載各式 .po 翻譯檔儲存在 /var/www/$site/sites/default/files/translations

語言偵測及選擇

<site>/admin/config/regional/language/detection
Detection and selection
Interface text language detection
Content language detection
  • Customize Content language detection to differ from Interface text language detection settings

修正維護 Translate (翻譯) 時,只顯示原始語言,無法輸入翻譯。
暫時啟用 Customize Content language detection。
<site>/admin/config/regional/language/detection
Detection and selection
Content language detection
  • Customize Content language detection to differ from Interface text language detection settings

    DETECTION METHOD
    • Content language

    • URL (啟用 URL 內容偵測)

    • Sessoin

    • User

    • Browser

    • Interface

    • Selected language

Save settings

需要 Content language detection 中的 URL 偵測功能才能輸入翻譯,按下 Save settings 讓該功能處於啟用狀態。之後取消 Customize Content language detection 再次按下 Save settings,不需要 Content language detection 的整個功能。

為什麼會有 Language switcher (Interface text)、Language switcher (Content)?

那是因為 Detection and selection 中啟用了 Content language detection, 未啟用時只有 Language switcher 即為 Language switcher (Interface text)。 當啟用 Content language detection 應以 Language switcher (Content) 做為選擇器。

那 Language switcher (User interface text) 跟 Language switcher (Content) 有何不同?

Language switcher (User interface text) VS Language switcher (Content)
上面提到的兩種分別涉及介面語言和內容語言,有關更多深入的解釋,請查看 Language Negotiation API

使用者頁面顯示英文

除了啟用前面的 User 之外,需配置帳戶的語言。

<site>/user/1/edit

LANGUAGE SETTINGS

Site language

English

URL 語言檢測設定

Drupal 偵測語言的方式有多種,採用 URL language detection configuration 是比較合適的選項, 將 English prefix 改為 en,Chinese, Traditional 則沒有 prefix,可避免站台 URL 需附加 zh-hant。

<site>/admin/config/regional/language/detection/url
URL language detection configuration

PATH PREFIX CONFIGURATION

English (en) path prefix (Default language)

http://site/ en

Chinese, Traditional (zh-hant) path prefix

http://site/

Chinese, Simplified (zh-hans) path prefix

http://site/ zh-hans

Selected language 所選語言配置

設定為中文這是重點,就算是站台預設語這為英文,在 URL 中沒有前綴語言路徑時就是中文。

<site>/admin/config/regional/language/detection/selected
Selected language configuration
Language

Chinese, Traditional

讓 Browser 運作正確

啟用瀏覽器語言檢測,在 Interface text language detection 啟用 (勾選) Browser (Content language detection 中的 Browser 不需啟用)。 另外在 URL 檢測 中的每一個語言都要有 path prefix,把 Chinese, Traditional 設定為 zh-hant, 如果其中有一個語言的沒有 path prefix,按 URL 順序 會將沒有 path prefix 的網址內定為 URL 檢測 的結果,那麼 Browser 檢測已無作用。啟用 Browser 檢測,站台 URL 必需附加 zh-hant
不過!當啟用 Browser 檢測後,選單 (menu) 中的 URL 並沒有前綴語言路徑,就算網址為 <site>/zh-hans 選單語言路徑還是空的, 在簡體中文頁面,去點擊選單又回到了正體中文,Drupal 處理方式並不正確。
安裝 Translatable menu link uri 來解決該問題。 安裝 (modi translatable_menu_link_uri) 後在 Content language 中有 Link override (已啟動)。

<site>/admin/config/regional/content-language
Content language
Custom menu link
  • Link override

在選單項目的維護頁面中會多出了 Link override

site>/admin/structure/menu/item/1/edit
Link (all languages)

/blog

Link override

/blog 該欄位就複製原來 (上面) 的 Link 即可。

註: 在上述中只要改變了語言設置,每次都要執行 dursh cr 才不會誤判。

Disable language

可將網頁去掉特定語言如 English。

<site>/admin/config/regional/language

English 按下 Edit 後,勾選

  • Disable language

安裝
modi disable_language
Language Switcher Extended

隱藏當前語言、若目前網頁沒有翻譯則隱藏語言切換器項目。

<site>/admin/config/regional/language/language-switcher-extended
  • Alter the language switcher for untranslated content entities

    Untranslated Handler

    Hide the language switcher link

    Current language mode

    Hide the language switcher link

安裝
modi language_switcher_extended

翻譯問題

<site>/sites/default/files/translations/drupal-8.x.x.zh-hant.po 有錯誤
msgid "1 comment"
msgid_plural "@count comments"
msgstr[0] "1 篇回應" (1)
msgstr[1] "@count 篇回應"
msgid "1 new comment"
msgid_plural "@count new comments"
msgstr[0] "1 則新回應"
msgstr[1] "@count 則新回應"
1 msgstr[0] "1 篇回應" 實際上應為 "0 篇回應"。
但這並不能怪翻譯,在 <site>/admin/config/regional/translate 中 Filter 出 comment 可以發現
Singular form
1 comment (1)

Plural form
@count comments
1 Drupal 已錯誤,實際應為 0 comment,不過它是 msgid 所以 …​ 要不 Druapl 大可把它去掉即可,0 篇回應 也不需要顯示。

雖然 Configuration export / import 可匯出、匯入翻譯,不過某些翻譯卻是採用文字對應的方式,只能由 User interface translation 修改,若找出的內容有多筆,按下 Save translations 事實上是多筆異動,當異動了不可修改的項目則會出錯。
Include customized translations 只會匯出自訂的翻譯內容,但也會匯出部份的 Configuration translation,匯入時可能出錯,這時只好自行處理。

zh-hant-cust-fixed.po
msgid "1 comment"
msgid_plural "@count comments"
msgstr[0] " "
msgstr[1] "@count 篇回應"

msgid "1 new comment"
msgid_plural "@count new comments"
msgstr[0] " "
msgstr[1] "@count 則新回應"

msgid "Contact"
msgstr "聯絡"

匯入上述檔案時,將 Overwrite non-customized translations 、 Overwrite existing customized translations 或者 Treat imported strings as custom translations 打勾才會覆蓋現有翻譯,更新 Drupal 可能需再做一次。

只能匯入整理過的檔案,否則可能會造成語言錯亂。

採用管理介面操作,實在不方便,常常忘記要勾選那些選項,而且當正體中文跟簡體中文一起處理時容易出錯,採用 Drush Language Commands 以 CLI 來匯入匯出。

安裝 drush_language
modi drush_language
匯出匯入示例
# 匯出 (1)
drush langexp --statuses=customized --langcodes=zh-hant --file=/var/www/files/config/translate/zh-hant.po

# 匯入整理的檔案
drush langimp --langcode=zh-hant /var/www/files/config/translate/zh-hant-cust-fixed.po
1 --statuses 的預設值為 customized,同時一併匯出其他類型時;雖然 drush langexp 的 --statuses 參數說明中提到可以採用以逗號分隔列表,但測試時會錯誤,可改用多個 --statuses 參數,如 --statuses=customized --statuses=not-customized 來解決。
匯入時出現下列訊息
[warning] trim() expects parameter 1 to be string, array given PoStreamReader.php:223 (1)
1 trim 預期參數 1 為字串,但給予陣列,不過這只是警告。在匯入檔的 msgid 有多行的情況下,測試結果合乎預期,並沒有問題。

Drupal 8 模組

為什麼要採用 composer 來下載或移除模組?

因為會一起下載相依模組,另外移除時也會一併刪除相關模組,強列建議採用 composer 來維護模組檔案。

drush 模組安裝及解除安裝

drush 安裝是指 Druapl 是否使用該模組,解除安裝後該模組的組態則被刪除 (模組建立某些欄位或資料會消失,重新安裝模組需再次輸入), 但是模組檔案還是存在,因為尚未以 composer 移除。
drush 採用 uninstall (pmu) 來命名解除安裝,不過卻採用 enable (en) 來命名安裝, 在網頁中倒是很明確是 Install、Uninstall。看到 enable (en) 要想成 install。

應先在測試站台安裝模組,一開始就測試解除安裝,有些模組解除安裝會出錯,測試無誤後才在實際站台安裝。
模組安裝及移除
# site=drupal
site=try1
extension=pathauto

cd /var/www/$site
composer require drupal/$extension
# Install
drush en $extension -y
chwww $site

# Uninstall
drush pmu $extension -y (1)

# Remove
composer remove drupal/$extension (2)
1 別忘了要測試解除安裝不會引發錯誤,如果出錯,表示這個模組並沒有正確移除 Drupal 組態。
2 移除模組前,記得 Drupal 要先解除安裝,否則會造成 Drupal 當掉。
以 Drush 安裝模組,要注意檔案權限問題。
cd /var/www/$site
# 安裝模組 Language / Configuration Translation / Content Translation / Interface Translation
drush en language, config_translation, content_translation, locale -y

find . ! -user www-data -ls
# ubuntu ubuntu $site/sites/default/files/translations
chwww $site (1)
1 採用 drush 安裝模組會建立相關路徑及檔案而擁有者為 ubuntu。 由 drush 安裝模組後,記得!每次都要以 chwww $site 重設擁有者為 www-data,最好!composer 下載模組後也重設擁有者。

若需要更多模組資料參閱:Drupal 模組介紹

模組維護指令碼

模組維護指令範例
# 安裝模組
modi 模組

# 安裝模組時一併測試解除安裝
modi 模組 --test

# 模組解除安裝
modu 模組
modi 安裝模組
# 如果要指定 composer 的自訂版本, 指定本參數
# CustomVersion=8

bind "set disable-completion on"

bash -c "cat > /var/www/bin/modi$CustomVersion" << EOF
#!/bin/bash

tab='	'
nl='
'
IFS=" \$tab\$nl"

usage="Usage: \${0##*/} [OPTION] MODULE[:^VERSION]

Require module and install.

options:
  -t, --test		Test uninstall
  -c, --cr   		Clear cache"

Uninstall=0
clearCache=0
while [ "\$#" -gt 0 ]; do
  case "\$1" in
    -t|--test) Uninstall=1; shift;;
    -c|--cr) clearCache=1; shift;;
    -h|--h*) echo "\$usage"; exit 1;;
    -*|--*) echo "unknown option: \$1" >&2; exit 1;;
    *)
      if [[ -z "\$Mod" ]]; then
        Mod=\$1;
      else
        echo "Too many modules!" >&2;
        exit 1;
      fi
      shift;;
  esac
done

if [[ -z "\$Mod" ]]; then
  echo "\$usage"
  exit 1
fi

if [ "\${PWD%/*}" != "/var/www" ]; then
  echo 'Not site directory!' >&2
  exit 1
fi

echo composer require drupal/\$Mod
set -e
composer$CustomVersion require drupal/\$Mod
echo drush en \${Mod%%:*} -y
drush en \${Mod%%:*} -y

if [ \$Uninstall -eq 1 ]; then
  echo drush pmu \${Mod%%:*} -y
  drush pmu \${Mod%%:*} -y
  echo drush en \${Mod%%:*} -y
  drush en \${Mod%%:*} -y
fi

if [ \$clearCache -eq 1 ]; then
  echo drush cr
  drush cr
fi

if [ "\$USER" != "www-data" ]; then
  echo sudo sh -c "chown -R www-data:www-data \$PWD; chmod -Rf 775 \$PWD"
  sudo sh -c "chown -R www-data:www-data \$PWD; chmod -Rf 775 \$PWD"
fi
EOF

bind "set disable-completion off"
sudo chmod +x /var/www/bin/modi$CustomVersion
modu 解除模組及移除
# 如果要指定 composer 的自訂版本, 指定本參數
# CustomVersion=8

bash -c "cat > /var/www/bin/modu$CustomVersion" << EOF
#!/bin/bash -e

nl='
'
IFS=" \$nl"

usage="Usage: \${0##*/} MODULE [OPTIONS]

Uninstall the module and remove.

OPTIONS:
  -r, --remove	Remove MODULE
  -c, --cr   		Clear cache"

RemoveModule=0
clearCache=0

while [ "\$#" -gt 0 ]; do
  case "\$1" in
    -h|--h*) echo "\$usage"; exit;;
    -r|--r*) RemoveModule=1; shift;;
    -c|--cr) clearCache=1; shift;;
    -*|--*) echo "unknown option: \$1" >&2; exit 1;;
    *)
      if [[ -z "\$Mod" ]]; then
        Mod=\$1;
      else
        echo "Too many modules!" >&2;
        exit 1;
      fi
      shift 1;;
  esac
done

if [ -z "\$Mod" ]; then
  echo "\$usage"
  exit 1
fi

if [ "\${PWD%/*}" != "/var/www" ]; then
  echo 'Not site directory!' >&2
  exit 1
fi

echo drush pmu \$Mod -y
drush pmu \$Mod -y
if [ \$RemoveModule -eq 1 ]; then
  echo composer$CustomVersion remove drupal/\$Mod
  composer$CustomVersion remove drupal/\$Mod
fi

if [ \$clearCache -eq 1 ]; then
  echo drush cr (1)
  drush cr
fi
EOF

sudo chmod +x /var/www/bin/modu$CustomVersion
1 composer 移除模組後 drush pm-list 該模組還是存在列表之中,若需要下達參數 -c

Drupal Modules 目錄結構

$site
└── modules
    ├── contrib (1)
    │   ├── config_filter
    │   ├── config_split
    │   └─ ...
    ├── custom (2)
    │   ├── myfeatures
    │   └─ ...
    ├── migrate_d7alias (2)
    └─ ...
1 官方模組安裝目錄
2 自訂模組安裝目錄
手動安裝及移除 admin_toolbar
cd /var/www/$site
tar -xzf /var/www/files/d8mod/admin_toolbar-8.x-2.4.tar.gz --directory=modules/contrib (1)
drush en admin_toolbar (2)
drush pmu admin_toolbar
rm -r /var/www/$site/modules/contrib/admin_toolbar
1 假設 Admin Toolbar 已經下載至 /var/www/files/d8mod,tar 解壓至 modules/contrib。
2 如果安裝時出現下列訊息,表示沒有下載相關模組,無法安裝。
Unable to install modules: module <Module Machine name> is missing its dependency module config_update.