Vueでrouterのヒストリーモードを使ってサブディレクトリで運用する

Vueのrouternのヒストリーモードとは通常のハッシュモードとは違い、#なしの普通のURLで1ページアプリを実現する方法。これをサイトのルートで運用するときはマニュアルに書いてある通りなのでハマることはないのだが、サブディレクトリでやろうとすると大変だったので覚書。

ここではサブディレクトリを/homepageとする。

vue.config.js

vue.config.jsを以下のように書く。

router.js

src/router.jsを以下のように書く。

.htaccess

public/.htaccessを以下のように書く

CORSが難しい

CORSはクロスサイト間のリソース管理。Javascriptから他のサイトのリソース取得を管理するためのプロトコル。

通常こういったクロスオリジンのアクセスは許されないが(ブラウザが許さない)サーバがあるhttpヘッダを返すことで許すことができる。

Access-Control-Allow-Origin

このヘッダを付けることで、クライアントはその値と自分のJSのサイトが一致していたら通信を許可する。.htaccessに以下のように記述すると、すべてのクロスオリジンアクセスを許す。

制限

通常は完全にアクセスを許すことはしたくないはずなので自分のサイトだけを登録するが、サイトが複数ある場合はデバッグ中のlocalhostを加えたい場合は面倒なことになる。

更にサイトがディレクトリを掘っていて、ディレクトリごとに.htaccessがある場合とかだっともっと複雑になる。

サイトが複数ある場合

とりあえず動いているものとして、以下の.htaccess。

これはlocalhostとtango.dip.jpを許可する。返されるヘッダにはアクセス元のサイトのみが返るのだと思われる。

仕様によると以下の記述でもいいらしい。(試していない)

メソッド

上記の.htaccessにはメソッドの記述もあるが、これは許すメソッドを定義しているものと思われる。そのためにブラウザはOPTIONメソッドでリクエストしてこの情報を得るものと思われる。このときのURLはサイトのURLと同じと思われるので、PHPなどが動くときは200が返るようにしておかないと、Chromeなどはエラーを出す。OPTIONのときはPHPの$_POSTがないと思われるので、このとき500とかを返すとCORSがうまくいかない。

ChromeなどのエラーResponse to preflight request doesn’t pass access control checkはこのOPTIONを指しているものと思われる。

このように非常に面倒で、ヘッダとかを調べるのも面倒なので適当に書いた。ヘッダを確認するにはChromeのDEVTOOLSを使うといい。304になってしまう場合は、シフトキーを押しながらリロードするか、リロードボタンで右クリックして、ハードリロードなどを選ぶ。タイプコラムがxhrになっているのがスクリプトからのアクセス。

ChromeのDevToolでCORSを調べる

axiosでPOSTしたデータがサーバのPHPの$_POSTで取得できない

axiosでpostしたオブジェクトはjson形式でサーバに送られる。content-typeはapplication/jsonで送られる。PHPはこれを$_POSTに入れない。通常のhtmlのformで送られるデータとはcontent-typeも中身も違う。このjsonで送られたデータをどうやってPHPで取得すればいいか。

axiosでformDataを送る

1つの解決法はaxiosでPOSTするときにフォーム形式で送る方法。これはオブジェクトの代わりにformDataを設定する方法とcontent-typeを設定する方法があるようだがここでは考えずサーバで対応する方法を考える。

PHPでjsonを受け取る

ここではapache2+PHPのサーバを考える。その前にクライアントからポストしたデータ(HTTPのボディ)はどのように扱われるのだろうかをはっきりさせたい。

PHPのマニュアルによるとcontent-typeがapplication/x-www-form-urlencodedmultipart/form-dataの場合は$_POSTにデータが入るらしい。マルチパートというのはもともとは1つのファイルに複数のファイルを埋め込む方式でメールなどで添付ファイルを送るときに使われたものだと思う。境界となる長い文字列を設定し、それでファイルを分割する。大きいファイルを送るとき、あるいは単にファイルをおくるときはブラウザはこの形式を使うのかもしれない。あるいはバイナリを送りたいときエンコードを指定して送るから必要になるのかもしれない。

いずれにしろ$_POSTにデータが入るのはこの2つの場合だけなのでapplication/jsonの場合は$_POSTには入らない。ではどこへ行くのか?あるいは単に捨てられてしまうのだろうか。

php://input

結論を言うとここにあるように、php://inputに行くらしい。これはPHPにおいて標準入力を表すときにphp://stdinなどと書くが、php://inputはPHPによってHTTPボディからの入力にリダイレクトされていてPHPスクリプトからはここから読み込めばHTTPボディが取得できることになる。

jsonの取得

今回のデータはjson形式なのであとはこれを$_POSTに変換してあげればその他のコードは変更せずに動くはず。

元のサイトのコードが少しおかしかったので修正した。

以下のようにpostmanで送るとPHPで取得できた。

多数の似たようなSQLを実行したい場合pythonでSQLを出力するといい

多くの似たようなSQLを発行したい場合、例えばプログラムのfor文で回せば処理できるような場合どうすればいいか。一般にSQLはfor文はないから、pythonなどでスクリプトを書くのもいいかもしれない。がスクリプトでDBを開いてとか書くのが面倒。そこでpythonでSQLだけを出力して、それを実行してしまえばいい。

jupyter

こういうときのちょっとしたpythonスクリプトを書くにはjupyterが便利。
まずは1個のSQLをpythonのprintで出力してみる

次にfor文で回す。SQLはformatで置換する。

文字列中の{0:03}はformat引数の0番目の値を3桁で0で埋めることを指定している。これを実行すると以下のようなSQLが得られる。

あとはこれはphpMyAdminにコピペしたり、mysqlに直接流し込んでもいいかもしれない。DBの変更は間違うと大変なのでよくチェックしてから行おう。

Ubuntuに最新のnodeをインストール

ubuntu16.04のaptでインストールするnodeは古くてvue cliを使えなかったので最新にしたい。

しかしすでに32ビットはnode 8までしかないようだ。
ここを参考にインストール

これは8をインストールする場合。64ビットUbuntuの場合は最新をインストールできる。

インストール後

$ node –version
v8.16.0
$ npm –version
6.4.1
$ vue –version
3.9.1
$

phpのcomposer覚書

nodeのnpmに近いphpのパッケージと依存マネージャ。

composerはパッケージマネージャではなく依存マネージャ。パッケージやライブラリの管理は行うがあくまでプロジェクト単位で行う。パッケージやライブラリはvendorディレクトリ配下にインストールされ、デフォルトではグローバルにインストールされない。npmやbundlerに近い。

プロジェクトが多数のライブラリに依存し、そのライブラリも他のライブラリに依存している場合に依存関係を解決してインストールしてくれる。

動作にはPHP5.3.2以上が必要。いくつかのphpフラグやコンパイルフラグも必要。インストーラを使えば警告で知らせてくれる。

compser自体のインストール

詳しくは省略。
https://getcomposer.org/installerをダウンロードしてphpで実行するか(Windows以外)。https://getcomposer.org/Composer-Setup.exeを実行してインストール。

composerはcomposer.pharという1つのファイルになっているので、これをプロジェクトに含めてもいいかもしれない。

Windowsでのバッチファイル

以下のバッチファイルをつくって、プロジェクトのルートに置くと便利。

composerの設定はcomposer.jsonに記述する。プロジェクトの依存関係が記述される。プロジェクトのルートディレクトリに置く。

デフォルトではPackagistというレポジトリからrequireで記述されたパッケージをインストールする(installコマンド)。パッケージ名はベンダー名/プロジェクト名になる。上記のバージョン指定は、1.0以上で1.1以下のパッケージを指定している。

パッケージのインストール

php composer.phar install

このコマンドを最初に実行したとき(まだcomposer.lockがない)は、必要なすべてのパッケージをvendor配下にインストールしてcomposer.lockにインストールしたバージョンを記述する。インストール時にcomposer.lockがあればこのファイルに記載されたバージョンをインストールする。このファイルを共有しておけば、開発者間でパッケージのバージョンを一致させられる。

アップデート

php composer.phar update

プラットフォームパッケージ

PHPそのものはcomposerでインストールするものではないが、依存関係は記述したい場合PHPをプラットフォームパッケージまたは仮想パッケージと呼ぶ。show –platformコマンドで一覧を表示できる。

オートロード

ライブラリがautoloadの指定を行っていれば、composerはvendor/autoload.phpを作成する。ユーザはこのファイルをインクルードしてライブラリを使うことができる。

自分自身のコードをautoloadに指定することもできる。

ここではネームスペースとディレクトリのマップをしている。srcディレクトリはプロジェクトのルートでvendorと同じ階層。これでたとえばsrc/Foo.phpはAcme\Fooクラスを含んでいることになる。

autoloadフィールドを追加した場合はvendor/autoload.phpを再構築するためにdump-autoloadコマンドを実行する必要がある。

ライブラリ

上記のautoloadの設定を行うとプロジェクトはほぼパッケージになる。違いは名前があるかどうかでこれはcomposer.jsonのnameプロパティを設定すればいい。

バージョンはVCSから推論するのでcomposer.jsonには記述しない。がVCSを使っていない場合はcomposer.jsonに記述できる。

コマンド

help

ヘルプ。引数にサブコマンドを指定すると、そのコマンドのヘルプ。

init

php composer init

composer.jsonを作成

引数なしまたはlist

ヘルプを表示

install または i

パッケージをインストール

update または u

パッケージをアップデート

search

レポジトリからパッケージを探す。composer.jsonでリポジトリを指定していない限りpackagist(デフォルトのレポジトリ)から探す。

php composer.phar search monolog

show

インストールされているパッケージを表示。*を指定してフィルタできる。パッケージを指定すると詳細を表示。

browse または home

パッケージのウェブサイトをブラウザで表示

php composer.phar browse p3k/picofeed

depends

指定されたパッケージに依存しているパッケージを表示

config

composerの設定情報の設定と表示。設定にはグローバルとローカルがある。ローカルはcomposer.jsonに保存される。レポジトリの設定などがある。

php composer.phar config –list

diagnose

エラー診断。エラーが出たときやってみるといい。

vueでグローバルな関数をつかう

Vueはコンポーネントでページを構成するフレームワークなのでグローバルな関数や変数というのは基本的には使わないと思われる。データのやり取りはpropsやeventで行うが、グローバル関数が欲しい場合もある。

Vueにはmixinという仕組みもあるみたいだが、これはVueコンポーネントにフックするために使うようで、プラグインなどにも影響するようなので、もっと普通のグローバルな関数を定義したい。

public/index.htmlにjavascriptを置いてもいいがここではvueらしくimportを使って行う。

まずはsrc/global.jsを新規に作成して、ここにグローバルな関数や変数を書く。

ここではdtraceをexportしている。

つぎにコンポーネントでこれをインポートして使う。

npm runのnode実行でonelineのjavascriptに引数を渡して実行する

nodeでjavascriptを実行する場合、通常はnodeにファイルを渡してスクリプトを実行するが短いスクリプトの場合はコマンドラインにスクリプトを書くことができる。ちょっとしたスクリプトを書きたい場合はこうすることですべての情報がコマンドラインにしか存在しないのでよりポータブルになる。しかしコマンドラインの制約から文字列を囲むクォートやダブルクォートが書きにくいので、その点は注意する必要がある。Windowsではシングルクォートは通常の文字のように扱われるので、スクリプト全体をダブルクォートで囲い、スクリプト内部での文字列はシングルクォートで囲むようにする。

次にスクリプトに引数を渡したいときはnodeに渡す引数と区別するために、通常は最後に–(2つのハイフン)をつけて、それ以降の引数はスクリプトに渡されるものであることを指示する。

上記のことを組み合わせて、スクリプト内で引数を受け取り、コマンドラインでスクリプトとそれに渡す引数を渡すことができる。これを応用してnpm runに記述しておけば、ちょっとしたコマンドをpackage.jsonに登録することができる。jsonでダブルクォートを扱うときはバックスラッシュでエスケープすればいいので矛盾は生じない。

nodeでのスクリプトへの引数の渡し方

-eでスクリプトをそのまま指定。
–のあとのコマンドライン引数はスクリプトに渡される。

スクリプト内では引数はprocess.argvで受け取る。

npm runに引数を渡す

npm runはそのまま実行するだけのようなので以下のように書く。ダブルクォートはバックスラッシュでエスケープする。

npm runを実行

グループポリシーエラー このコンピュータのグループポリシーオブジェクトを開くことができませんでした。

gpedit.mscを開くと以下のようなエラーが出る。

グループポリシー エラー

グループポリシーの設定ファイルが壊れているとこのエラーがでるようだ。

設定ファイルの初期化

フォルダ C:\Windows\System32\GroupPolicy\Machine をリネームすると次回起動時にまた作られる。C:\Windows\System32\GroupPolicyは隠しファイルになっているので、エクスプローラーで隠し属性ファイルも表示するようにする。

エクスプローラーで隠し属性ファイル表示

C:\Windows\System32\GroupPolicy\Machineをリネーム