tohokuaikiのチラシの裏

技術的ネタとか。

axiosでParallel実行する時のエラーハンドリングがよくわからない

axiosで並列して全部終わったら…というやつ。

axios.all([
    axios.get('/api/user/'),
    axios.get('/api/image')
]).then(([res1, res2]) => {
    this.user = res1.data;
    this.image = res2.data;
}).catch(err =>{
    console.log(err);
});

ってやると、2つgetしたうちの最初のエラーしかcatchしてくれない。

個々のエラーを見たかったら

axios.all([
    axios.get('/api/user/').catch(err => { /*  error処理 */ }),
    axios.get('/api/image').catch(err => { /*  error処理 */ })
]).then(([res1, res2]) => {
    this.user = res1.data;
    this.image = res2.data;
});

という感じに個々のaxiosにcatchを付ける。でも、これだとthenにいっちゃう。

それが嫌なら

axios.all([
    axios.get('/api/user/').catch(err => { /*  error処理 */ throw(err); }),
    axios.get('/api/image').catch(err => { /*  error処理 */  throw(err);})
]).then(([res1, res2]) => {
    this.user = res1.data;
    this.image = res2.data;
}).catch(err =>{
    console.log(err);
});

ってやると、catchできるけどそれって最初のとあんま変わんないっていう…。

LaravelでEthnaのフォームフィルターみたいなやつ

あれな。Inputの時にPOST値を自動的に全角から半角にしてくれたりするやつ。あれ、すげー便利なんだけど、Laravel本体にはないらしい。

waavi/sanitizerをインストール

composerにあるので https://packagist.org/packages/waavi/sanitizer

$ composer require waavi/sanitizer

でインストール

Filterクラスを作成

App/Http/Requests/Filters ディレクションを作成してクラスを登録。applyメソッドを作る。

<?php
namespace App\Http\Requests\Filters;

use Waavi\Sanitizer\Contracts\Filter;

/**
 * Class Zentohan
 */
class Zentohan implements Filter
{
    /**
     * @param mixed $value
     * @param array $options
     * @return mixed|string|string[]
     */
    public function apply($value, $options = [])
    {
        return mb_convert_kana($value, 'KVa', 'UTF-8');
    }
}

Requestクラスで使う

Validator前にFilterしてくれる。

<?php
namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Waavi\Sanitizer\Laravel\SanitizesInput;
use App\Http\Requests\Filters\Zentohan;

class UserRequest extends FormRequest
{
    use SanitizesInput;

    /**
     * @return array filters before sanitized
     */
    public function filters()
    {
        return [
            'name'  => 'zentohan',
            'email' => ['zentohan', 'lowercase'],
        ];
    }

    public function customFilters()
    {
        return [
            'zentohan' => Zentohan::class
            ];
    }
}

うーん、便利。

filtersは配列で複数、あるいは|でつないで複数いける。

Vuejsの共通関数の設置

utility.jsとかにして全体で使いたい場合ありますよね。methodsに突っ込みます。

mixin用のファイル作成

my_vue_mixin.js

export default{
  methods: {
    aaa(){
        console.log('123');
    }
  }
}

Vueに仕込む

app.js

import Vue from 'vue';
import myVueMixin from './my_vue_mixin';
window.Vue = require('vue');
Vue.mixin(myVueMixin);

const app = new Vue({
    el: '#app',
});

この2行ね

import myVueMixin from './my_vue_mixin';
Vue.mixin(myVueMixin);

Vueファイルで使う

普通にmethodsのメンバーとして使える。 Foo.vueで

    methods: {
        confirm(){
            this.aaa();
        }

とか。

traitのメソッドをoverwriteしたんだけど、そのoverwriteされたメソッドを呼びたい場合

参考にさせていただきました

qiita.com ありがとうございました。

試行錯誤してみる

まずは基本となるtraitのAと親クラスBaseを定義

<?php
trait A
{
    public function say()
    {
        echo "I am A\n";
    }
}

class Base
{
    public function say()
    {
        echo "I am Base\n";
    }
}

で、Baseを継承しAをtraitしたクラスを作る

<?php
class Sayer extends Base
{
    use A ;

    public function say()
    {
        echo "I am Sayer\n";
    }
}

このSayerクラスのsay()メソッドからtraitのsay()メソッドをコールしたいわけです。

単純にparentを使った

<?php
class Sayer extends Base
{
    use A ;

    public function say()
    {
        echo "I am Sayer\n";
        parent::say();
        $this->sayA();
    }
}

(new Sayer())->say();

結果

I am Sayer
I am Base

そりゃー、そーですよね。parentは継承元のクラスなんで…

単純に$this->を使った

<?php
class Sayer extends Base
{
    use A;
    
    public function say()
    {
        echo "I am Sayer\n";
        $this->say();
    }
}
(new Sayer())->say();

結果

I am Sayer
I am Sayer
...(略:252回繰り返す)
I am Sayer
I am Sayer
PHP Fatal error:  Uncaught Error: Maximum function nesting level of '256' reached, aborting! in /home/vagrant/work/trait_parent.php:22

メソッドループして怒られた。…当たり前だな。

解決方法

use ... as を使う

<?php
class Sayer extends Base
{
    use A {
        A::say as sayA;
    }
    
    public function say()
    {
        echo "I am Sayer\n";
        $this->sayA();
    }
}
(new Sayer())->say();

結果

I am Sayer
I am A

無事traitのメソッドが呼び出せた。

LaravelのRequest->rules()がどの条件で掛かるのか?

が良くわからなかったので追ってみた。

ざっとBreakpointを設置して

<?php
class FormRequestServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    {
        $this->app->afterResolving(ValidatesWhenResolved::class, function ($resolved) {
            $resolved->validateResolved();
        });

の $resolved->validateResolved();で登録しているみたい。GETメソッドの場合は個々を実行せず、PATCHメソッドの時はこの部分を実行していた。

$this->app->afterResolving() の実装

このメソッドを追ってみるとsrc/Illuminate/Container/Container.php

<?php
class Container implements ArrayAccess, ContainerContract
{
    public function afterResolving($abstract, Closure $callback = null)
    {
        if (is_string($abstract)) {
            $abstract = $this->getAlias($abstract);
        }

        if ($abstract instanceof Closure && is_null($callback)) {
            $this->globalAfterResolvingCallbacks[] = $abstract;
        } else {
            $this->afterResolvingCallbacks[$abstract][] = $callback;
        }
    }

だったんだけど、こっからよくわかんなかった…