2019/07/02
「jQuery LoadingOverlay」をネイティブで実装してみる。

サンプル

Github: yoo16/html_samples

HTML


  <button onclick="loading_overlay.show('loading1')">show on element1</button>
  <button onclick="loading_overlay.hide('loading1')">hide on element1</button>
  <button onclick="loading_overlay.show('loading2')">show on element2</button>
  <button onclick="loading_overlay.hide('loading2')">hide on element2</button>
  <button onclick="loading_overlay.show()">show on body</button>

  <div id="loading1" class="card">
    This is loading1 element areas.<br>
    This is loading1 element areas.<br>
    This is loading1 element areas.<br>
    This is loading1 element areas.<br>
    This is loading1 element areas.<br>
    This is loading1 element areas.<br>
  </div>

  <div id="loading2" class="card">
    This is loading2 element areas.<br>
    This is loading2 element areas.<br>
    This is loading2 element areas.<br>
    This is loading2 element areas.<br>
    This is loading2 element areas.<br>
    This is loading2 element areas.<br>
  </div>

  <style>
    .card {
        width: 400px;
        border: 1px solid #a0a0a0;
        background: rgb(255, 242, 198);
        padding: 10px;
    }
  </style>

Javascript


var LoadingOverlay = function() {
    var _this = this
    this.loading_overlay_name = 'loading_overlay';
    
    this.show = function(selector, options) {
        _this.hide(selector);
        var style = "";
        style+= "position: absolute;";
        style+= "z-index: 1050;";
        style+= "background-color: rgba(255, 255, 255, 0.2);";
        style+= "background-position: center center;";
        style+= "background-repeat: no-repeat;";

        var top = "0;";
        var left = "0;";
        var width = "100%;";
        var height = "100%;";
        var background_size = 'contains';
        var element = document.body;
        if (selector) {
            element = document.getElementById(selector);
            var rect = element.getBoundingClientRect();
            top = rect.top;
            left = rect.left;
            width = element.clientWidth;
            height = element.clientHeight;
            background_size = _this.backgroundSize(element);

            let td = element.closest('td');
            if (td) {
                top = 0;
                left = 0;
            }
        }
        style+= "background-size: " + background_size + ";";
        style+= "top: " + top + "px;";
        style+= "left: " + left + "px;";
        style+= "width: " + width + "px;";
        style+= "height: " + height + "px;";
        style+="background-image: url(" + loading_image + ");";

        _this.loading_overlay_element = document.createElement('div');
        _this.loading_overlay_element.classList.add(_this.loading_overlay_name);
        _this.loading_overlay_element.style = style;

        element.appendChild(_this.loading_overlay_element);

        //timer
        function hideHandler() {
            clearInterval(_this.timer);
            _this.timer = null;
            _this.hide(selector);
        }
        if (options && options.timeout > 0) {
            if (!_this.timer) _this.timer = setInterval(hideHandler, options.timeout);
        }
    }
    this.hide = function(selector) {
        var parent_element;
        if (selector) {
            parent_element = document.getElementById(selector);
        } else {
            parent_element = document.body;
        }
        [].forEach.call(parent_element.children, function(element) {
            if (element.classList.contains(_this.loading_overlay_name)) {
                parent_element.removeChild(element);
            }
        });
    }
    this.backgroundSize = function(element) {
        background_size = "contains";
        var img = new Image();
        img.src = loading_image;

        var width_rate = 0;
        var height_rate = 0;
        if (img.width > element.clientWidth) {
            width_rate = element.clientWidth / img.width;
        }
        if (img.height > element.clientHeight) {
            height_rate = element.clientHeight / img.height;
        }
        var rate = 0;
        if (width_rate > height_rate) {
            rate = width_rate;
        } else {
            rate = height_rate;
        }
        if (rate > 0) background_size = rate * 30 + "%;"
        return background_size;
    }
}
var loading_image = "data:image/gif;base64,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";

var loading_overlay = new LoadingOverlay();

表示処理

document.createElement('div') で LoadingOver Element を作成し、style を動的に設定後、ターゲットに追加(appendChild()) している。 (ターゲットがない場合は document.body) styleはターゲットの位置やサイズを取得して absolute で位置合わせしている。 ローディング画像(loading_image)は、画像をBase64に変換しているが、URLでも構わない。 backgroundSize() ではローディング画像のサイズを調整している。 ローディング画像が親より小さければ「background_size: contains」、大きければ「%」で調整する。

非表示処理

指定したIDの子要素の中の、LoadingOver Element のクラスを検索して削除(removeChild()) これで要素毎のローディングにも対応できる。

  2019/07/01
クラス名や「rel」アトリビュートを指定して、新規ウィンドウで開く

サンプル

html_samples/popup.html

HTML


    <a href="http://yoo-s.com" rel="popup" window_name="window_name" window_option="width=500,height=500,toolbar=yes,menubar=yes,scrollbars=yes">rel New Window</a>
    <a href="http://yoo-s.com" class="popup_class" window_name="window_name" window_option="width=500,height=500,toolbar=yes,menubar=yes,scrollbars=yes">class New Window</a>
HTML属性にウィンドウ名「window_name」、オプション「window_option」を指定した

rel を指定して開く

rel属性を指定した querySelectorAll() で NodeList を取得して click イベントを登録 (IEだと単にループで回せないので、一工夫必要)

    function loadPopupRelEvent(rel_name) {
        var popupEvent = function(event) {
            var window_name = '_blank';
            var window_option = null;
            if (this.getAttribute('window_name')) window_name = this.getAttribute('window_name');
            if (this.getAttribute('window_option')) window_option = this.getAttribute('window_option');
            window.open(this.href, window_name, window_option).focus()
            event.preventDefault();
            event.stopPropagation();
        }
        var query_string = '[rel = "' + rel_name + '"]';
        let elements = document.querySelectorAll(query_string);
        if (!elements) return;
        [].forEach.call(elements, function (element) {
            element.addEventListener('click', popupEvent, false);
        });
    }
    document.addEventListener('DOMContentLoaded', function () {
      loadPopupRelEvent('popup', params);
    });

クラス指定して開く

getElementsByClassName() で HTMLCollection を取得して click イベントを登録 (IEだと単にループで回せないので、一工夫必要)

    function loadPopupClassEvent(class_name) {
        var popupEvent = function(event) {
            var window_name = '_blank';
            var window_option = null;
            if (this.getAttribute('window_name')) window_name = this.getAttribute('window_name');
            if (this.getAttribute('window_option')) window_option = this.getAttribute('window_option');
            window.open(this.href, window_name, window_option).focus()
            event.preventDefault();
            event.stopPropagation();
        }
        let elements = document.getElementsByClassName(class_name);
        if (!elements) return;
        [].forEach.call(elements, function (element) {
            element.addEventListener('click', popupEvent, false);
        });
    }
    document.addEventListener('DOMContentLoaded', function () {
      loadPopupClassEvent('popup_class', params);
    });
要素にclickイベントを登録し、正規表現でURLパースする

  2019/06/17
テーブルソートは、jQuery(tablednd.js)で比較的簡単に実装できる。 tablednd はマウスイベントを駆使して実装している感じだが、ここではHTML5のDND(Drag & Dropイベント)を利用して実装してみる。

HTML5ドラッグ&ドロップの仕様確認

まずは仕様を確認 ・HTML Living Standard:Drag and dropネイティブ HTML5 ドラッグ&ドロップ

サンプル&ライブラリ

tableの並び替え&アップデートスクリプトのライブラリ(PwJS)を作成してみた。

Github

PwJSライブラリ *PwTableDND.js, PwNode.jsを利用 html_samples/sotrable_table.html 色々と制御する必要があるので、ここでは主要部分だけ記述 *並び替えの保持やAPI更新は記述なし

ドラッグ&ドロップの実装

「dragstart」「dragover」「drop」などのDNDイベントを登録して、Element取得・操作を行う

        //各イベントハンドラ
        function handleDragStart(event) {
            //ここにドラッグアイテムの取得処理
            event.target.style.opacity = '0.4';  //透明度を有効
            event.stopPropagation();
        }
        function handleDrag(event) {
        }
        function handleDragEnter(event) {
        }
        function handleDragOver(event) {
            event.dataTransfer.dropEffect = 'move'; //仕様でサポートしている dropEffect
            event.preventDefault();  //伝播を止める
            return false;
        }
        function handleDragLeave(event) {
            
        }
        function handleDrop(event) {
            //ここにターゲットアイテムの取得処理
            event.preventDefault();  //伝播を止める
            event.stopPropagation();  //リンクキャンセル
        }
        function handleDragEnd(event) {
            event.target.style.opacity = '' //透明度を無効
        }
        //各イベントの登録
        document.addEventListener('dragstart', handleDragStart, false);
        document.addEventListener('drag', handleDrag, false);
        document.addEventListener('dragenter', handleDragEnter, false)
        document.addEventListener('dragover', handleDragOver, false);
        document.addEventListener('dragleave', handleDragLeave, false);
        document.addEventListener('drop', handleDrop, false);
        document.addEventListener('dragend', handleDragEnd, false);
伝播しないように preventDefault(), ドラッグでリンク誤動作しないように stopPropagation() を実行しているが、実際に実行してみるとよくわかる。

ドラッグ&ドロップで行を移動

並び順のデータID「row-id」属性を持った「tr」で構成 「tbody」内の「tr」を入れ替えるようなスクリプトを作成する

  <table id="sortable-table">
    <thead>
      <tr>
        <th>City</th>
      </tr>
    </thead>
    <tbody>
      <tr row-id="1">
        <td>Tokyo</td>
      </tr>
      <tr row-id="2">
        <td>Osaka</td>
      </tr>
      <tr row-id="3">
        <td>Nagoya</td>
      </tr>
      <tr row-id="4">
        <td>Kobe</td>
      </tr>
    </tbody>
  </table>

「draggable = true」でドラッグ可能&ソート属性を生成

querySelectorAll() などでElement や HTMLCollection を取得して、各行の属性を動的に設定 HTML5では「draggable = true」でドラッグ可能になる

       ....

    var _this = this;
    this.table_id = 'sortable-table';
    this.row_id_column = 'row-id';
    this.body_selector = '';
    this.tr_selector = '';
    this.sortable_tr_selector = '';
        ....

    this.enableDrag = function() {
        _this.loadSelectorColumn();
        if (!this.table_id) return;
        var row_id;
        [].forEach.call(this.getElements(), function(element, index) {
            _this.before_rows.push(element);
            row_node = PwNode.byElement(element);
            if (row_id = row_node.attr(_this.row_id_column)) {
                row_node.setAttr('id', pw_row_id_column + row_id);
                row_node.setAttr('order', index + 1);
                row_node.setAttr('draggable', true);
                if (!pw_app.isIE()) {
                    row_node.setAttr('ondragstart', "event.dataTransfer.setData('text/plain', null)");
                }
            }
        });
    }
    this.loadSelectorColumn = function() {
        _this.body_selector = '#' + _this.table_id + ' tbody';
        _this.tr_selector = '#' + _this.table_id + ' tr';
        _this.sortable_tr_selector = _this.body_selector + ' tr';
    }
    this.getElements = function() {
        let elements = document.querySelectorAll(_this.sortable_tr_selector);
        return elements;
    }
FirefoxではHTMLタグに「ondragstart="event.dataTransfer.setData('text/plain', null)"」を指定しておかないと、何故か動作しなかった。 *pw_app.isIE() はライブラリのIE判別関数

DNDイベント処理

dropイベントで、Drag Element, Drop Elementの取得・入れ替えを行う

        function handleDragStart(event) {
            let tr = event.target.closest('tr');
            if (tr) _this.drag_item = event.target.closest('tr');
            event.target.style.opacity = '0.4';
            event.stopPropagation();
        }
        function handleDrop(event) {
            var tr = event.target.closest('tr');
            if (tr && _this.drag_item != tr) {
                _this.target_item = tr;
            }
            event.target.style.opacity = '1.0'
            let row_id = _this.drag_item.getAttribute(_this.row_id_column);
            if (row_id && _this.target_item && _this.drag_item != _this.target_item) {
                var tbody = PwNode.byQuery(_this.body_selector).first();
                let drag_order = _this.drag_item.getAttribute('order');
                let target_order = _this.target_item.getAttribute('order');
                if (drag_order > target_order) {
                    tbody.insertBefore(_this.drag_item, _this.target_item);
                } else if (drag_order < target_order) {
                    tbody.insertBefore(_this.drag_item, _this.target_item.nextElementSibling);
                }
                //テーブル並び替え後の処理を記述
                //並び順管理、tr.order を振り直す etc..
            }
            event.preventDefault();
            event.stopPropagation();
        }
event.target.closest() で「tr」を取得 「tbody」内で insertBefore() を利用し、並び順を考慮しつつ Element を書き換える 色々な方法があると思うが、上記は「tr」の order が並び替え後に順番を振り直す事を前提にしている

  2019/06/03
jQuery の $(document).on() をネイティブでコーディング document.addEventListner() で記述するが、ネイティブの場合はターゲット(Event.target)が何かによって条件分岐が必要

サンプル

Github

yoo16/html_samples/blob/master/document_on.html

idの場合


    //jQuery
    $(document).on('click', '#id_name', function() {
        //working
    });

    //native
    document.addEventListener('click', function(event) {
        if (event.target.id === 'id_name') {
            //working
        }
    });

classの場合


    //jQuery
    $(document).on('click', '.class_name', function() {
        //working
    });

    //native
    document.addEventListener('click', function(event) {
        if(event.target.classList.contains('class_name'))
            //working
        }
    });
querySelectorAll() で取得する方法もある。 (この方がjQueryに近いか?) ただ、addEventListener() を事前登録するため、後にHTMLを発生さした要素では動作しないのでイベント管理が必要

querySelectorAll() classの場合


        document.querySelectorAll('.class_name').forEach(function(element) {
            element.addEventListener('click', function(event) {
                //working
            });
        });
上記はIEの場合「NodeList」をループで回せない可能性があるので、

        let elements = document.querySelectorAll('.class_name');
            [].forEach.call(elements, function(element) {
            element.addEventListener('click', function(event) {
                //working
            });
        });
としても良い。

  2019/05/28

・git clone が重い
・秘密のファイルを Commit してしまった

など、過去にファイルを Commit & Pull してしまった場合、問題ファイルをなかったことにしたい場合があります。

履歴の削除は「git filter-branch」を利用してできますが、破壊的に履歴変更するため事前バックアップするなど作業は自己責任で行ってください。

PHPサンプルスクリプト

destory_git_history.php

オブジェクト容量の大きいファイルを検出

git_find_big.sh で大きなオブジェクトを抽出


$ du -sh .git/objects 12M .git/objects
$ sh git_find_big.sh

「git_find_big.sh」は、gitコマンドを用いて「.git/objects/pack/pack」内の容量の多いオブジェクト順で抽出します。

履歴を抹消

抽出したファイルやディレクトリを削除 (refs/heads/master と refs/remotes/origin/master を書き換え)
※ディレクトリの場合は「git rm -r」


$ git filter-branch -f --index-filter 'git rm --cached --ignore-unmatch ファイルパス' --prune-empty -- --all

ガベージコレクションを利用して、不要なオブジェクトやログを削除します。


$ git gc --aggressive --prune=now

git オブジェクトのリパックします。


$ git repack -A -d

強制的にPush


$ git push --force origin master

共同作業している場合は、clone してもらった方が安全かもしれません。

  2019/05/28
Gitignore にファイルを記述しても反映されない場合、キャッシュをクリアして commit & push してみる。
$ git rm -r --cached .bash_profile rm '.bash_profile'
ファイル名に「.」を指定して、全ファイルをターゲットにする事もできるが、ちょっと怖いので1ファイルずつ実行した。

  2019/05/15

UFJ が API を虎視眈々と開発していた。

カブドットコムのAPIも使えたりと結構楽しそう、というか近々実用化されそうな予感がします。

カブドットコムのAPI(kabu.com API)は本番環境で利用できるとのことだが、
法人契約が必要なのと当然ながら審査が必要です。

開発用API登録

UFJ API

API種別

2019/05/15現在、個人口座、法人口座、振込申請、総合振込申請、給与賞与振込申請、特別徴収地方税のAPIが用意されている。

UFJ API

API Client Secretの発行

当然ながらAPIを利用するには、Client Secret の発行が必要となる。

UFJ API

APIリファレンス

各サービス毎にリファレンスは用意されている。

cURL,Ruby,Python,PHP,Java,Node,Go,Swift のサンプルが記載されており、
結構本気度が伺えられる。 また、レスポンスは基本 json のようだ。

UFJ API

ただ本番利用の場合は、金融業界なので審査が厳しいと予想される。

ライブラリ(PHP)

使いやすいように、Github にクラスライブラリを作成してました。

https://github.com/yoo16/ufj_api (2019/05/15現在アカウント情報取得のみ)

また、検証用データが用意されていて、Account ID一覧は以下の通り


001001110001 002001110002 325001110003 135011110005 118011110008 
329011110009 002021110013 002022220003 325022220004 909022220013 
002022220014 002023330003 325023330004 480023330005 777023330008 
118023330009 427383330012 909383330013 002383330014 002283330016

実行結果


$ php get_account.php 002023330003 

{"branchNo":"002","branchName":"丸の内","accountTypeCode":"02",
"accountTypeDetailCode":"00099",
"accountTypeName":"定期","accountNo":"3330003",
"accountName":null,"accountNameKana":null,
"balance":100000,"withdrawableAmount":null,
"currencyCode":"JPY"
,"foreignCurrencyBalance":null,
"yenEquivalent":null,"exchangeRate":null,
"totalMarketValue":null,
"totalUnrealizedProfitAndLoss":null,
"mutualFundAccountType":null,"fundBaseDate":null}

  2019/05/15
30日前より前のメールをラベル抽出して、ゴミ箱に移動するスクリプト GitHub: yoo16/gas_samples

function removeGmail() {
    var before_days = 30;
    var spreadsheet_id = 'スプレードシートID';
    var sheet = SpreadsheetApp.openById(spreadsheet_id).getActiveSheet();
    var values = sheet.getDataRange().getValues();
    for (var i = 0; i < values.length; i++) {
        removeMail(values[i], before_days);
    }
}

function removeMail(label, before_days) {
    var condition = 'older_than:' + before_days + 'd label:'+ label;
    var threads = GmailApp.search(condition);
    for (var i = 0; i < threads.length; i++) {
        threads[i].moveToTrash();
    }
    //TODO loop for all threads by label
    //var threads = GmailApp.search(condition, 0, 100);
    //GmailApp.moveThreadsToTrash(threads);
}

Google Apps Script : GmailApp Reference

GmailApp の機能はClass GmailAppを参照 Gmail検索ラベルは複数あるので、Googleスプレッドシートに記載して読み取る スプレッドシートの指定は、ファイル名検索でもできるが、あらかじめID取得しておいた方が楽

var sheet = SpreadsheetApp.openById(spreadsheet_id).getActiveSheet();

Gmail操作

GmailApp.search() メソッドで Gmailを検索できるが、引数は Gmail のブラウザ操作で現れるものと同じと考えて良い。

var threads = GmailApp.search('older_than:' + before_days + 'd label:'+ label);
ただし件数制限がある模様(threads.length を調べると500件)

    for (var i = 0; i < threads.length; i++) {
        threads[i].moveToTrash();
    }
1スレッドづつ削除するが、完全削除ではなくゴミ箱に移動する (完全削除メソッドは GAS では用意されていない)

Threadをまとめてゴミ箱に移動

上記だと forループで1スレッド毎にゴミ箱に移動するが、一括でゴミ箱移動する「GmailApp.moveThreadsToTrash()」がメソッドが存在する

var threads = GmailApp.search('older_than:' + before_days + 'd label:'+ label);
GmailApp.moveThreadsToTrash(threads);
ただし「この操作は最大 100 件のスレッドにのみ適用できます。」と表示され、100件までしか動作しないようなので、search() するときに件数を指定

var condition = 'older_than:' + before_days + 'd label:'+ label;
var threads = GmailApp.search(condition, 0, 100);
GmailApp.moveThreadsToTrash(threads);
これを、メールがなくなるまでループで回せば全削除はできそう

トリガー登録で定期実行

定期的にスクリプトを実行するには「編集 > 現在のプロジェクトのトリガー」から設定できる。 GAS Trigger 「トリガーを追加」でスケジュールを設定できる(詳細設定はわかりやすいので割愛) GAS Trigger

  2019/05/02
プロジェクトを整理していたら、アプリケーションキー「encryption key」を消失http://xxx.xxx.xxx.xxx:8000/ のアクセス時に Runtimeエラーが表示 作成する
$ php artisan key:generate
Application key set successfully.
実際にはクラスファイル「KeyGenerateCommand」で、Laravel Config設定に基づき、 base64_encode() と Encrypter::generateKey() でランダムキーを生成している模様。 Illuminate Foundation Console KeyGenerateCommand
    public function handle()
    {
        $key = $this->generateRandomKey();
       .....
        $this->laravel['config']['app.key'] = $key;
    }
    protected function generateRandomKey()
    {
        return 'base64:'.base64_encode(
            Encrypter::generateKey($this->laravel['config']['app.cipher'])
        );
    }

  2019/04/29

Linux PHPパッケージの用意

通常PHP環境(PDO, JSON, LAMP & LAPP...)で最低限入れておけば動作しそうだが、laravel プロジェクト作成のバージョンによって異なる Installation(5.8)


# aptitude install php-zip php7.3-pdo php7.3-pgsql php7.3-mysql php7.3-mbstring php7.3-ssh2 php7.3-gd php7.3-curl php7.3-tokenizer php7.3-bcmath php7.3-ctype

composer の用意

PHP7.3 で環境を作成するため、ソースでインストールした。 (Debian9系パッケージの composer だとエラーになる) PHP7.3 で compser install できない


composer -V
Composer version 1.8.5

Laravel インストール & プロジェクト作成

composer で Laravel をインストールし、~/.config/composer/vendor/ にコマンドパスを通す


$ composer global require "laravel/installer"
$ export PATH="~/.config/composer/vendor/bin:$PATH"

プロジェクト作成(laravelコマンド)

この時点でエラーになる場合は、ライブラリが不足している可能性がある ライブラリが膨大なため、まぁまぁ時間がかかる


$ laravel new project_name
...
  - Installing symfony/translation (v4.2.7): Downloading (100%)         
  - Installing nesbot/carbon (2.17.1): Downloading (100%)         
  - Installing monolog/monolog (1.24.0): Downloading (100%)         
  - Installing league/flysystem (1.0.51): Downloading (100%)         
  - Installing laravel/framework (v5.8.14): Downloading (100%)  
...
Package manifest generated successfully.
Application ready! Build something amazing.

パーミッション変更

storage, bootstrap/cache のパーミッションを変更しないと起動できない


$ chmod -R 777 storage
$ chmod -R 777 bootstrap/cache

ここら辺はコマンド自動化した方が良いかと

プロジェクト作成(Composerコマンド)

こちらの方が一般的か? laravel のパスが利用できない場合は、以下のコマンドで作成


$ composer create-project laravel/laravel --prefer-dist project_name 5.8

Laravelサーバ起動

個人環境では、Mac上にVirtualBox(Debian)サーバを別IPでルーティングしているため、IPの指定(--host)が必要


$ php artisan serve --host=192.168.11.56

Laravel

リダイレクト設定

artisan serve でなく Apache で動作させる場合、public のリダイレクト設定が必要 VirtualHost で設定する方法もあるが、「.htaccess」で public をルートとみなすようにする

PHP7.x & Laravel5.x

<ifmodule mod_rewrite.c="">
    <ifmodule mod_negotiation.c="">
        Options -MultiViews
    </ifmodule>

    RewriteEngine On

    RewriteCond %{REQUEST_FILENAME} -d [OR]
    RewriteCond %{REQUEST_FILENAME} -f
    RewriteRule ^ ^$1 [N]

    RewriteCond %{REQUEST_URI} (\.\w+$) [NC]
    RewriteRule ^(.*)$ public/$1

    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ server.php

</ifmodule>
フォーム有効期限切れで Page Expired をリダイレクト
ログを日付でローテーションやクリアや削除
Homebrew で PHP8.0 から PHP7.4 にダウングレード
Big sur で zsh 移行と Homebrew アップグレード
Mac に minikube をインストール
途中から .gitignore に追加する
Larevel 6.x から Laravel 8.x にバージョンアップ
Composer で Allowed memory size (メモリ不足)エラー
Blade でカスタムクラスを利用する
git push git pull にブランチ指定せずに実行する
git pull や git push できなくなったとき
Docker のコンテナからホストOS に接続
Mac で ローカル IP アドレス(ipv4)のみを表示する
ホストOS から Docker の MySQLコンテナに接続
caching_sha2_password のエラー
node-config で環境設定ファイルを利用する
rootパスワードを初期化(再設定)する
Git から clone したときのエラー対処
Mac に MySQL をインストール
Mac に PostgreSQL をインストール
Laravel 環境構築 - Mac ネイティブ編
Firebase 入門 - Firebase とは
Firebase 入門 - CLI インストールとデータベースの設定
AWS 無料枠(t2.micro)で容量とメモリエラー
Cloud9 を起動する -初心者編-
gcloud で GCEインスタンスを起動してみる
AWS CLI と jq でインスタンス一覧を整形して表示
React と Laravel7 のプロジェクトを作成する
Homebrewインストール-2020年版
3直線で囲まれた範囲塗りつぶし
PuLP で線形最適化問題を解く
カスタムのペジネーションを作る
node-sass を使って sass をコンパイルする
Log ファサードでSQLログを分離して書き出す
いちから始める Docker - 複数のコンテナを使う - (2020年)
いちから始める Docker - docker-compose を使う - (2020年)
AWS ECR を使ってみる
Laravel7 でマルチ認証
Mac に AWS Client を設定する
Laravel7 リリース
v-html でHTML表示する
Laravel で Nuxt.js を使ってみる(Docker環境)
Laravel で Vue コンポーネントを使う
いちから始める Docker -コンテナをビルド- (2020年)
いちから始める Docker -起動してみる- (2020年)
Mac で MySQL(8系)
composer で vendor がインストールできない
Eloquent の日付を Carbon で扱う
webpack 4 入門(npm編)
[Mac]容量を減らす