nanisore oishisou

Webエンジニアあるまさんのゆるふわ奮闘記。

git研修用スライド&Web API勉強会スライド

新卒が入って来た時に行ったgit研修用のスライドをSpeaker Deckで全世界に公開したので
Gitをこれから教えようと思ってるor初心からやり直したいという人がいたら参考にしてみてください。

あと8月のPG会で
初心者向けにWeb APIを超分かりやすく初歩の初歩から説明した際のスライドもアップしました。

話すことをすぐ忘れてしまうタイプなので
話すことをスライドに全部書いているため、スライドというか、もはや本w

あと時間管理ができなくて話しすぎるとよく言われてしまうので
これ以上は話さないぞという戒めでもあるw

git研修用は自分でも時々見返してしまうくらい頭がすっきりします。

ぜひ、ご一読ください!

VuetifyのDate Pickerを日本語化したら"日"ってついてくる、やだキモい

長い前置き(飛ばし読み推奨)

最近、フロント側を完全に脱jQueryして、Vue.js + Vuex + VueRouter + Vuetifyで開発を進めている。

これまでもVue.js + Vuex この2つは使っていたわけなんだけど
bootstrapベースであるAdminLTEと組み合わせることに限界を感じていて、
それぞれの開発者がVueライブラリを探して入れてみたり、
自作してみたりみたいなことを、それぞれの案件で繰り返していたわけだ。

心の声(もう、こんなお飾りのjQuery依存のUIフレームワークなんて実際は足枷じゃねーか。確かにデザインは綺麗なんだけど。。)

そこで出会ったのがVuetify。

少し使い込んでみた感じ、グリッドレイアウトにflexboxを採用しているので
レイアウトに苦戦することもあるけど、それだって新しいbootstrap4も同じだし
もはや、これが時代の流れなのかもしれないと思い、思い切って使ってみることにした。

エンジニアは、手を動かさなくなったら
時代に置いていかれて、すぐに周りについていけなくなる。
これは私がしばらくエンジニア業から離れたときに、痛いほど感じたことだ。
久しぶりに会ったエンジニアの知人の言っていることが分からなかった。

別に毎日懸命に手を動かして勉強する必要はない。
ただ、ニュースを毎日見るように、
ご飯を毎日食べるように、
時代の流れだけは把握しておかないといけない。
エンジニアとは、そういう生き物だ。そう感じた。

話が脱線しすぎた。元に戻そう。

Vuetifyを採用してみて最初は、
使い慣れないこととドキュメントの多さにグロッキーになっていたが
いくつか実装してみると、だいぶ手に馴染んできた。
アニメーションが綺麗でデザインも綺麗。
動きもサクサク。

モックを作成しPMに見せたら、いたく感動してくれた。

よかった。間違ってない。何となくそう思えた。
いいデザインは、人の心を魅了する。
いいデザインは、高品質を演出する。
いいデザインは、そのプロダクトを作った人間の情熱を伝えることができる。

要するに、
Vuetifyっていいね!

本題

Vuetifyのコンポーネントは、かなりいろいろ気が利いている。
色を変えるのも、デザインをカスタマイズするのも設定一つでできてしまう。

しかし、日本語化したDate Pickerだけは(あとTime Pickerもなんだけど。。)
ちょっとキモい部分がある。

f:id:arm4:20180817154130p:plain
日本語化したDate Picker

え?何この"日"ってやつ。
しつこいwwwwwwwww

消したかったけどoptionにday-formatはあるけどdate-formatがない。

いろいろ検索してみたらこんなcodepenを発見。

codepen.io

あれ?day-formatで指定すればいいっぽい?

ためしにday-formatに以下を設定してみたところ、
しつこい"日"は消えてくれました。

    <v-date-picker
      v-model="picker"
      :landscape="landscape"
      :reactive="reactive"
      locale="jp-ja"
      :day-format="date => new Date(date).getDate()"
    ></v-date-picker>

f:id:arm4:20180817154555p:plain
日よ、消え去れ!

めでたし、めでたし。

Homebrew を updateしたら、php -vでdyld: Library not loaded: /usr/local/opt/icu4c/lib/libicui18n.61.dylibと言ってくる

タイトル長っw

個人的に使ってみたことのあったyarnなんですが、本案件で使おうよとなると
yarnというものがありましてから始まり、こういう面で嬉しいんですねと続き、
それをPMに承認してもらって、じゃあそれをメンバーに周知して、と
いろいろ根回しが必要で面倒なので、npmのままやってたんですね。

あと別にnpmでも困らないので、正直。

しかし、新しいプロジェクトでは使いたいなーと思っていた矢先に
「駅前に新しく出来たプロジェクトがあるんだけど、俺たちも一緒にyarnにしませんか?」と
コミュ強なPMからお誘いされたんで、そうしてあげることにしました。
ライブラリのインストール速くてラクラクだねー。
バージョンもロックされて安心だしー。
あと、別にこれ途中からyarnにしても何の問題もないなー。yarn addすればyarn.lockも勝手に出来るし。(←知らなかったw)
yarn最高やーん。布教しよw

で、これからが本題なんだけど、
先日High Sierraクリーンインストールした関係で
yarnをinstallしなくちゃならなかったのでhomebrew updateしてhomebrewでインストールしたわけです。

したら、nginxさんから"502 Bad Gateway"とか怒られるようになって、
なんでやろかーといろいろと探っていたところ、php がエラってることが分かりました。 PHPを複数バージョン入れてるからだと思うんだよね。。。

またこれかよ。もうphpenvみたいなの使ったほうがいいかも。

それを辛うじて修正できたので、ここで手順を晒しておきます。

ちょっとワーニングまで直せてないんだけど。
直したので後述するぜ。

PHPを復活させるまでのベル子の軌跡

homebrewのupdateを実施したところ、phpがエラーを吐くようになった。

具体的には以下のエラー。

[-] php -v
dyld: Library not loaded: /usr/local/opt/icu4c/lib/libicui18n.61.dylib
  Referenced from: /usr/local/bin/php
  Reason: image not found
[1]    2282 abort      php -v

同じことで困っている人を発見。

kimikimi714.hatenablog.com

phpの再インストールが必要と書いてあるが、参考のstackoverflowにはsymlink方式とbrew unlink libpng方式もあるので まずはそちらから試すほうをおすすめする。理由は後述。

この人が参照しているstackoverflowはこちら

stackoverflow.com

ということで私は思い切ってphpを再インストールしてみた。 再インストールはオススメしない。理由は後述。

brew reinstall php72

そして、php -vをすると

[~] php -v
PHP Warning:  PHP Startup: Unable to load dynamic library 'memcached.so' (tried: /usr/local/Cellar/php/7.2.6/pecl/20170718/memcached.so (dlopen(/usr/local/Cellar/php/7.2.6/pecl/20170718/memcached.so, 9): image not found), /usr/local/Cellar/php/7.2.6/pecl/20170718/memcached.so.so (dlopen(/usr/local/Cellar/php/7.2.6/pecl/20170718/memcached.so.so, 9): image not found)) in Unknown on line 0

Warning: PHP Startup: Unable to load dynamic library 'memcached.so' (tried: /usr/local/Cellar/php/7.2.6/pecl/20170718/memcached.so (dlopen(/usr/local/Cellar/php/7.2.6/pecl/20170718/memcached.so, 9): image not found), /usr/local/Cellar/php/7.2.6/pecl/20170718/memcached.so.so (dlopen(/usr/local/Cellar/php/7.2.6/pecl/20170718/memcached.so.so, 9): image not found)) in Unknown on line 0
PHP Warning:  PHP Startup: Unable to load dynamic library 'imagick.so' (tried: /usr/local/Cellar/php/7.2.6/pecl/20170718/imagick.so (dlopen(/usr/local/Cellar/php/7.2.6/pecl/20170718/imagick.so, 9): image not found), /usr/local/Cellar/php/7.2.6/pecl/20170718/imagick.so.so (dlopen(/usr/local/Cellar/php/7.2.6/pecl/20170718/imagick.so.so, 9): image not found)) in Unknown on line 0

Warning: PHP Startup: Unable to load dynamic library 'imagick.so' (tried: /usr/local/Cellar/php/7.2.6/pecl/20170718/imagick.so (dlopen(/usr/local/Cellar/php/7.2.6/pecl/20170718/imagick.so, 9): image not found), /usr/local/Cellar/php/7.2.6/pecl/20170718/imagick.so.so (dlopen(/usr/local/Cellar/php/7.2.6/pecl/20170718/imagick.so.so, 9): image not found)) in Unknown on line 0
PHP 7.2.7 (cli) (built: Jun 22 2018 06:27:50) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.2.7, Copyright (c) 1999-2018, by Zend Technologies

いっぱいエラーが出た。

探してみると/usr/local/Cellar/php/7.2.6ではなく/usr/local/lib/php/pecl/20170718配下にある。

[~] sudo find / -name imagick.so
/usr/local/lib/php/pecl/20170718/imagick.so

php.iniを書き換える

vi /usr/local/etc/php/7.2/php.ini
extension_dir = "/usr/local/lib/php/pecl/20170718"
;extension_dir = "/usr/local/Cellar/php/7.2.6/pecl/20170718"

php -vしてみるとまだなんかエラーを吐いているが、一応phpは動くようになった。

[~] php -v
PHP Warning:  Version warning: Imagick was compiled against Image Magick version 1799 but version 1800 is loaded. Imagick will run but may behave surprisingly in Unknown on line 0

Warning: Version warning: Imagick was compiled against Image Magick version 1799 but version 1800 is loaded. Imagick will run but may behave surprisingly in Unknown on line 0
PHP 7.2.7 (cli) (built: Jun 22 2018 06:27:50) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.2.7, Copyright (c) 1999-2018, by Zend Technologies

※ 7/13追記

Imagickを入れ直す

[~] pecl uninstall imagick
[~] pecl install imagick

php -vをして以下のようなエラーが出たら、php.iniにモジュールロードが二重で書かれているので、
一行削除する。

[-] php -v
PHP Warning:  Module 'imagick' already loaded in Unknown on line 0

Warning: Module 'imagick' already loaded in Unknown on line 0
PHP 7.2.7 (cli) (built: Jun 22 2018 06:27:50) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.2.7, Copyright (c) 1999-2018, by Zend Technologies

phpの再起動を忘れずに。

sudo brew services restart php

こんな感じで直るは直るけど気持ち悪いワーニングが出るので、再インストールは最後の手段にしたほうが良さげ。
あとマイナーバージョンが変わってまうし。

v-modelをちゃんと理解し、Vue-select+Vuexで実装する方法、そして好みの引数を渡す方法

あなたは覚えているだろうか。この記事を。

arm4.hatenablog.com

そう。Vuexを導入するとv-modelは使えなくなる。

これは、v-modelではstoreのstateを直接書き換えに行ってしまうためだ。
そのため、上記のようにして自前でstateの値と同期が取れるように書いてやる必要性がある。

ライブラリを導入しようと思うと、だいたいサンプルのコードにはv-modelが登場してくるので
Vuex初心者は困惑してしまう。

これも、上記のv-modelとは要するに何をしているのかということを理解することで ライブラリのサンプルのコードを自前で書き直すことができるようになる。

v-modelとはつまり何か

まずはこちらのv-modelについての公式の解説を見てもらいたい。

jp.vuejs.org

<input v-model="searchText">

イコール

<input
  v-bind:value="searchText"
  v-on:input="searchText = $event.target.value"
>

この原理を利用してVuexのstoreのステートをセットするようにしているのが、
私が前に書いた記事の手法である。

それからライブラリに登場する際のv-modelを理解するのに重要なのが、以下の部分。

<custom-input
  v-bind:value="searchText"
  v-on:input="searchText = $event"
></custom-input>
Vue.component('custom-input', {
  props: ['value'],
  template: `
    <input
      v-bind:value="value"
      v-on:input="$emit('input', $event.target.value)"
    >
  `
})

要するにカスタムコンポーネントを使っている場合の挙動はこちらになる。

ここでたぶんみんな思うことは一つだと思う。

searchTextに代入している$eventとは一体何ですか?

jp.vuejs.org

コンポーネントでイベントをリッスンすると、送出されたイベントの値に $event でアクセスできます:

要するに子コンポーネントでinputというカスタムイベントを発行し、
そこで本当のネイティブイベントのvalueを親に渡しているということだ。

Vue-selectはカスタムコンポーネントで実現されているので、
この挙動を理解することで自分が意図したように実装することができる。

Vue-selectって何?

sagalbot.github.io

要するにVue版のSelect2だ。

Vue-select+Vuexの実装方法

Vuexを使っている際の実装方法は実は公式ドキュメントに記載がある。

Vuex · vue-select

このような実装だと、毎度毎度setActivePersonのようなメソッドを書かなくてはいけなくなるので
できれば私が書いた記事のようにkey_nameを渡したら勝手にsetしてくれるような汎用的なメソッドを通したいところだ。

そのためには、key_nameを渡すようにしたいが、
引数を渡すとvalueが渡されてこない。

ここにkey_nameを渡すには、仕組みが分かっていないと渡せない。

ここでさっきの知識が生きてくる。

Vue-selectは、選択された値が変わるとon-changeというプロパティに設定したcallback関数が実行される仕組みになっている。

github.com

デフォルトでは以下が設定されている。

      onChange: {
        type: Function,
        default: function (val) {
          this.$emit('input', val)
        }
      },

自前のinputカスタムイベントを発火することで、v-modelを使ってデータが同期されるようにしているようだ。

公式サイトに書いてあったカスタムコンポーネントの作り方と同じ手法だ。

ここでもう一度v-onのおさらいをする。

jp.vuejs.org

通常の要素上で利用した場合、ネイティブ DOM イベント だけ購読します。カスタム要素コンポーネント上で利用した場合、子コンポーネント上での カスタムイベント の発行を購読します。

ということで、inputタグで@inputとするのとv-selectタグで@inputと書くのは
もともと全然意味が違う。

@inputでVue-selectが発行しているカスタムイベントをリッスンし、$eventでそのイベントが渡してくるデータを拾う。

<v-select 
    multiple
    label="email"
    @input="updateValue($event, 'active_peaple')"
    :options="$store.state.people"
    :value="$store.state.form.active_peaple"
  ></v-select>

このようにすると、思い通りkey_nameが渡せるようになる。

実際に実装してみたコードは以下だ。

codepen.io

v-modelとカスタムコンポーネントの仕組みを理解することで、
カスタムコンポーネントとして実装するタイプのコンポーネントをVuexで思い通りに実装するやり方が分かるようになると思う。

これからVuexやるよって人は、 難しいと思わずにしっかり抑えておいて欲しい!

Laravel5.6のセッション管理をmemcachedでやる手順(2)

パート1はこちらからどうぞ。

arm4.hatenablog.com

Laravelのsessionドライバーをmemcachedにしようと思ったわけだが
あんなにいつも親切なLaravelのドキュメントに、
なんと、設定方法が載っていなかった。

なので、Laravelのフレームワークのコードを読んで設定したぜよ

というお話。

Laravel 5.6 のsessionドライバーでmemcachedを使う(Macローカルで実験)

.envをのSESSION_DRIVERを書き換える。

.env

SESSION_DRIVER=memcached

vendor/laravel/framework/src/Illuminate/Session/SessionManager.php これによると、cacheドライバーとセッションドライバーの設定は共通らしい。

sessionのconfigのstoreにcacheのstoreのキーを指定すればよいっぽい。

    /**
     * Create an instance of the Memcached session driver.
     *
     * @return \Illuminate\Session\Store
     */
    protected function createMemcachedDriver()
    {
        return $this->createCacheBased('memcached');
    }
    /**
     * Create an instance of a cache driven driver.
     *
     * @param  string  $driver
     * @return \Illuminate\Session\Store
     */
    protected function createCacheBased($driver)
    {
        return $this->buildSession($this->createCacheHandler($driver));
    }
    /**
     * Create the cache based session handler instance.
     *
     * @param  string  $driver
     * @return \Illuminate\Session\CacheBasedSessionHandler
     */
    protected function createCacheHandler($driver)
    {
        $store = $this->app['config']->get('session.store') ?: $driver;

        return new CacheBasedSessionHandler(
            clone $this->app['cache']->store($store),
            $this->app['config']['session.lifetime']
        );
    }

config/session.php

    /*
    |--------------------------------------------------------------------------
    | Session Cache Store
    |--------------------------------------------------------------------------
    |
    | When using the "apc" or "memcached" session drivers, you may specify a
    | cache store that should be used for these sessions. This value must
    | correspond with one of the application's configured cache stores.
    |
    */

    'store' => 'memcached',

config/cache.php

    /*
    |--------------------------------------------------------------------------
    | Cache Stores
    |--------------------------------------------------------------------------
    |
    | Here you may define all of the cache "stores" for your application as
    | well as their drivers. You may even define multiple stores for the
    | same cache driver to group types of items stored in your caches.
    |
    */

    'stores' => [

        'apc' => [
            'driver' => 'apc',
        ],

        'array' => [
            'driver' => 'array',
        ],

        'database' => [
            'driver' => 'database',
            'table' => 'cache',
            'connection' => null,
        ],

        'file' => [
            'driver' => 'file',
            'path' => storage_path('framework/cache/data'),
        ],

        'memcached' => [
            'driver' => 'memcached',
            'persistent_id' => env('MEMCACHED_PERSISTENT_ID'),
            'sasl' => [
                env('MEMCACHED_USERNAME'),
                env('MEMCACHED_PASSWORD'),
            ],
            'options' => [
                // Memcached::OPT_CONNECT_TIMEOUT  => 2000,
            ],
            'servers' => [
                [
                    'host' => env('MEMCACHED_HOST', '127.0.0.1'),
                    'port' => env('MEMCACHED_PORT', 11211),
                    'weight' => 100,
                ],
            ],
        ],

        'redis' => [
            'driver' => 'redis',
            'connection' => 'default',
        ],

    ],

自分のMacmemcachedをインストールして実験するため
localhostなので設定はこのままで大丈夫そうだ。

しかしリロードするとMemcachedはないと怒られた。

Symfony \ Component \ Debug \ Exception \ FatalThrowableError (E_ERROR)
Class 'Memcached' not found

https://laravel.com/docs/5.6/cache#memcached-cache

cacheのほうのドキュメントを読んでみると、Memcached PECL package をインストールしなさいよと書いてある。

pecl install memcached

peclでインストールしてみたがエラーが出た。

ERROR: `/private/tmp/pear/temp/memcached/configure --with-php-config=/usr/local/opt/php/bin/php-config --with-libmemcached-dir=no' failed

libmemcachedのインストールでコケているっぽいのでbrewインストールする。

brew install libmemcached

再度、実行したらインストールに成功。

zlibでエラー出る人はXcodeのアップデートか、再インストールが必要そう。

pecl install memcached
.
.
Build process completed successfully
Installing '/usr/local/Cellar/php/7.2.6/pecl/20170718/memcached.so'
install ok: channel://pecl.php.net/memcached-3.0.4
Extension memcached enabled in php.ini

ちゃんと入っているので、phpをリスタートする。

php -i | grep memcached
memcached
memcached support => enabled
libmemcached version => 1.0.18
sudo brew services stop php
sudo brew services start php

保存されているかテストする

routes/web.php

Route::get('/', function () {
    session()->put('sample', 'beruko');

    return view('welcome');
});

ここでデバッグするためにddとか書いてしまうとsessionが保存されないので、デバッグしたい気持ちをぐっとこらえる。

telnetに接続しmemcachedに保存されているか確認する

stats items
STAT items:8:number 1
stats cachedump 8 1
ITEM beruko_sandbox_cache:uWTlfeZtpTUpHFAYfNR6nwycgA53gO0uZ1xg5nkp [273 b; 1529063998 s]
END
get beruko_sandbox_cache:uWTlfeZtpTUpHFAYfNR6nwycgA53gO0uZ1xg5nkp
VALUE beruko_sandbox_cache:uWTlfeZtpTUpHFAYfNR6nwycgA53gO0uZ1xg5nkp 0 273
a:5:{s:50:"login_web_59ba36addc2b2f9401580f014c7f58ea4e30989d";i:2;s:9:"_previous";a:1:{s:3:"url";s:26:"http://beruko-sandbox.test";}s:6:"_flash";a:2:{s:3:"old";a:0:{}s:3:"new";a:0:{}}s:6:"_token";s:40:"BVVBUIbJE94ZCLpb71aTLtSQzNI15r7MUIGwLdjj";s:6:"sample";s:6:"beruko";}
END

わーい♫ できたー

Laravel5.6のセッション管理をmemcachedでやる手順(1)

おっす、おらベル子。久しぶりのブログだぜっ!

最近、忙しくてイラストもまともに描けなくてストレスが溜まってるぜっ!
その代わり踊ってるんですが、踊りとイラストはまた別物なので、イラストを描く一人の時間がとにかく欲しいです。

昔から、好きなことに一人で没頭する時間がないと、快適に暮らしていてもストレスが徐々に溜まってきてしまうんですよね。

とにかく一人の時間を少し作って絵を描きたいです。

ということで本題です。

Laravel5.6のセッション管理をmemcachedでやりたい人向けの記事です。

memcached、何それ美味しいの?」な人から手順どおりやれば、Laravelのセッションドライバーをmemcachedでやれるようになります。

具体的にどういうときにmemcached使ったほうがいいのかというと、
Webサーバ2台構成とかでセッションを共有しないといけないなどの際に
ローカルストレージのfileじゃセッションの共有ができないので、 memcachedでやるとかそういう感じです。

キーと値のペアをメモリ上に保持するKVSの一種でRedisのお友達なので、
memcachedじゃなくてRedisでもいいです。

というかむしろ特別な理由がなければRedisでもいい気がしました。

まず、パート1ではmemcachedとは何かと基本的な使い方を学び、Macローカルにmemcachedをインストールします。

memcachedについて

gihyo.jp

memcachedとRedisの違い

yakst.com

qiita.com

post.simplie.jp

なるほどねー。

Macmemcachedをインストールし、実行確認する手順

memcachedbrewインストール

brew install memcached
which memcached

自動起動させるコマンドと、起動コマンドを案内してくれた。 brewでインストールしたので以下のフルパスじゃなくてmemcachedって打てば使えそう。

To have launchd start memcached now and restart at login:
  brew services start memcached
Or, if you don't want/need a background service you can just run:
  /usr/local/opt/memcached/bin/memcached

macOS High Sierratelnetを使えるようにする

https://qiita.com/samuraidays/items/b8a3d4a06e2c6c379865

brew install telnet

memcachedの起動オプション

オプション 説明
-p 利用するTCPのポート。デフォルトは11211
-m 最大のメモリーサイズ。デフォルトは64MB
-vv very verboseモードで起動してデバックメッセージやエラーをコンソールへ出力
-d memcachedをデーモンとしてバックグラウンドで起動
-h ヘルプを表示

telnet で接続

[~] telnet localhost 11211
Trying ::1...
Connected to localhost.
Escape character is '^]'.

バージョンの確認

version
VERSION 1.5.8

ステータスの確認

stats
STAT pid 3684
STAT uptime 96
STAT time 1529014973
STAT version 1.5.8
STAT libevent 2.1.8-stable
STAT pointer_size 64
STAT rusage_user 0.020749
STAT rusage_system 0.016610
STAT max_connections 1024
STAT curr_connections 2
STAT total_connections 3
STAT rejected_connections 0
STAT connection_structures 3
STAT reserved_fds 20
STAT cmd_get 0
STAT cmd_set 0
STAT cmd_flush 0
STAT cmd_touch 0
STAT get_hits 0
STAT get_misses 0
STAT get_expired 0
STAT get_flushed 0
STAT delete_misses 0
STAT delete_hits 0
STAT incr_misses 0
STAT incr_hits 0
STAT decr_misses 0
STAT decr_hits 0
STAT cas_misses 0
STAT cas_hits 0
STAT cas_badval 0
STAT touch_hits 0
STAT touch_misses 0
STAT auth_cmds 0
STAT auth_errors 0
STAT bytes_read 16
STAT bytes_written 15
STAT limit_maxbytes 67108864
STAT accepting_conns 1
STAT listen_disabled_num 0
STAT time_in_listen_disabled_us 0
STAT threads 4
STAT conn_yields 0
STAT hash_power_level 16
STAT hash_bytes 524288
STAT hash_is_expanding 0
STAT slab_reassign_rescues 0
STAT slab_reassign_chunk_rescues 0
STAT slab_reassign_evictions_nomem 0
STAT slab_reassign_inline_reclaim 0
STAT slab_reassign_busy_items 0
STAT slab_reassign_busy_deletes 0
STAT slab_reassign_running 0
STAT slabs_moved 0
STAT lru_crawler_running 0
STAT lru_crawler_starts 510
STAT lru_maintainer_juggles 145
STAT malloc_fails 0
STAT log_worker_dropped 0
STAT log_worker_written 0
STAT log_watcher_skipped 0
STAT log_watcher_sent 0
STAT bytes 0
STAT curr_items 0
STAT total_items 0
STAT slab_global_page_pool 0
STAT expired_unfetched 0
STAT evicted_unfetched 0
STAT evicted_active 0
STAT evictions 0
STAT reclaimed 0
STAT crawler_reclaimed 0
STAT crawler_items_checked 0
STAT lrutail_reflocked 0
STAT moves_to_cold 0
STAT moves_to_warm 0
STAT moves_within_lru 0
STAT direct_reclaims 0
STAT lru_bumps_dropped 0
END

各項目の詳細

tetsuyai.hatenablog.com

データをセット&ゲット

このへんを参考にデータをセットしたりゲットしたりしてみる。

kakakakakku.hatenablog.com

morizyun.github.io

set

# set key flags expiretime bytes
set hoge 0 0 4
# value
huga
STORED

保存するbyte数が間違ってるとエラーが返ってくる

set hoge 0 0 4
laravel
CLIENT_ERROR bad data chunk
ERROR

get

get hoge
VALUE hoge 0 4
huga
END

ありもしないkeyを指定するとエラーは返ってこず、ただ終わる

get hogege
END

なるほど、難しいことは何もない。 Redisと変わらなそう。

インクリメントとかデクリメントとか、コマンド間違えてみたりとか

set count 0 0 1
1
STORED
get count
VALUE count 0 1
1
END
incr count 1
2
get count
VALUE count 0 1
2
END
decr count 1
1
get count
VALUE count 0 1
1
END
incr count 2
3
get count
VALUE count 0 1
3
END

ありもしないキーを指定

decr count3
ERROR

存在しないコマンドを唱える

dect count 3
ERROR

なるほど、Redisと一緒ですね。

保存しているキーの一覧を表示

stats itemsと打って、items:{m}:number {n}みたいな行を探し、 stats cachedump {m} {n}みたいに打つと、キーの一覧を表示できる。

stats items
STAT items:1:number 2
STAT items:1:number_hot 0
STAT items:1:number_warm 0
STAT items:1:number_cold 2
STAT items:1:age_hot 0
STAT items:1:age_warm 0
STAT items:1:age 572
STAT items:1:evicted 0
STAT items:1:evicted_nonzero 0
STAT items:1:evicted_time 0
STAT items:1:outofmemory 0
STAT items:1:tailrepairs 0
STAT items:1:reclaimed 0
STAT items:1:expired_unfetched 0
STAT items:1:evicted_unfetched 0
STAT items:1:evicted_active 0
STAT items:1:crawler_reclaimed 0
STAT items:1:crawler_items_checked 6
STAT items:1:lrutail_reflocked 0
STAT items:1:moves_to_cold 7
STAT items:1:moves_to_warm 5
STAT items:1:moves_within_lru 0
STAT items:1:direct_reclaims 0
STAT items:1:hits_to_hot 0
STAT items:1:hits_to_warm 0
STAT items:1:hits_to_cold 7
STAT items:1:hits_to_temp 0
END
stats cachedump 1 2
ITEM count [1 b; 0 s]
ITEM hoge [4 b; 0 s]
END

mitsuakikawamorita.com

キーの削除

delete hoge
DELETED
stats items
STAT items:1:number 1
.
.
END
stats cachedump 1 1
ITEM count [1 b; 0 s]
END

有効期限付きでセット

set some_id 0 10 1
1
STORED

速攻唱えると参照できるが

get some_id
VALUE some_id 0 1
1
END

10秒後に唱えると消えている。

get some_id
END

儚い。

telnetを終了する

^C^]
telnet>  q
Connection closed.

memcachedコマンド一覧

l-w-i.net

NoSQL比較

qiita.com

Redisと違って、永続化もできないし、保存できるデータ構造も文字列しかなさそうなので
他にいろんな用途で使うようなことがあればRedisのほうがいいのかなと思いました。
でもmemcachedはシンプルで分かりやすくていいです。

ちなみにLaravelのセッションドライバーはRedisも選べます。

パート2はLaravel側の設定について書くぜ!
お楽しみにー。

Vuex使った時にフォームのバインディングにv-model使うと怒られる問題の解決法

Vuex使った時にフォームのバインディングにv-model使うと怒られる問題の 最終的な私の答え。

eventでvalueとキーネームを飛ばして ミューテーションでキーネーム付け合わせて、 バーンて入れるだけ。

これならミューテーションにupdateHogeを入力項目ごとに書かなくて済む。

inputにはこれを書いて

:value="blogForm.title"
@input="updateBlogForm($event, 'title')"

inputのあるコンポーネントのmethodにはこれを書いて

updateBlogForm(e, key_name) {
    this.$store.commit('updateBlogFormValue', { value:e.target.value, key_name });
}

ストアにこれを書くだけ

updateBlogFormValue (state, { value, key_name }) {
    state.blogForm[key_name] = value;
},

思いついたときに感動した。


【キーワード】 Vuex form input v-model エラー mutation バインディングイデア