MAMPでPHPのバージョンを .htaccess で切り替えられるようにした
環境
やりたいこと
MAMPでは設定で直近2バージョンのPHPを切り替えられるのだが、この方法だと・・・
- 切り替えられるのは2バージョンのみ
- MAMP環境全体をそのPHPバージョンにしてしまう。「特定のディレクトリのみ特定のPHPバージョンにしたい」とかできない
- 切り替える都度、MAMP(Apache)の再起動が必要になる
という問題がある。よくレンタルサーバーなどでは .htaccess でPHPのバージョンを切り替えられるようになっているが、あれをローカル開発環境のMAMPでもできるようにした、という話。こういうやつ↓
https://blog.heteml.jp/?p=5509
前提となる知識
手順自体は簡単なのだが、前提として必要な知識が欠けてたので時間がかかった。サーバ周りよわよわおじさんです。
- PHP動かすにはモジュール版とCGI版がある。いやー単語だけはよく聞くなー!モジュール版とCGI版。今回はじめてその意味がわかった(?)のだが、前者はApache起動時にロードされる(=なのでバージョン切り替えたらApache再起動が必要)。高速。後者はPHPの実行のたびに呼ばれる。遅い。
- モジュール版のPHPは1つのバージョンしか読み込むことができない。最初試しに httpd.conf でPHPの LoadModule 行を2つに増やして別バージョン読み込ませてみたのだが、Apacheが起動しなくなった。笑
- つまり俺のやりたいことを実現するにはCGI版のPHPを動かすしかない。
- CGI版PHPってのは、php-cgiというファイル名で存在してるらしい。MAMPだと /Applications/MAMP/bin/php/php___VERSION___/bin/php-cgi ってやつ(___VERSION___にはPHPのバージョン番号が入る)。知ったときは「なんだよーお前こんなとこにいたのかよー。名前だけはよく聞いてたけどはじめましてよろしくね。nice to meet you!」という気分になった。
- つまり、「ヘイ, Siri。このディレクトリ配下の拡張子phpのファイルは、LoadModuleで読み込んでるPHPじゃなくて、こっちのCGI版PHP、つまり php-cgi ちゃんを使ってくれーーー!」「ピロリン♪ おっしゃっている意味がよくわかりません」という設定を行えばOKということである。
では、具体的な手順。
① ApacheのCGIディレクトリにCGI版PHPへのシンボリックリンクを作成する
まずはApacheがCGIを実行できる場所(不明な場合 httpd.conf の ScriptAlias 参照)にCGI版PHPを設置する。以下、今回はPHP5.6.31という古いバージョンを使いたかったので、そのような記述になっている。
$ cd /Applications/MAMP/cgi-bin/ # ApacheのCGIディレクトリ $ ln -s /Applications/MAMP/bin/php/php5.6.31/bin/php-cgi php56 # php56という名前でCGI版PHPへのシンボリックリンクを作成 $ chmod 755 php56 # CGI版PHPを実行可能にする
② httpd.conf の編集
httpd.conf に次の行を追記。場所はとりあえず元のPHPのLoadModuleの下あたりにしておいた(適当)。①で作ったCGI版PHPを php56-cgi という名前で呼び出すイメージ。
Action php56-cgi /cgi-bin/php56
③ .htaccessの編集
そのバージョンのPHPを動かしたいディレクトリ配下に、.htaccess ファイルを設置し、次の記述を追加する。ちなみに下記では拡張子htmlでもPHPを実行するようにしている。必要なければ「.html」は要らない。
AddHandler php56-cgi .php .html
これで、.htaccess が置かれたディレクトリ配下の拡張子php/htmlのファイルはすべて、php56-cgi(すなわちそれはCGI版PHPであり、ファイル実体としては php-cgi)に引き渡され、めでたくPHPのコードとして処理される。ちなみにそれ以外のディレクトリでは、LoadModule で指定されたPHPバージョンが動く。
古いWordPressを古いPHP環境で動かす
・・・という経験したので記録しておく。先日のFacebookのグレーアカウントの記事といい、普通は誰も経験しないし経験したところで今後の仕事の知見として役立ちそうもない記事ばかり蓄積している気がする。
修行するぞ修行するぞ修行するぞ修行するぞ修行するぞ...
こちらの環境はmacOS Catalina、MAMP。
古いWordPress:3.1.4
元サイトがこれだったので。追ってバージョンアップするとしても、とりあえずローカルPC上で3.1.4をインストールして同じ環境構築して様子をみたい。という事情。これをローカルPC上のMAMPで動かしたい。
- 古いWordPress自体は公式からあっさりダウンロードできた。よしよし。
- ではインストール画面を表示・・・できない。「Internal Server Error HTTP 500」。
- エラーログ確認。Console.appから /Applications/MAMP/logs/php_error.log を見る
PHP Parse error: syntax error, unexpected 'new' (T_NEW) in /___WPまでのパス___/wp/wp-settings.php on line 219
- なるほど!わからん。ググったらPHP7じゃ使えなくなった文法が使われてるとのこと。なるほどですね。ちなみになんか $hoge =& new fuga() のような記述。
- エラーとなった記述はこのバージョンのWordPressの至るところで使われており、修正して云々はできなそう。なのでPHPのバージョンを下げる。5系まで下げれば良さげなのでそうしよう。
- MAMPでは設定で直近2バージョンのPHPが選択できるので、/Applications/MAMP/bin/php/ の中で最新バージョンと php5.4系だけ残してあとはリネームしておく。
- MAMPの設定でこの5.4を選択
- Apache再起動
- ちなみに phpMyAdmin 使えるのか確認したところPHP5.5以上が必要だと怒られる。phpMyAdmin はいちおう使いたいので5.4じゃなくて5.6系を使うことにする。
- ようやく再度WordPressインスール
- 成功しました的な画面が出るが、その画面の上部に思い切りエラーが出てる!
WordPress database error Specified key was too long; max key length is 767 bytes
みたいなの。
- ググる。wp-config.php の文字コードが utf8mb だと出がちなエラーらしい。マルチバイトだとバイト数の計算が違う的なやつだろうと推測。詳しくは調べない。
- 元サイトの wp-config.php 見ると utf8mb ではなく utf8 だったので真似する。
- phpMyAdmin から全テーブル削除して再度インストール(やっぱり phpMyAdmin 使えるようにしておいてよかった←SQL使えない人)
- みたび WordPress インストール
- 成功!
ただこれだとこのWP動かすときだけPHPのバージョン切り替えないといけない。.htaccessでPHPのバージョン切り替える方法もちょっと試したがうまくいかなかった。どうせ短期間だけなので深追いはしていない。
→深追いしました。以下の記事。
neriu.hatenablog.com
EJSとJSONから大量のHTMLを生成するためのメモ
フルスクラッチでゴリゴリHTMLを書いていると避けて通れないのがHTMLテンプレートエンジンの問題。少し前にこんなツイートをしていて、最近はもっぱら html-include をメインに使っていたのだが、ファイル数が数十を超えてくるとやはりEJSが必要になる。
大げさなフレームワーク使うほどじゃないけどカジュアルにHTMLインクルードしたいときの方法の変遷
— 高橋廸久(道久) (@neriu) 2020年6月3日
けっこう前→SSI
かなり前→PHPのインクルード
ちょっと前→EJS
少し前→gulpでがちゃがちゃやる
最近→html-includes
PHPとEJSはなんでもできるっちゃできるので今でも現役#npm #ejs
しかし利用頻度が低いと使うたびにググり直しになるのが辛いので、ここにEJSの始め方をメモしておくことにする。
EJSの本家サイト
ejs.co
想定しているシーン
たくさんのHTMLファイルがあって、タイトルやDescriptionやCanonicalやページごとのclassなどのページのメタ情報をHTMLに直書きするのは辛い・・・みたいなシーンを想定している。要約するとこうだ。
メタ情報をサイト全体で体系的かつ一元的に管理したいと考え「そうだ、まずエクセルにまとめよう」ってなるのはサイト制作あるあるだが、いざそれを元にサイト作って、その後修正やページ追加なんかのタイミングで時間もないしとりあえず簡単だしお腹すいたからっていう理由でHTMLだけを直しちゃってエクセルとズレが生じた瞬間もうエクセルは役立たずになりあとはもうずっとHTMLを個別に修正していくしかない、そのうちぐちゃぐちゃになって「ちょっと男子〜!メタ情報はもっとこうサイト全体で体系的かつ一元的に管理しなきゃダメでしょ〜!」みたいになって「よし!それじゃあ今のHTML全部総ざらいして、メタ情報をまずはエクセルにまとめよっか!」ってなって・・・(以下ループ)・・・みたいなあるあるなシーンを阻止したいというシーン。
を想定している(早口)。
こんなイメージ
0. 準備
npmがインストールされていればそれでOK。
1. EJSに必要なnpmパッケージのインストール
gulpに頼らなくてもできるのだと思うが、とりあえず慣れてるので...。gulp、gulp-ejs、gulp-rename、fsの4つのパッケージをインストールする。
$ npm i -D gulp gulp-ejs gulp-rename fs
fsはファイルの入出力をするパッケージで、今回はJSONの読み込みに利用する。gulp-ejsがEJS本体で、gulp-renameはEJSで出力されたファイル拡張子を .ejs から .html に変換するのに使う。
2. メタ情報を管理するExcelファイルを用意する
ページごとにタイトルとdescriptionを管理するというごくシンプルな例だと、ExcelのA列にページID(p001でもtopでもページを一意に識別できればなんでも良し)。B列にタイトル、C列にdescriptionがあり、それがページ数分だけの行数があるイメージ。便宜上Excelと書いたがわかりやすければなんでもいい。
3. ExcelをJSONに変換する
ここはいろいろツールがあるのだろうが、私の場合はここを使っている。
このページ左側のテキストボックスに、Excelで全選択コピーしたものを貼り付ける。次にOutputに「Hash」を選択する。最後に「Convert」をクリック。以上。
ちなみに「Hash」がキモで、こうするとエクセルのA列すなわちページIDをキーとしたJSONデータが出来上がる。するとEJSで値を参照するときに「data['p001'].title」みたいにできて便利。
これで以下のようなJSONが出力されるのでファイルに貼り付けて保存する。
例: page-data.json
{ "p000": { "title": "ホーム | サイト名", "description": "すごくイケてる会社のホムペです。" }, "p010": { "title": "製品情報 | サイト名", "description": "イケてる製品情報を紹介します。" }, (以下略) }
4. gulpfile.js でEJSのgulpタスクを定義する
下記の例では、ejsフォルダの*.ejsファイルをEJSが処理してdistフォルダに出力する。EJSにはJSONデータ(例ではpage-data.json)を渡している。後述するが、EJSファイルでは渡されたJSON(ページごとのメタデータ)を適宜差し込んだ上でHTMLを組み立てる。そんな処理になっている。
例: gulpfile.js
var gulp = require('gulp'); var fs = require( 'fs' ); var ejs = require('gulp-ejs'); var rename = require('gulp-rename'); gulp.task('ejs', function(done) { var json = JSON.parse(fs.readFileSync('./ejs/page-data.json', 'utf-8')); gulp.src([ './ejs/**/*.ejs', '!' + './ejs/**/_*.ejs' ]) // 第1引数がEJSの処理対象とするファイル、第2引数が除外ファイル .pipe(ejs({ pageData: json })) // これがEJS本体処理。jsonデータを渡してる .pipe(rename({ extname: '.html' })) // 拡張子をhtmlにする .pipe(gulp.dest('../dest/')); // 出力先フォルダ done(); });
5. EJSファイルを用意する
EJSファイル内で使える変数や構文などは解説しているサイトがたくさんあるので割愛する。ここではJSONデータをどうやって展開するかだけ説明する。といっても実に簡単。まずは某ページ(仮にページID「p001」とする)のEJSファイル本体。%で囲まれたEJSの世界以外は普通にHTMLで記述する。
例: index.ejs(なんか適当なページの本体ファイル)
<% const meta = pageData['p001']; %> <%- include('inc/_header.ejs', { 'meta': meta }); %> <div class="main"> (略。ここは普通にHTMLで記述) </div> <%- include('inc/_footer.ejs'); %>
pageDataにはgulpfile.jsのタスクで渡されたJSONデータがまるっと入っているので、その中のページID「p001」の情報のみを取り出して変数 meta に入れている。そしてこの変数 meta を共通ヘッダファイル(inc/_header.ejs)に渡している。ついでに共通フッタ(inc/_footer.ejs)も読み込んでいるが、こちらは全ページ同じなのでデータ受け渡しはなし。
ひとつ注意はEJSタグの使い方。「<% ...%>」で囲まれた範囲は基本はJavaScript構文の世界。それに対して「<%- ... %>」のようにハイフンがつくと、変数やインクルードファイルをHTMLとして展開してそのまま出力する世界となる。「<%-変数名%>」のようにすると、その変数の中身をシンプルに出力できてGood。逆にハイフンなしの「<% ...%>」にinclude構文を書いても何も出力されないので注意。コンパイルエラーにもならないのでハマりがち。
あとファイル名先頭にアンダースコア(_)が付加されているejsファイルは、gulpfile.jsにて出力対象外としている。アンスコつけ忘れると、destフォルダに「inc/header.html」などという意味のないファイルができてしまう。そういう仕組み。
続いて共通ヘッダファイルそのもの。今回のゴールであるページのメタ情報を出力する本体のファイルとなる。
例: inc/_header.ejs(全ページで使う共通ヘッダ)
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title><%- meta.title %></title> <meta name="description" content="<%- meta.description %>"> (以下略)
変数 meta で渡された情報を「<%-変数名%>」で出力している。今回はページタイトルとDescriptionだけだが、同じ要領でOGPタグやページ別のclass名やその他なんでもできてしまう。
6. gulpのejsタスクの実行
いよいよHTMLの生成。gulpfile.jsでタスク名を「ejs」としているのでgulpfile.jsのあるディレクトリでこうする。
$ gulp ejs
数十〜数百くらいのEJSファイルなら一瞬でdestフォルダにhtml出力してくれる。ejs配下のフォルダ構成も維持してくれる。gulpのタスクでejsフォルダをwatchしておけば、ファイル編集する都度htmlを書き出してくれる。
まとめ
必要なのは次のとおり。
- npmパッケージ(gulp, gulp-ejs, gulp-rename, fs)のインストール
- エクセルファイル
- JSON
- gulpfile.js
- EJSファイル
今回は使っていないがEJSは普通にJavaScriptの構文であり、条件分岐もループも使える。なのでたとえば定型化された製品情報をエクセルで持たせておいてEJSで出力といった使い方もできる。エクセルやGoogleスプレッドシートなら誰でも(クライアントでも)編集できるし、データベースやその管理システムなどの大げさな仕組みが不要というのがEJSを使う利点だ。
またEJSに限らずだが、複数人での作業も上記と package.json をgitで共有して $ npm install してもらえばそこからすぐに開発に参加してもらえる。
イラレで選択した複数オブジェクトの幅を縦横比を変えずに揃えるスクリプト
イラレで選択した複数オブジェクトの幅を縦横比を変えずに揃えるスクリプトが欲しかったので作った。車輪の再発明感ハンパないが、ちょっと探した限り、幅のみ変える(=縦横比が変わってしまう)スクリプトはあったのだが、縦横比を変えずに幅を揃えられるのはなかったので……。
仕様
- 選択した複数オブジェクトの幅を、その中の最前面オブジェクトに揃える。
- このとき、各オブジェクトの縦横比は変えないように変形する。
- 選択オブジェクトが1つ以下の場合は何もしない。
GitHub
https://github.com/michihisa/AI-script-set-the-width-of-selected-objects
var selectedObj = activeDocument.selection; // 選択オブジェクトが2つ以上なければ何もしない if (selectedObj.length <= 1) { alert('オブジェクトを2つ以上選択してください。'); } else { // この幅に揃える var w = selectedObj[0].width; for (var i = 0; i < selectedObj.length; i++) { // 縦横比 var ratio = w / selectedObj[i].width; // 変更後の高さ var h = selectedObj[i].height * ratio; // 変更 selectedObj[i].width = w; selectedObj[i].height = h; } }
備考
- SPAiなどのイラレ用スクリプトランチャーがあるとより便利(ショートカット設定も行える)。 https://tama-san.com/spai/
- 整列時のようにキーオブジェクトを指定して、そいつ基準で幅を揃えられると尚良かったのだが、少し調べた限りスクリプトでキーオブジェクトを取得する方法がわからなかった(誰か教えてくれると嬉しいです!)。できないっぽい(?)
Facebookの「グレーアカウント」なるものにハマったのでメモ。
2020/6/26 追記:結果判明。以下の手順でOKだった!ことを追記。
グレーアカウントとは、FB公式によると
グレーアカウントは、個人用Facebookアカウントを使用せずにFacebookページの管理と広告の掲載を行うためのアカウントです。 このため、グレーアカウントの範囲は制限されており、アクセスできる機能が標準のFacebookアカウントよりも制限されています(一部のセキュリティ機能を含む)。
というものらしい。
https://developers.facebook.com/docs/graph-api/changelog/archive/gray-accounts?locale=ja_JP
とにかくグレーアカウントで管理しているFBページは広告も作れずインスタ連携もできない。困った存在なのだ。
しかもグレーアカウントの解除的な操作は(たぶん)ないので困り果てていたのだが、次の手順でちゃんとしたアカウントの管理下に置けたっぽい。ぽいというのは管理者になって7日間は「セキュリティのためまだ何もできませんよ」という期間なので。7日後が楽しみ(怖い)。
で、手順である。
1. 普通のアカウントを用意する
まず当該FBページの管理者として設定したい「通常のFBアカウント」を用意する。これは普段自分(自社)がFB広告出したり、他のFBページ管理したりと常用しているアカウントが良いだろう。なければ作る。
ここが最初のハマリポイントで、最初はグレーアカウントを解除する方向でばかりググっていたために、別アカウントを用意してそいつを管理者に設定すればよい的な情報がさっぱり出てこなかった。
また、その「通常のFBアカウント」のメールアドレスはグレーアカウントのメアドと違うものでなければならない(そもそも同じメアドで複数アカは作れない?)。ので、やっぱりここでも「別アカ用意しよう!」という発想には至りにくいのだ。
2. グレーアカウントでログイン
ログインという初歩的操作にもハマリポイントが。なんとログインできない(笑)。
いや、実はできてるのだがログイン後の画面がリダイレクトループにハマって表示されない。ここで気落ちしてはいけない。気にせずURL欄に http://www.facebook.com/settings/ と入力すれば、ログインした状態で当該FBページの設定ページが表示される(よく気がついたな・・・俺)。アプリでも「表示できねーよ」的なエラーメッセージが表示されるので一瞬もう詰んだかな?って絶望するが、アプリでは設定ボタンが押せるのでPCよりはまだなんとかなる感が高い。
3. 当該FBページの「設定>ページの管理権限」から管理者として1のユーザを追加
権限の種類は最上位の「管理者」で。
ログイン後はこの「ページの管理権限」だなと推測するのは比較的簡単だった。探していた「グレーアカウントを通常アカウントに切り替え」みたいな権限操作メニューがなくてがっかりするが、「ためしに通常アカウントの管理者を追加してみるか」とはギリ思える。半信半疑ながら正解まであと少し!
しかし次でまたハマる。
4. 新しい管理者ユーザに承認依頼がいくので承諾する
何にハマったかって言うと、なんと承認依頼が来ない(笑)。
PCにもメールにも来なくて、まさかスマホアプリにしか来てないなんてことがあるとは思わないので、ここで俺は何度か引き返した。「こっちじゃねーか」って。実はこっちでよくってスマホアプリの通知に承諾依頼が来てるので「承諾」する。これは未だに謎。俺のケースだけなのかなー?
5. 1週間待つ
もちろんここにもハマリポイントがある。1週間待つことではない(いやこれもそうだが)。なんとそもそもその1週間待てっていう指示が読めない(笑)。信じられないと思うかもしれないが本当に読めない。なぜならメッセージが表示されるのは一瞬だけ(1秒未満)だから。「ん?なんか今出てたな……」くらい。
俺の場合はそのFBページと某インスタアカウントを連携したかったので、インスタのスマホアプリのプロフィールの「ページ」から当該FBページを選択したかったのでそうしたのだが、その操作で何やらメッセージが一瞬出て消える。何度繰り返しても同じでもうしょうがないので、iPhoneの画面収録で操作を録画したものを一時停止して見た。人生で一度も使ったのことのないスマホの画面収録機能を「今こそ使うときぞ!」と気がついた自分をここでも褒めてあげたい。
このようにしてようやく「セキュリティ上の理由から、ページで管理者として追加後1週間はこのページのビジネスマネージャへの追加リクエストを承認できません」というメッセージを確認できた。なんだこれ。
以上まとめるとわずか5ステップなのだが5つ中4つにハマリポイントが用意されており、そのひとつひとつで丁寧に着実にライフが削られていく。
というかまだ1週間後にならないと本当に当該FBページとインスタ連携できるのかわからないんだけど……。感触的にはすごくできた感があるので大丈夫だとは思うが、ここまで丁寧な仕事ぶりを見せてくれたFacebookのことなので最後にも大きな罠をしかけていると考えたほうがいいかもしれない。
6. 1週間待った!
大丈夫だった。当該管理者として追加した通常のアカウントでログインし、当該FBページに関するあらゆる権限が付与されていることをかくにん!よかった!
懸案であったインスタアカウントと当該FBページの連携も難なく成功した。いやーホントによかった。もうこれでグレーアカウントが俺の人生に登場しても怖くないぞ(たぶんもう二度と登場しない)。
以上。
Dribbbleのプレイヤーになったぞ!
ちょっと前に古い実績(申し訳ない!)をいくつかアップロードしてDribbbleのドラフトにかけたら、親切な紳士か淑女がプレイヤーに招待してくれたぞ。うぇーい!
今ってDribbbleのプレイヤーになるハードル下がってるのかな。ラッキー以外の何ものでもない気がするが、せっかくなのでいろいろなshotをキメていきたい。
Photoshopで作成したpsdファイルをIllustratorのaiファイルに配置するとクリッピングパスが外れる問題
事象報告。Adobeにも連絡済み。
Photoshop CC 2018で作成したpsdファイルをIllustrator CC 2018で作成したaiファイルに配置したらクリッピングパスが外れた。後述するがCC 2018以前のバージョンでも発生する模様。今まで大丈夫だったpsd & ai ファイルでいきなりそうなったので焦ったが、直前に行った操作というのが「Macのシステム言語を日本語から英語に変更」というものだったので、もういちど日本語に戻したらとりあえず事象は解消(もちろん言語変更ごときでクリッピングパスが外れないのが本来だと思うので根本的な解決ではない)。
ちなみにその前にもうひとつ試したことがあり、それでも事象解消した。つまり「Photoshopでクリッピングパス名を英文にしてから一度クリッピングパスを外し、再度クリッピングパスを設定して保存する」という方法で、もちろん大量のpsd、過去のpsd、他人から受け取ったpsdにまでいちいちこの操作を行うのは現実的じゃないので緊急時の間に合わせ程度にしか使えない。こちらの方法はネット上の情報(https://forums.adobe.com/thread/2251424)を参考にした。どうやら以前のバージョンから存在していた問題の模様で、やはりシステム言語に対する言及もある。
もうひとつ、言語が問題ならばということで「じゃあシステム言語に合わせてイラレとフォトショも英語版にしちゃえば解決じゃね?」と考え果敢に実行してみたところ、ダメだった。とにかくクリッピングパス名が日本語だとダメそうということで、Photoshopでクリッピングパス名を英文にするか、システム言語を日本語に戻すしかない。逆にシステム言語が日本語でありさえすれば、アプリケーション自体が英語版でも事象発生しない(まじかー)。
まとめ。
発生条件をまとめるとこう。
「Macのシステム言語が英語のとき、フォトショCC 2018で作成した日本語のクリッピングパス名はイラレCC 2018上では無効」
バージョンはCC 2018以前でも発生(CC以降?)。Windowsならどうか、他の言語ならどうか等はもちろん不明だが、なんとなく英文クリッピングパス以外全部アウトっぽい気もする。
事後対処は2つあってこう。
「Macのシステム言語を日本語にする」
「クリッピングパス名を英文にしてクリッピングパスいったん解除してまた設定して保存し直す」
うーん辛い。
事前対処も一応ある。
「クリッピングパス名は常に英文にする」
もちろん既存psdに対する対処にはならないし、あと日本語版フォトショはデフォルトのパス名が「パス 1」とかなのでいちいち直すのも辛い。
日本のユーザが海外ユーザにファイル渡す場合は普通に発生しうるケースですし、Adobeさんなる早でお願いしますー。