4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Laravelのキャッシュファイルのパーミッション設定

Posted at

以前以下の記事でキャッシュファイルのパーミッション設定を結局「umask」を利用しましたが、もっと良い方法がないか調べてみました。
Laravelのファイルパーミッションの問題

他は?

ファイル・ディレクトリの作成がumaskの影響を受けることなら、ログの設定ファイルでパーミッションはどうやるの?調べてみました。たどり着いたのが以下のメソッドです。

Monolog\Handler\StreamHandler.php

   /**
     * {@inheritdoc}
     */
    protected function write(array $record): void
    {
        if (!is_resource($this->stream)) {
            if (null === $this->url || '' === $this->url) {
                throw new \LogicException('Missing stream url, the stream can not be opened. This may be caused by a premature call to close().');
            }
            $this->createDir();
            $this->errorMessage = null;
            set_error_handler([$this, 'customErrorHandler']);
            $this->stream = fopen($this->url, 'a');
            if ($this->filePermission !== null) {
                @chmod($this->url, $this->filePermission);
            }
            restore_error_handler();
            if (!is_resource($this->stream)) {
                $this->stream = null;

                throw new \UnexpectedValueException(sprintf('The stream or file "%s" could not be opened: '.$this->errorMessage, $this->url));
            }
        }

        if ($this->useLocking) {
            // ignoring errors here, there's not much we can do about them
            flock($this->stream, LOCK_EX);
        }

        $this->streamWrite($this->stream, $record);

        if ($this->useLocking) {
            flock($this->stream, LOCK_UN);
        }
    }

:frowning2:結局chmodか〜〜〜。そうなら俺も作るよ。

カスタムキャッシュドライバを作成

設定ファイル

先ず、設定ファイルを追記して置きましょう!permissionsを追加しました。

config/cache.php
        'file' => [
            'driver' => 'local',
            'path' => storage_path('framework/cache/data'),
            'permissions' => [
                'dir' => 0775,
                'file' => 0664,
            ],
        ],

ここのdriverも「file」→「local」に変えます。

ストア作成

そのあと、ドライバー用のストアを作成します。

pp\Extensions\CacheLocalFileStore.php
<?php
namespace App\Extensions;

use Illuminate\Cache\FileStore;
use Illuminate\Filesystem\Filesystem;
use League\Flysystem\Cached\CachedAdapter;

class CacheLocalFileStore extends FileStore
{

    /**
     * The file cache permissions.
     *
     * @var array
     */
    protected $permissions;

    /**
     * Create a new file cache store instance.
     *
     * @param Filesystem $files
     * @param $config
     */
    public function __construct(Filesystem $files, $config)
    {
        $this->files = $files;
        $this->directory = $config['path'];
        $this->permissions = $config['permissions'];
    }

    /**
     * Store an item in the cache for a given number of seconds.
     *
     * @param  string  $key
     * @param  mixed   $value
     * @param  int  $seconds
     * @return bool
     */
    public function put($key, $value, $seconds)
    {
        $this->ensureCacheDirectoryExists($path = $this->path($key));

        $result = $this->files->put(
            $path, $this->expiration($seconds).serialize($value), true
        );
        @chmod($path, $this->permissions['file']);

        return $result !== false && $result > 0;
    }

    /**
     * Create the file cache directory if necessary.
     *
     * @param  string  $path
     * @return void
     */
    protected function ensureCacheDirectoryExists($path)
    {
        $concatPath = $this->directory;
        $dir = trim(str_replace($concatPath, '', dirname($path)), '/');
        $dirNames = explode('/', $dir);
        foreach ($dirNames as $direName) {
            $concatPath .= '/'. $direName;
            if (! $this->files->exists($concatPath)) {
                $this->files->makeDirectory($concatPath, 0777, true, true);
                @chmod($concatPath, $this->permissions['dir']);
            }
        }
    }
}

既存のFileStoreを継承して使いました。ensureCacheDirectoryExists中でforeach分を使った理由は作成するpathが「/8/50」ようなディレクトリ構造なのでchmodが親の断層も出来る用法が思い浮かばなかったからです。

プロバイダー作成

登録するためにプロバイダーを作成します。

<?php

namespace App\Providers;

use App\Extensions\CacheLocalFileStore;
use App\Extensions\MongoStore;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\ServiceProvider;

class CacheServiceProvider extends ServiceProvider
{
    /**
     * コンテナ結合の登録
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * 全アプリケーションサービスの初期起動
     *
     * @return void
     */
    public function boot()
    {
        Cache::extend('local', function ($app) {
            return Cache::repository(new CacheLocalFileStore($app['files'], config('cache.stores.file')));
        });
    }
}

設定ファイルのドライバー「local」で登録します。上記のプロバイダーをconfig/app.phpに登録します。

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?