従来はプログラムから特定のパスにディレクトリやファイルを追加する際、それらのパーミッションの変更にはPHPのchmod()を使用していました。しかし、最近ドキュメントを読み返してみてLaravelらしいやり方を学んだのでまとめます。
デフォルトの権限
まずはStorageファサードを使用してstorage配下にディレクトリやファイルを追加した場合に、それらのパーミッションがどうなっているのか確認してみましょう。config/filesystems.phpの設定をデフォルトの状態から変更していない前提で話を進めます。tinkerで以下を実行してみてください。
// ディレクトリを作成
> Storage::makeDirectory('memos');
= true
// ファイルを作成
> Storage::put('memos/todo.txt', '今日のTODOリスト...');
= true
ディスクを指定していないのでデフォルトのlocalディスクドライバが選択され、storage/app配下にmemos/todo.txtが追加されたはずです。追加されたディレクトリとファイルのパーミッションを確認してみましょう。
$ ls -la storage/app/ | grep memos drwx------ 3 hikaru staff 96 12 12 22:53 memos $ ls -la storage/app/memos/todo.txt -rw-r--r-- 1 hikaru staff 20 12 12 23:12 storage/app/memos/todo.txt
※ユーザ名及びグループ名は実行環境毎に異なるので仮です。ご自身の環境の値に置き換えて読み進めてください。
上記の実行結果から分かる通りパーミッションは以下の通りになっていました。
- memosディレクトリ(rwx——): ユーザのみフルアクセス可能
- todo.txt(rw-r–r–): 誰でも閲覧可能、書き込みはユーザのみ可能
todo.txt自体は誰でも閲覧可能となっていますが、memosディレクトリ自体の権限がユーザにのみ付与されているので、他のユーザはその配下にアクセスする事ができません。アクセスしようとするとPermission deniedと表示されます。memosディレクトリも誰でも閲覧可能とするにはどうすれば良いでしょうか?
visibilityの設定
Laravelにおいてはパーミンションの事をvisibilityと呼ぶ様です。visibilityの設定値はpublicかprivateの2択に簡略化されており、ローカルであれクラウドであれ同じ操作でアクセス権の設定を行えます。詳しくは公式ドキュメントをご確認ください。visibilityを設定するにはsetVisibility()を使用します。第一引数にvisibilityを設定するターゲットを、第二引数にpublic or privateを指定します。例えば、前項のmemosディレクトリをpublicにするなら、
> Storage::setVisibility('memos', 'public');
= true
権限をチェックしてみましょう。
$ ls -la storage/app/ | grep memos drwxr-xr-x 3 hikaru staff 96 12 12 23:39 memos
誰でも閲覧可能となりましたね。今度は逆にtodo.txtをprivateにしてみましょう。
> Storage::setVisibility('memos/todo.txt', 'private');
= true
権限を確認するとユーザhikaruのみ閲覧可能となっていました。
$ ls -la storage/app/memos/todo.txt -rw------- 1 hikaru staff 25 12 12 23:43 todo.txt
デフォルトの設定ではpublicとprivateを指定した場合のアクセス権についてまとめると以下の通りになっていました。
filesystems.phpで詳細設定
publicやprivateによって設定されるアクセス権をより細かくカスタマイズしたいケースがあるかもしれません。その場合はfilesystems.phpにて指定する事ができます。以下はデフォルトのlocalディスクドライバの設定です。
...
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
'throw' => false,
],
...
これを次のように変更してみます。
...
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
'throw' => false,
'directory_visibility' => 'public',
'visibility' => 'public',
'permissions' => [
'file' => [
'public' => 0664,
'private' => 0600,
],
'dir' => [
'public' => 0775,
'private' => 0700,
],
]
],
...
directory_visibilityとvisibilityはディレクトリやファイルを追加した際のデフォルトのvisibilityを指定しています。前項ではディレクトリ追加時のvisibilityがprivateになっていましたが、publicに変更しました。そして、permissions内ではファイルとディレクトリにおけるpublicとprivateを指定した際に割り当てるパーミッションを8進数で指定します。上記ではpublic時にグループユーザにも書き込み権限を付与しました。設定通りにアクセス権が付与されるか、再度tinkerでチェックしてみましょう。
> Storage::makeDirectory('memos2');
= true
権限を確認すると
$ ls -la storage/app/ | grep memos2 drwxr-xr-x 2 hikaru staff 64 12 21 20:27 memos2
あれれ、グループユーザに書き込み権限が付与されていません。何故でしょう?しばらくソースコードと睨めっこしてやっと気づきました。犯人はumaskです。Storage::makeDirectory()は内部的にPHPのmkdir()を使用しているのですが、そちらのドキュメントにはこう書かれています。
また permissions は、 現在設定されている umask の影響も受けます。 umask を変更するには umask() を使用します。
umaskとはUnix系OSにおいてディレクトリやファイルを追加した際のアクセス権を指定するコマンドです。例えば、私の環境、macOSではデフォルトでは標準的な022が指定されており、基本パーミッションである0777から022を引いた0755がデフォルトのパーミッションとなります。ドキュメントに書かれている通り、umask()で制限を解除してからディレクトリ作成コマンドを実行してみましょう。
> umask(000);
= 18
> Storage::makeDirectory('memos3');
= true
> Storage::put('memos3/todo.txt', '今日のTODOリスト...');
= true
パーミッションを確認すると
$ ls -la storage/app/ | grep memos3 drwxrwxr-x 3 hikaru staff 96 12 21 20:48 memos3 $ ls -la storage/app/memos3/todo.txt -rw-rw-r-- 1 hikaru staff 13 12 21 20:48 todo.txt
config/filesystems.phpで指定した通り、ディレクトリもファイルもグループユーザにも書き込み権限が付与されました。
メルマガ購読の申し込みはこちらから。
