20200116のlaravelに関する記事は6件です。

laravel のログイン機能name へ変更

以下の手順で上手く行きました。

1

【2014_10_12_000000_create_users_table.php】
$table->string('name')->unique();

2
【LoginController.php】
public function username()

{

return 'name';

}

3
【login.blade.php】

Name
<div class="col-md-6">                                      
    <input id="name" type="name" class="form-control" name="name" value="{{ old('name') }}" required autofocus                                      
    @if ($errors->has('name'))  

        <span class="help-block">   

            <strong>{{ $errors->first('name') }}</strong>   

        </span> 

    @endif  

</div>

拍手!

分かる人は分かる

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

laravel のログイン機能をnameでログインへ変更する機能

以下の手順で上手く行きました。

1

【2014_10_12_000000_create_users_table.php】
$table->string('name')->unique();

2
【LoginController.php】
public function username()

{

return 'name';
}

3
【login.blade.php】

Name
<div class="col-md-6">                                      
    <input id="name" type="name" class="form-control" name="name" value="{{ old('name') }}" required autofocus                                      
    @if ($errors->has('name'))  

        <span class="help-block">   

            <strong>{{ $errors->first('name') }}</strong>   

        </span> 

    @endif  

</div>

動作確認OK

拍手!

以上

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel で S3 にファイルを上げるタイミングで ACL を設定する

はじめに

Laravel のファイルストレージでは AWS の S3 を指定して保存することができます。
S3を指定する方法は公式ドキュメントを参照してもらうとして、保存は下記のように store メソッドを利用します。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class UserAvatarController extends Controller
{
    public function update(Request $request)
    {
        $path = $request->file('avatar')->store('avatars');

        return $path;
    }
}

重要なポイント

保存をするとき、上記の例では Storage ファサードを使っていません。
もちろんファサードを使って保存することも可能で、

$path = Storage::putFile('avatars', $request->file('avatar'));

このように公式ドキュメントには書いてあります。
で、やりたいのはドキュメントに ファイル視認性 と書かれていますが、

$visibility = Storage::getVisibility('file.jpg');
Storage::setVisibility('file.jpg', 'public')

ファイルが既に保存されている場合、上記の設定でズバッと設定をしてしまいたい。デフォルトで private になっているところを公開の public にしたい場合はどうしたら良いのか、です。
つまり store の段階で最初からできてくれよってことですね。

で、例の如く...

ないんですよね、ドキュメント上に正解が。

ヒントはあって、第二引数で他のディスク(この例だとローカルストレージを利用中)に保存したい場合などは下記のように書かれています。

$path = $request->file('avatar')->store(
    'avatars/'.$request->user()->id, 's3'
);

となると、もしかすると第3や第4の引数でなにかあるかもしれない。
ということでコアを追いかけることになります。

この場合の $requestIlluminate\Http\Requestです。
追跡していくと、

Illuminate\Http\Request
 ↓
Illuminate\Http\Concerns\InteractsWithInput
 ↓
Illuminate\Http\UploadedFile

と、辿れます。どうやって辿るかは正直、勘です。
エスパー並の感度で遡った結果、

store メソッドを見つけました。

Illuminate\Http\UploadedFile
    public function store($path, $options = [])
    {
        return $this->storeAs($path, $this->hashName(), $this->parseOptions($options));
    }

    public function storeAs($path, $name, $options = [])
    {
        $options = $this->parseOptions($options);

        $disk = Arr::pull($options, 'disk');

        return Container::getInstance()->make(FilesystemFactory::class)->disk($disk)->putFileAs(
            $path, $this, $name, $options
        );
    }

    protected function parseOptions($options)
    {
        if (is_string($options)) {
            $options = ['disk' => $options];
        }

        return $options;
    }

parseOptions を見ると、文字列を与えると自動的に配列で disk の key/val 型になるように整形して storeAs に渡しているのがみて取れますね。

で、最終的には putFileAs で保存しているのが分かるわけですが、FilesystemFactory でいよいよ Factory の文字が見えてまいりました。

これの実体は Illuminate\Contracts\Filesystem\Factory です。
こいつは interface なので、基底にもつクラスがいるはずで、それは何かというと Illuminate\Filesystem\FilesystemAdapter になります。
このなかに putFileAs のメソッドも登場してくるわけですが、

Illuminate\Filesystem\FilesystemAdapter
    public function putFileAs($path, $file, $name, $options = [])
    {
        $stream = fopen($file->getRealPath(), 'r');

        $result = $this->put(
            $path = trim($path.'/'.$name, '/'), $stream, $options
        );

        if (is_resource($stream)) {
            fclose($stream);
        }

        return $result ? $path : false;
    }

    public function put($path, $contents, $options = [])
    {
        $options = is_string($options)
                     ? ['visibility' => $options]
                     : (array) $options;

        if ($contents instanceof File ||
            $contents instanceof UploadedFile) {
            return $this->putFile($path, $contents, $options);
        }

        return is_resource($contents)
                ? $this->driver->putStream($path, $contents, $options)
                : $this->driver->put($path, $contents, $options);
    }

putFileAs は put への橋渡しをしていますね。
で、put のところで visibility が登場しており、この辺りがかなりそれっぽい。
で、最終的に $this->driver で保存してそうだということが return からわかります。

ここで使われている drive は当然ながら s3 のはずなので、driver を探します。
このファイルの先頭付近で

use League\Flysystem\AwsS3v3\AwsS3Adapter;

と書かれているので、この辺りがとても怪しい。
本体は Laravel のコアから外れて /vendor/league の下までいくとようやく出てきます。
このクラスを眺めていると、ようやく AWS SDK のオプションが出てきました。

この辺は AWS SDK for PHP のドキュメントを見ると、ファイルアップロード関数の putObject と一致しているのがわかります。

League\Flysystem\AwsS3v3\AwsS3Adapter
    protected static $metaOptions = [
        'ACL',
        'CacheControl',
        'ContentDisposition',
        'ContentEncoding',
        'ContentLength',
        'ContentType',
        'Expires',
        'GrantFullControl',
        'GrantRead',
        'GrantReadACP',
        'GrantWriteACP',
        'Metadata',
        'RequestPayer',
        'SSECustomerAlgorithm',
        'SSECustomerKey',
        'SSECustomerKeyMD5',
        'SSEKMSKeyId',
        'ServerSideEncryption',
        'StorageClass',
        'Tagging',
        'WebsiteRedirectLocation',
    ];

この場合、ACL が今回の対象になるポイントで、Laravelがファイル視認性とか言ってますが、最終的に渡したいのは
private|public-read|public-read-write|authenticated-read|aws-exec-read|bucket-owner-read|bucket-owner-full-control のどれかをこのアダプターの ACL というキーに突っ込みたいわけです。
というわけで、それっぽい関数をみてみると、

League\Flysystem\AwsS3v3\AwsS3Adapter
    protected function upload($path, $body, Config $config)
    {
        $key = $this->applyPathPrefix($path);
        $options = $this->getOptionsFromConfig($config);
        $acl = array_key_exists('ACL', $options) ? $options['ACL'] : 'private';

        if (!$this->isOnlyDir($path)) {
            if ( ! isset($options['ContentType'])) {
                $options['ContentType'] = Util::guessMimeType($path, $body);
            }

            if ( ! isset($options['ContentLength'])) {
                $options['ContentLength'] = is_resource($body) ? Util::getStreamSize($body) : Util::contentSize($body);
            }

            if ($options['ContentLength'] === null) {
                unset($options['ContentLength']);
            }
        }

        try {
            $this->s3Client->upload($this->bucket, $key, $body, $acl, ['params' => $options]);
        } catch (S3MultipartUploadException $multipartUploadException) {
            return false;
        }

        return $this->normalizeResponse($options, $path);
    }

upload のメソッドに $acl = array_key_exists('ACL', $options) ? $options['ACL'] : 'private';が出てきますね。
ACLという配列キーが出てこなければ private にせよ、と書いてあるので逆に ACL のキーで渡せば良いことがわかります。

というわけで解決方法

長くなりましたが $options に配列で渡していけば良いことがわかりました。

$path = $request->file('avatar')->store('avatars', ['disk' => 's3', 'ACL' => 'public-read']);

ということで、このように第二引数に配列で渡しましょう。その際に disk のキーを渡すのもお忘れなく。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravelで現在日時を指定できるプラグインを作った

Carbon を正しく使っているプロジェクトに限るけど、現在日時を指定してアプリケーションを動かせるプラグインを作った。
スタンドアロンのサーバ php artisan serve を1999年7月31日として実行したい場合は以下のように環境変数で日付を指定できる。

$ LARAVEL_NOW=1999-7-31 php artisan serve

Carbon がパースできる書式なら自由に指定できるので、日次バッチを昨日の日付で動かすこともできる。

# 昨日の日付として動作確認できる!
$ LARAVEL_NOW=yesterday php artisan app:daily-job

プラグインの中で Carbon::setTestNow() でセットしているだけ。動作確認するときにソースコードを変更せずに外部から指定できるので少し便利になった。

https://github.com/grohiro/laravel-now

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Laravel】リレーション先で検索する方法

Laravelでリレーション先で検索することがあったため備忘録。

例えば下記のようなモデルがあったとします。

User.php
class User extends Model
{
    public function project()
    {
        return $this->belongsTo('App\Project');
    }
}
Project.php
class Project extends Model
{
    public function organization()
    {
        return $this->belongsTo('App\Organization');
    }
}

※主キーはidとします。

リレーション先で検索

Userからリレーション先であるProjectのorganization_idで絞り込みたいとします。

  • whereHasを使用する場合
UserController.php
$Users = User::whereHas('project', function ($query) use ($request) {
    $query->where('organization_id', $request->organization_id);
})->get();

  • whereHasを使用しない場合
UserController.php
$Users = User::whereIn('project_id', function ($query) use ($request) {
    $query->from('projects')
        ->select('id')
        ->where('organization_id', $request->organization_id);
})->get();

リレーション先のリレーションで検索

Userからリレーション先であるProjectのリレーション先のOrganizationのnameで絞り込みたいとします。

  • whereHasを使用する場合
UserController.php
$Users = User::whereHas('project', function ($query) use ($request) {
    $query->whereHas('organization',  function ($query) use ($request) {
        $query->where('name', $request->organization_name);
    }
})->get();

  • whereHasを使用しない場合
UserController.php
$Users = User::whereIn('project_id', function ($query) use ($request) {
    $query->from('projects')
        ->select('id')
        ->whereIn('organization_id', function ($query) use ($request) {
            $query->from('organizations')
                ->select('id')
                ->where('name', $request->organization_name);
        });
})->get();

他により良い方法などありましたらご教示いただけますと幸いです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

material-ui-dropzoneでapplication/octet-streamのMime typeが登録できなかった話

内容

ずっと出来ると思っていたcadファイルをアップロードしようと思ってやってみたら、拒否されてしまったのでそれを解決したお話

結論

acceptedFilesのjwwみたいな感じで拡張子を指定してあげればうまく出来たよ

<DropzoneDialog
    open={open}
    onSave={handleSave.bind(this)}
    dialogTitle={"ファイルをアップロードする"}
    acceptedFiles={['image/*', 'application/*, .jww , .dwg , .dxf , .jwc , .p21']}
    dropzoneText={"アップロードしたいファイルをドラッグアンドドロップするかクリックして選択ください"}
    cancelButtonText={"アップロードをやめる"}
    submitButtonText={"アップロードする"}
    onDrop={handleCheck.bind(this)}
    showPreviews={true}
    maxFileSize={5242880}
    onClose={handleClose}
            />
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む