学習備忘録

よく忘れてしまうのをここにメモしておく

コントローラからjsに値を渡す方法

  • @jsonを利用する

  • フロント側

<script>
let companies = @json($companies);
</script>

-js側 - companiesにhtmlで指定した値がjson形式で入っている。

$(document).on("change", ".select-company", function(){
  let val = $(this).val()
  companies.forEach(company => {
    if(val == company.id) {
      company.stores.forEach(store => {
        select.append($('<option>').attr({value: store.id}).text(store.title))
      });
    }
  });
});
  • <data-xxx=aaa>を利用する

  • フロント側

    • data-xxxで値を入力する。
<button type="button" class="blue-btn edit-btn" data-toggle="moda"
                                data-target="#editAccount" data-userid="{{$user->id}}"
                                data-role="{{implode(',', $user->roles->pluck('id')->all())}}"
                                data-canly-role="{{Encore\Admin\Auth\Database\Role::getFirstCanlyRole($user->roles->pluck('id')->all())}}"
                                data-companies="{{implode(',',$user->companies->pluck('id')->all())}}">
                                編集
                            </button>

-js側 - $(this).data('userid');みたいな感じで取得できる。

$('button.edit-btn').click(function () {
  // form の action を調整する
  const userId = $(this).data('userid');
  const orgAction = $('#route-account-update').val();
  $('#form-edit').attr('action', orgAction + '/' + userId);

  // role をセットする
  const role = $(this).data('canly-role');
  $("#accounts_edit_role_select").val(role);

  // 会社情報をクリアする
  const rowBakup = $('.row-company-select:last-child');
  $(".companies-to-edit").children().remove();
  $(".companies-to-edit").append(rowBakup);

  // 所属する companies 分だけ行を追加する
  const companies = ($(this).data('companies') + '').split(',');
  $.each(companies, function (index, val) {
    if (0 < index) {
      copyCompanyRow();
    }
    $(`.row-company-select:last-child select option[value='${val}']`).prop('selected', true);
  });
});

jquery複数の値入力周りのまとめ

課題

  • 入力フォームで複数の値を入力したい
  • 入力フォームの行を動的に増やした
  • 動的に増やした入力フォームに対して、イベント追加したい
  • イベントを検知した要素を取得したい
  • 複数の値を入力するフォーム(select2など)を動的に増やした場合に、適切にpostする方法。
  • select2の選択肢をjqueryで操作する方法

対策

入力フォームで複数の値を入力したい

<select name="stores[1][]" class="form-control select2-js-store-name cursor-pointer" multiple="multiple" data-placeholder="店舗(指定なし)">
                                    
</select>
  • js
    • select要素に対してselect2を呼び出す。※前提としてselect2を読み込んでいる必要がある。
$(document).ready(function () {
  $('.select2-js-store-name').select2();
});

入力フォームの行を動的に増やしたい&&複数の値を入力するフォーム(select2など)を動的に増やした場合に、適切にpostする方法。

  • フロント側
                 <div class="accounts-to-add">
                        <div class="row d-flex align-center justify-content-between margin-top-8 row-invitation-input">
                            <div class="col-md-3 pl-0 pr-1">
                                <input name='email[]' type="text" class="form-control border-radius-4"
                                    placeholder="name@example.com">
                            </div>
                       
                            <div class="col-md-2 pl-0 pr-1 select-store">
                                <div class="custom-select select2-div">
                                    <select name="stores[1][]" class="form-control select2-js-store-name cursor-pointer" multiple="multiple" data-placeholder="店舗(指定なし)">
                                    
                                    </select>
                                    <i class="fa fa-chevron-down"></i>
                                </div>
                            </div>
            
                            <div class="col-md-1 px-0">
                                <span>
                                    <button type="button" class="btn btn-add-key p-0 m-12 btn-add-account-row-delete"
                                        onclick='deleteAccountRowOnAddModal(this)'>
                                        <i class="fa fa-times"></i>
                                    </button>
                                </span>
                            </div>
                        </div>
                    </div>
  • js側
    • INPUT_ACCOUNT_ROWで初期の1行目をクローンしておく
    • ボタン(add-invitation-button)が押されたら、親要素(account-to-add)にクローンを追加する
    • select2の場合追加後に、select2を設定しないとplaceholderが正しく表示されない。
    • store_length以降の処理で新しく生成した要素に個別のnameを付けている。それにより、postされた側での処理がしやすくなる。
INPUT_ACCOUNT_ROW = $('.accounts-to-add').children().clone();
// 新規行の追加
$('.add-invitation-button').click(function () {
  let newLine = INPUT_ACCOUNT_ROW.clone(true);
  // select2 を remove して再設定する
  newLine.find('span.select2-container').remove();
 
  $('.accounts-to-add').append(newLine);

  let stores_length = $('.accounts-to-add').children('div').length
  newLine.find('.select2-js-store-name').select2()
  newLine.find('.select2-js-store-name').attr('name', 'stores'+'['+stores_length+'][]')
});

動的に増やした入力フォームに対して、イベント追加したい&&select2の選択肢をjqueryで操作する方法&&イベントを検知した要素を取得したい

  • js側
    • documentに対して、第一引数にイベントを設定し第二引数で動的に増やした要素名を入力する。
    • $(this)とすればイベントを検知した要素を取得できる。
$(document).on("change", ".select-company", function(){
  let select = $(this).parent().parent().parent().find(".select2-js-store-name")
  select.children().remove()

  let val = $(this).val()
  companies.forEach(company => {
    if(val == company.id) {
      company.stores.forEach(store => {
        select.append($('<option>').attr({value: store.id}).text(store.title))//セレクトボックスのoptionの追加
      });
    }
  });

  //セレクトボックスのoptionの削除
  select.val(null).trigger('change')
});

formを使用せずaタグでクエリーパラメータを送信する方法

課題

  • 送信したいクエリパラメータの数が決まっていない
  • formが使用できない

実装

  • フロント側
    • $requestにはkeyとvalueで構成された配列が入っている。
    • http_build_queryを使用し、$requestをkey1=value1&key2=value2みたいな形式にしている
<a type="button" class="green-border-btn small-btn margin-right-10"
            id="exportAccountsCsv"
            href="{{ route('accounts.export_csv') }}">
                <div class="d-flex align-center">
                    <img src="{{ asset('img/download-cloud.png') }}" alt="" class="margin-right-10">
                    <span>CSVダウンロード</span>
                </div>
            </a>
            <input type="hidden" id="accountsQueryParam" value="{{ http_build_query($request) }}">
  • js側
    • 対象のaタグがクリックされた際に、先ほど整型した$requestをurlの末尾にくっつている。
$('#exportAccountsCsv').click(function (e) {
  e.preventDefault();
  let queryParam = $('#accountsQueryParam').val()
  let url = $(this).attr('href') + '?' + queryParam;
  window.location = url;
});

ECSでのタスク実行方法

課題

  • fargateで運用している場合、sshで接続してコマンドを実行ということができない。そのため外部からツールを利用して実行しなければいけない

対処法

  • 今回は例としてseedを考える

  • seed用のタスク定義を作成する.

{
    "networkMode": "awsvpc",
    "cpu": "256",
    "memory": "512",
    "requiresCompatibilities": [ "FARGATE"],
    "executionRoleArn": "arn:aws:iam::467531687456:role/ecs_task_execution_role",
    "containerDefinitions":
    [
      {
        "name": "seed",
        "image": "467531687456.dkr.ecr.ap-northeast-1.amazonaws.com/match-project-app-development:latest",
        "essential": true,
        "entryPoint": ["/bin/sh"],
        "command": ["-c", "php artisan db:seed --class=DatabaseSeeder"],
        "environment": [
          {
            "name": "APP_NAME",
            "value": "match-project"
          },
          {
            "name": "APP_ENV",
            "value": "development"
          },
          {
            "name": "APP_DEBUG",
            "value": "true"
          },
          {
            "name": "LOG_CHANNEL",
            "value": "cloudwatch"
          },
          {
            "name": "CLOUDWATCH_LOG_RETENTION",
            "value": "60"
          },
          {
            "name": "DB_CONNECTION",
            "value": "mysql"
          },
          {
            "name": "DB_HOST",
            "value": "match-project-dev-aurora-cluster.cluster-clfk8ycueurb.ap-northeast-1.rds.amazonaws.com"
          },
          {
            "name": "DB_PORT",
            "value": "3306"
          },
          {
            "name": "DB_USERNAME",
            "value": "organizer"
          },
          {
            "name": "DB_PASSWORD",
            "value": "pass1234"
          },
          {
            "name": "DB_DATABASE",
            "value": "lara_match"
          },
          {
            "name": "BROADCAST_DRIVER",
            "value": "log"
          },
          {
            "name": "CACHE_DRIVER",
            "value": "redis"
          },
          {
            "name": "SESSION_DRIVER",
            "value": "redis"
          },
          {
            "name": "SESSION_LIFETIME",
            "value": "10080"
          },
          {
            "name": "REDIS_HOST",
            "value": "$REDIS_HOST_DEV"
          },
          {
            "name": "REDIS_PASSWORD",
            "value": "null"
          },
          {
            "name": "REDIS_PORT",
            "value": "6379"
          },
          {
            "name": "AWS_BUCKET",
            "value": "match-project.dev.uploads"
          },
          {
            "name": "MAIL_DRIVER",
            "value": "ses"
          },
          {
            "name": "MAIL_FROM_ADDRESS",
            "value": "tmp"
          },
          {
            "name": "MAIL_FROM_NAME",
            "value": "dev"
          },
          {
            "name": "SES_REGION",
            "value": "us-east-1"
          },
          {
            "name": "ADMIN_HTTPS",
            "value": "true"
          }
        ]
      }
    ]
  }
aws ecs register-task-definition --family match-project-dev-seed --cli-input-json file://seed-task-definition.json --region ap-northeast-1
  • あとは以下を状況に合わせて変更して、実行
SUBNETS=$(aws ecs describe-services --cluster match-project-dev --service app --region ap-northeast-1 --query "services[0].networkConfiguration.awsvpcConfiguration.subnets" --output text | awk '{printf "%s,%s",$1,$2}')
SECURITY_GROUPS=$(aws ecs describe-services --cluster match-project-dev --service app --region ap-northeast-1 --query "services[0].networkConfiguration.awsvpcConfiguration.securityGroups" --output text)

aws ecs run-task --launch-type FARGATE --cluster match-project-dev --task-definition match-project-dev-migrate --region ap-northeast-1 --count 1 --network-configuration "awsvpcConfiguration={subnets=[$SUBNETS],securityGroups=[$SECURITY_GROUPS],assignPublicIp=ENABLED}" --query "tasks[0].taskArn" --output text

factoryでオリジナルの値を生成したいする方法

課題

  • facoryのチートシートに求める値が存在していないので自身で実装しなければいけない

対処法

  • factory内でランダムに値を生成する場合
<?php
$factory->define(UserProfile::class, function (Faker $faker) {
    $residence = ['東京都', '大阪府', '静岡県', '福岡県', '神奈川県', '沖縄県', '北海道', '香川県'];
    $job = ['エンジニア', 'CA', '商社', '銀行員', '公務員', '国家公務員', '医師', 'パイロット'];
    $text = [
        'こんばんわ☺️
        
        仲良くしていただけると嬉しいです❗️',
        '初めまして☺️
        
        マッチングアプリは初めてですが是非よろしくお願いします。',
        'こんにちわ☺️
        
        真剣に出会いを探しています。連絡取れると嬉しいです❗️',
    ];

    return [
        'user_id' => function() {
            return factory(App\User::class)->create()->id;
        },
        'user_name' => null,
        'residence' => $residence[rand(0, 7)],
        'age'       => rand(20, 30),
        'height'    => rand(160, 180),
        'job'       => $job[rand(0,7)],
        'img_url'   => null,
        'text'      => $text[rand(0, 2)],

    ];
});
  • 順序通りにfactoryを生成したい場合
<?

private $img_url = [
        'https://matching-kou.s3-ap-northeast-1.amazonaws.com/3/40e84e95.jpg',
        'https://matching-kou.s3-ap-northeast-1.amazonaws.com/4/42905757_1946147315443146_8509928890392442925_n.jpg',
        'https://matching-kou.s3-ap-northeast-1.amazonaws.com/5/a0001508_main.jpg',
        'https://matching-kou.s3-ap-northeast-1.amazonaws.com/6/aru.jpg',
        null,
        null,
        null,
        null,
        null,
        null,
        null,
        null,
        null,
        null,
        null
    ];
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        $this->call(UserTableSeeder::class);
        $this->call(UserProfileTableSeeder::class);

        for($i = 3; $i < 23; $i++) {
            factory(App\User::class, 1)->create(['id' => $i, 'sex' => 1, 'name' => $this->user_name[$i - 3]])->each(function ($user) use($i){
                factory(App\Model\UserProfile::class, 1)->create(['user_id' => $user->id, 'user_name' => $this->user_name[$i - 3], 'img_url' => $this->img_url[$i - 3]]);
            });
        }

        for($i = 23; $i < 43; $i++) {
            factory(App\User::class, 1)->create(['id' => $i, 'sex' => 0, 'name' => $this->user_name[$i - 1]])->each(function ($user) use($i){
                factory(App\Model\UserProfile::class, 1)->create(['user_id' => $user->id,'user_name' => $this->user_name[$i -1], 'img_url' => $this->img_url[$i - 1]]);
            });
        }

        $this->call(RoomsTableSeeder::class);
        $this->call(LikesTableSeeder::class);
        $this->call(MessagesTableSeeder::class);
    }

中間テーブルのカラムに値を持たせる方法

  • 中間テーブルのstatusカラムに値を指定したいときはこんな感じで書く。
<?php

   public function send(Request $request, User $user)
    {
        //$now = Carbon::now()->format('Y-m-d H:i:s');

        $request->user()->send_like_user()->detach($user);
        $request->user()->send_like_user()->attach($user, ['status' => 'sended']); //ここがポインんと

        return ['name' => $user->name];
    }

factoryでリレーション を持たせてモデルを生成する方法

状況

  • userモデルのリレーション先であるuser_profileのuser_idにuserモデルのidを持たせたい

  • user_profileのfactoryはこんな感じ

<?php

/** @var \Illuminate\Database\Eloquent\Factory $factory */

use App\Model\UserProfile;
use Faker\Generator as Faker;

$factory->define(UserProfile::class, function (Faker $faker) {
    return [
        'user_id' => function() { //ここからがポイント
            return factory(App\User::class)->create()->id;
        },
        'user_name' => $faker->userName(),
        'residence' => "東京都",
        'age'       => rand(20,30),
        'job'       => $faker->jobTitle,
        'img_url'   => "https://matching-kou.s3.ap-northeast-1.amazonaws.com/3/TW2fauu9FNUFIYorYS8zqcSee1w2V6HPR36uJKOj.png",
        'text'      => $faker->text(100),

    ];
});
  • facotryを生成する時にこんな感じで書くけばいい
<?php

       factory(User::class, 6)->create()->each(function ($user) {
            factory(UserProfile::class, 1)->create(['user_id' => $user->id, 'age' => "25"]);
        });