- 投稿日:2021-01-23T23:58:03+09:00
キューで重い動作を非同期で動かしてみた
経緯
移行元のデータベースから開発側にデータを移行することになった。 だが、データ量が膨大なので非同期で処理をしてみました。事前準備
- キューのジョブテーブルとキューが失敗した時のテーブルを作成
# ジョブを記録するためのデータベーステーブルを作成する php artisan queue:table php artisan migrate
- envファイルに以下を追加で記述
QUEUE_CONNECTION=databaseジョブを作成する
php artisan make:job InsettJob非同期で処理する処理をジョブ内に作成する
<?php namespace App\Jobs; use App\Domains\Facility\UseList; use DateTime; use Exception; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; use Illuminate\Support\Facades\DB; use Illuminate\Support\Str; use PDO; use PDOException; class InsettJob implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; /** * タイムアウトまでの秒数 * * @var int */ public $timeout = 60; /** * Create a new job instance. * * @return void */ public function __construct() { // } /** * ANCHOR [connectionToBase 移行元のデータベースに接続] * * @return [type] [return description] */ public function connectionToBase() { try { $db = 'データベース名'; // データベースに接続 $pdo = new PDO( "mysql:dbname={$db};host=mysql;charset=utf8mb4", 'ユーザー名', 'パスワード', [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, ] ); return $pdo; } catch (PDOException $e) { header('Content-Type: text/plain; charset=UTF-8', true, 500); exit($e->getMessage()); } } /** * ANCHOR [getTableData 指定したテーブルデータを取得] * * @param [type] $db [$db description] * @param string $query [$query description] * * @return object [return description] */ public function getTableData($db, string $query): object { return $db->query($query); } /** * ANCHOR[registrationPreparation インサート準備] * * @param object $facilityList [$facilityList description] * * @return void */ public function registrationPreparation(object $facilityList): void { DB::table('移行先テーブル')->truncate(); $insertList = []; foreach ($facilityList as $v) { $insertList[] = [ 'id' => $v['code'], 'name' => $v['name'], 'name_kana' => $v['name_kana'], 'created_at' => $v['insert_date'], 'updated_at' => $v['update_date'] ]; } $this->registrationExecution($insertList); } } /** * [registrationExecution インサート処理] * * @param array $insertList [$insertList description] * * @return void [return description] */ public function registrationExecution(array $insertList): void { DB::transaction(function () use ($insertList) { try { DB::table('移行先テーブル')->insert($insertList); } catch (Exception $e) { header('Content-Type: text/plain; charset=UTF-8', true, 500); exit($e->getMessage()); } }); } /** * Execute the job. * * @return void */ public function handle() { // DB接続 $db = $this->connectionToBase(); $sql = 'SELECT * FROM テーブル名 ORDER BY code ASC'; // クエリ実行 $facilityList = $this->getTableData($db, $sql); $this->registrationPreparation($facilityList); } public function failed(Exception $exception) { header('Content-Type: text/plain; charset=UTF-8', true, 500); exit($exception->getMessage()); } }コントローラーでジョブを呼び出す
<?php namespace App\Http\Controllers; use App\Jobs\FacilityCategoryImportJob; use App\Jobs\InsettJob; use DateTime; use Exception; use Illuminate\Http\RedirectResponse; class DatabaseMigrationController extends Controller { /** * 施設データ移行事前準備 * php artisan queue:work --sleep=3 --tries=1 --stop-when-empty --queue=facility * php artisan queue:restart キューの設定反映 * * @return void [return description] */ public function facilityImport(): void { try { InsettJob::dispatch()->onQueue('facility'); } catch (Exception $e) { header('Content-Type: text/plain; charset=UTF-8', true, 500); exit($e->getMessage()); } } }ジョブ内容を反映させる
php artisan queue:restartキューを動かす
php artisan queue:work --sleep=3 --tries=1 --stop-when-empty --queue=facility
- 投稿日:2021-01-23T23:58:03+09:00
キューで重い処理を非同期で動かしてみた
経緯
移行元のデータベースから開発側にデータを移行することになった。 だが、データ量が膨大なので非同期で処理をしてみました。事前準備
- キューのジョブテーブルとキューが失敗した時のテーブルを作成
# ジョブを記録するためのデータベーステーブルを作成する php artisan queue:table php artisan migrate
- envファイルに以下を追加で記述
QUEUE_CONNECTION=databaseジョブを作成する
php artisan make:job InsettJob非同期で処理する処理をジョブ内に作成する
<?php namespace App\Jobs; use App\Domains\Facility\UseList; use DateTime; use Exception; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; use Illuminate\Support\Facades\DB; use Illuminate\Support\Str; use PDO; use PDOException; class InsettJob implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; /** * タイムアウトまでの秒数 * * @var int */ public $timeout = 60; /** * Create a new job instance. * * @return void */ public function __construct() { // } /** * ANCHOR [connectionToBase 移行元のデータベースに接続] * * @return [type] [return description] */ public function connectionToBase() { try { $db = 'データベース名'; // データベースに接続 $pdo = new PDO( "mysql:dbname={$db};host=mysql;charset=utf8mb4", 'ユーザー名', 'パスワード', [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, ] ); return $pdo; } catch (PDOException $e) { header('Content-Type: text/plain; charset=UTF-8', true, 500); exit($e->getMessage()); } } /** * ANCHOR [getTableData 指定したテーブルデータを取得] * * @param [type] $db [$db description] * @param string $query [$query description] * * @return object [return description] */ public function getTableData($db, string $query): object { return $db->query($query); } /** * ANCHOR[registrationPreparation インサート準備] * * @param object $facilityList [$facilityList description] * * @return void */ public function registrationPreparation(object $facilityList): void { DB::table('移行先テーブル')->truncate(); $insertList = []; foreach ($facilityList as $v) { $insertList[] = [ 'id' => $v['code'], 'name' => $v['name'], 'name_kana' => $v['name_kana'], 'created_at' => $v['insert_date'], 'updated_at' => $v['update_date'] ]; } $this->registrationExecution($insertList); } } /** * [registrationExecution インサート処理] * * @param array $insertList [$insertList description] * * @return void [return description] */ public function registrationExecution(array $insertList): void { DB::transaction(function () use ($insertList) { try { DB::table('移行先テーブル')->insert($insertList); } catch (Exception $e) { header('Content-Type: text/plain; charset=UTF-8', true, 500); exit($e->getMessage()); } }); } /** * Execute the job. * * @return void */ public function handle() { // DB接続 $db = $this->connectionToBase(); $sql = 'SELECT * FROM テーブル名 ORDER BY code ASC'; // クエリ実行 $facilityList = $this->getTableData($db, $sql); $this->registrationPreparation($facilityList); } public function failed(Exception $exception) { header('Content-Type: text/plain; charset=UTF-8', true, 500); exit($exception->getMessage()); } }コントローラーでジョブを呼び出す
<?php namespace App\Http\Controllers; use App\Jobs\FacilityCategoryImportJob; use App\Jobs\InsettJob; use DateTime; use Exception; use Illuminate\Http\RedirectResponse; class DatabaseMigrationController extends Controller { /** * 施設データ移行事前準備 * php artisan queue:work --sleep=3 --tries=1 --stop-when-empty --queue=facility * php artisan queue:restart キューの設定反映 * * @return void [return description] */ public function facilityImport(): void { try { InsettJob::dispatch()->onQueue('facility'); } catch (Exception $e) { header('Content-Type: text/plain; charset=UTF-8', true, 500); exit($e->getMessage()); } } }ジョブ内容を反映させる
php artisan queue:restartキューを動かす
php artisan queue:work --sleep=3 --tries=1 --stop-when-empty --queue=facility
- 投稿日:2021-01-23T19:31:05+09:00
laravel-mixのコンパイルでSyntaxError: Unexpected token = と怒られたら
発生したエラー
laravel-mixでコンパイルしたところ下記のエラーで怒られた
触ってないファイルでsyntax errorとか言われて困ったubuntu# npm run dev npm WARN npm npm does not support Node.js v10.23.1 npm WARN npm You should probably upgrade to a newer version of node as we npm WARN npm can't make any promises that npm will work with this version. npm WARN npm Supported releases of Node.js are the latest release of 4, 6, 7, 8, 9. npm WARN npm You can find the latest version at https://nodejs.org/ > @ dev /var/www/vue-laravel-spa > npm run development npm WARN npm npm does not support Node.js v10.23.1 npm WARN npm You should probably upgrade to a newer version of node as we npm WARN npm can't make any promises that npm will work with this version. npm WARN npm Supported releases of Node.js are the latest release of 4, 6, 7, 8, 9. npm WARN npm You can find the latest version at https://nodejs.org/ > @ development /var/www/vue-laravel-spa > mix [webpack-cli] /var/www/vue-laravel-spa/node_modules/laravel-mix/src/Mix.js:18 static _primary = null; ^ SyntaxError: Unexpected token = at new Script (vm.js:83:7) at NativeCompileCache._moduleCompile (/var/www/vue-laravel-spa/node_modules/v8-compile-cache/v8-compile-cache.js:240:18) at Module._compile (/var/www/vue-laravel-spa/node_modules/v8-compile-cache/v8-compile-cache.js:184:36) at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10) at Module.load (internal/modules/cjs/loader.js:653:32) at tryModuleLoad (internal/modules/cjs/loader.js:593:12) at Function.Module._load (internal/modules/cjs/loader.js:585:3) at Module.require (internal/modules/cjs/loader.js:692:17) at require (/var/www/vue-laravel-spa/node_modules/v8-compile-cache/v8-compile-cache.js:159:20) at module.exports (/var/www/vue-laravel-spa/node_modules/laravel-mix/setup/webpack.config.js:2:17) npm ERR! code ELIFECYCLE npm ERR! errno 2 npm ERR! @ development: `mix` npm ERR! Exit status 2 npm ERR! npm ERR! Failed at the @ development script. npm ERR! This is probably not a problem with npm. There is likely additional logging output above. npm ERR! A complete log of this run can be found in: npm ERR! /root/.npm/_logs/2021-01-23T09_26_30_393Z-debug.log npm ERR! code ELIFECYCLE npm ERR! errno 2 npm ERR! @ dev: `npm run development` npm ERR! Exit status 2 npm ERR! npm ERR! Failed at the @ dev script. npm ERR! This is probably not a problem with npm. There is likely additional logging output above. npm ERR! A complete log of this run can be found in: npm ERR! /root/.npm/_logs/2021-01-23T09_26_30_443Z-debug.log環境
% sw_vers ProductName: Mac OS X ProductVersion: 10.15.7 BuildVersion: 19H2 % docker version Client: Docker Engine - Community Cloud integration: 1.0.1 Version: 19.03.13 API version: 1.40 # php -v PHP 7.4.7 (cli) (built: Jun 11 2020 18:41:17) ( NTS ) Copyright (c) The PHP Group Zend Engine v3.4.0, Copyright (c) Zend Technologies with Xdebug v3.0.2, Copyright (c) 2002-2021, by Derick Rethans # php artisan -v Laravel Framework 8.24.0原因
ググりまくった結果こちらのサイトに辿り着いた
https://github.com/JeffreyWay/laravel-mix/issues/2570
どうやらnode.jsのバージョンを最新にすると直るらしい対処
こちらの記事を参考に対処した
https://qiita.com/seibe/items/36cef7df85fe2cefa3ea
https://qiita.com/kiwi-bird/items/e3e551938d09282cf4ee
今回初めて知ったのだがn package
を使うことでnpmパッケージとnode.js自体のバージョン管理をしてくれるらしい
こんな便利なものがあったのかというわけで
n package
をインストールするubuntu# npm install n -g # グローバルにインストールする npm WARN npm npm does not support Node.js v10.23.1 npm WARN npm You should probably upgrade to a newer version of node as we npm WARN npm can't make any promises that npm will work with this version. npm WARN npm Supported releases of Node.js are the latest release of 4, 6, 7, 8, 9. npm WARN npm You can find the latest version at https://nodejs.org/ /usr/local/bin/n -> /usr/local/lib/node_modules/n/bin/n + n@7.0.0 added 1 package from 4 contributors in 0.858s # n stable # 最新のnodejsをインストール installing : node-v14.15.4 mkdir : /usr/local/n/versions/node/14.15.4 fetch : https://nodejs.org/dist/v14.15.4/node-v14.15.4-linux-x64.tar.xz installed : v14.15.4 (with npm 6.14.10) Note: the node command changed location and the old location may be remembered in your current shell. old : /usr/bin/node new : /usr/local/bin/node To reset the command location hash either start a new shell, or execute PATH="$PATH" # apt purge -y nodejs npm # aptで入れた古いnodejsとnpmを削除 Reading package lists... Done Building dependency tree Reading state information... Done The following packages were automatically installed and are no longer required: gyp javascript-common libbrotli1 libc-ares2 libexpat1 libjs-inherits libjs-is-typedarray libnode-dev libnode64 libpython-stdlib libpython2-stdlib libpython2.7-minimal libpython2.7-stdlib libreadline7 libssl-dev libuv1 libuv1-dev lsb-base mime-support nodejs-doc python python-minimal python-pkg-resources python2 python2-minimal python2.7 python2.7-minimal Use 'apt autoremove' to remove them. The following packages will be REMOVED: node-abbrev* node-ajv* node-ansi* node-ansi-align* node-ansi-regex* node-ansi-styles* node-ansistyles* node-aproba* node-archy* node-are-we-there-yet* node-asn1* node-assert-plus* node-asynckit* node-aws-sign2* node-aws4* node-balanced-match* node-bcrypt-pbkdf* node-bluebird* node-boxen* node-brace-expansion* node-builtin-modules* node-builtins* node-cacache* node-call-limit* node-camelcase* node-caseless* node-chalk* node-chownr* node-cli-boxes* node-cliui* node-clone* node-co* node-color-convert* node-color-name* node-combined-stream* node-concat-map* node-concat-stream* node-config-chain* node-console-control-strings* node-copy-concurrently* node-core-util-is* node-cross-spawn* node-cyclist* node-dashdash* node-decamelize* node-decompress-response* node-deep-extend* node-defaults* node-delayed-stream* node-delegates* node-detect-indent* node-detect-newline* node-duplexer3* node-duplexify* node-ecc-jsbn* node-editor* node-encoding* node-end-of-stream* node-errno* node-escape-string-regexp* node-execa* node-extend* node-extsprintf* node-find-up* node-flush-write-stream* node-forever-agent* node-form-data* node-from2* node-fs-vacuum* node-fs-write-stream-atomic* node-fs.realpath* node-gauge* node-get-caller-file* node-get-stream* node-getpass* node-glob* node-got* node-graceful-fs* node-gyp* node-har-schema* node-har-validator* node-has-flag* node-has-symbol-support-x* node-has-to-string-tag-x* node-has-unicode* node-hosted-git-info* node-http-signature* node-iconv-lite* node-iferr* node-import-lazy* node-imurmurhash* node-inflight* node-inherits* node-ini* node-invert-kv* node-is-builtin-module* node-is-npm* node-is-object* node-is-plain-obj* node-is-retry-allowed* node-is-stream* node-is-typedarray* node-isarray* node-isexe* node-isstream* node-isurl* node-jsbn* node-json-parse-better-errors* node-json-schema* node-json-stable-stringify* node-json-stringify-safe* node-jsonify* node-jsonparse* node-jsonstream* node-jsprim* node-latest-version* node-lazy-property* node-lcid* node-libnpx* node-locate-path* node-lockfile* node-lowercase-keys* node-lru-cache* node-mem* node-mime-types* node-mimic-fn* node-mimic-response* node-minimatch* node-minimist* node-mississippi* node-mkdirp* node-move-concurrently* node-mute-stream* node-node-uuid* node-nopt* node-normalize-package-data* node-npm-package-arg* node-npm-run-path* node-npmlog* node-oauth-sign* node-object-assign* node-once* node-opener* node-os-locale* node-osenv* node-p-cancelable* node-p-finally* node-p-limit* node-p-locate* node-p-timeout* node-package-json* node-parallel-transform* node-path-exists* node-path-is-absolute* node-path-is-inside* node-performance-now* node-prepend-http* node-process-nextick-args* node-promise-inflight* node-promzard* node-proto-list* node-prr* node-pump* node-pumpify* node-punycode* node-qs* node-qw* node-rc* node-read* node-read-package-json* node-readable-stream* node-registry-auth-token* node-registry-url* node-request* node-require-directory* node-require-main-filename* node-resolve-from* node-retry* node-rimraf* node-run-queue* node-safe-buffer* node-semver* node-semver-diff* node-set-blocking* node-sha* node-shebang-command* node-shebang-regex* node-signal-exit* node-slash* node-slide* node-sorted-object* node-spdx-correct* node-spdx-expression-parse* node-spdx-license-ids* node-sshpk* node-ssri* node-stream-each* node-stream-iterate* node-stream-shift* node-string-decoder* node-string-width* node-strip-ansi* node-strip-eof* node-strip-json-comments* node-supports-color* node-tar* node-term-size* node-text-table* node-through* node-through2* node-timed-out* node-tough-cookie* node-tunnel-agent* node-tweetnacl* node-typedarray* node-uid-number* node-unique-filename* node-unpipe* node-url-parse-lax* node-url-to-options* node-util-deprecate* node-uuid* node-validate-npm-package-license* node-validate-npm-package-name* node-verror* node-wcwidth.js* node-which* node-which-module* node-wide-align* node-widest-line* node-wrap-ansi* node-wrappy* node-write-file-atomic* node-xdg-basedir* node-xtend* node-y18n* node-yallist* node-yargs* node-yargs-parser* nodejs* npm* 0 upgraded, 0 newly installed, 241 to remove and 18 not upgraded. After this operation, 16.7 MB disk space will be freed. (Reading database ... 19266 files and directories currently installed.) Removing npm (5.8.0+ds6-4+deb10u2) ... Removing node-gyp (3.8.0-6) ... Removing node-nopt (3.0.6-3) ... Removing node-abbrev (1.1.1-1) ... Removing node-request (2.88.1-2) ... Removing node-har-validator (5.1.0-1) ... Removing node-ajv (5.0.0-1) ... Removing node-ansi (0.3.0-3) ... Removing node-boxen (1.2.2-1) ... Removing node-ansi-align (2.0.0-1) ... Removing node-libnpx (10.2.0+repack-1) ... Removing node-yargs (10.0.3-2) ... Removing node-cliui (4.1.0-1) ... Removing node-wrap-ansi (4.0.0-1) ... Removing node-chalk (2.3.0-2) ... Removing node-ansi-styles (3.2.1-1) ... Removing node-ansistyles (0.1.3-1) ... Removing node-npmlog (4.1.2-1) ... Removing node-gauge (2.7.4-1) ... Removing node-cacache (11.3.2-2) ... Removing node-move-concurrently (1.0.1-2) ... Removing node-archy (1.0.0-2) ... Removing node-are-we-there-yet (1.1.4-1) ... Removing node-http-signature (1.2.0-1) ... Removing node-sshpk (1.13.1+dfsg-2) ... Removing node-asn1 (0.2.3-1) ... Removing node-dashdash (1.14.1-2) ... Removing node-jsprim (1.4.0-1) ... Removing node-verror (1.10.0-1) ... Removing node-form-data (2.3.2-2) ... Removing node-asynckit (0.4.0-2) ... Removing node-aws-sign2 (0.7.1-1) ... Removing node-aws4 (1.8.0-1) ... Removing node-read-package-json (2.0.13-1) ... Removing node-copy-concurrently (1.0.5-4) ... Removing node-bcrypt-pbkdf (1.0.1-1) ... Removing node-bluebird (3.5.1+dfsg2-2) ... Removing node-normalize-package-data (2.4.0-1) ... Removing node-is-builtin-module (2.0.0-1) ... Removing node-builtin-modules (3.0.0-1) ... Removing node-npm-package-arg (6.0.0-2) ... Removing node-validate-npm-package-name (3.0.0-1) ... Removing node-builtins (1.0.3-1) ... Removing node-call-limit (1.1.0-1) ... Removing node-yargs-parser (11.1.1-1+deb10u1) ... Removing node-camelcase (5.0.0-1) ... Removing node-caseless (0.12.0-1) ... Removing node-tar (4.4.6+ds1-3) ... Removing node-chownr (1.1.1-1) ... Removing node-cli-boxes (1.0.0-1) ... Removing node-widest-line (1.2.2-1) ... Removing node-co (4.6.0-1) ... Removing node-color-convert (1.9.0-3) ... Removing node-color-name (1.1.3-1) ... Removing node-combined-stream (1.0.7-1) ... Removing node-mississippi (3.0.0-1) ... Removing node-concat-stream (1.6.2-1) ... Removing node-config-chain (1.1.11-1) ... Removing node-console-control-strings (1.1.0-1) ... Removing node-through2 (2.0.5-2) ... Removing node-flush-write-stream (1.0.3-1) ... Removing node-term-size (1.2.0+dfsg-2) ... Removing node-os-locale (2.0.0-1) ... Removing node-execa (0.10.0+dfsg-1) ... Removing node-cross-spawn (5.1.0-2) ... Removing node-parallel-transform (1.1.0-2) ... Removing node-cyclist (1.0.1-2) ... Removing node-decamelize (1.2.0-1) ... Removing node-latest-version (3.1.0-1) ... Removing node-package-json (4.0.1-1) ... Removing node-got (7.1.0-1) ... Removing node-decompress-response (3.3.0-1) ... Removing node-registry-url (3.1.0-1) ... Removing node-registry-auth-token (3.3.1-1) ... Removing node-rc (1.1.6-2) ... Removing node-deep-extend (0.4.1-2) ... Removing node-delayed-stream (0.0.5-1) ... Removing node-delegates (1.0.0-1) ... Removing node-detect-indent (5.0.0-1) ... Removing node-detect-newline (2.1.0-1) ... Removing node-duplexer3 (0.1.4-4) ... Removing node-pumpify (1.5.1-1) ... Removing node-duplexify (3.6.1-1) ... Removing node-ecc-jsbn (0.1.1-1) ... Removing node-editor (1.0.0-1) ... Removing node-encoding (0.1.12-2) ... Removing node-stream-each (1.2.2-2) ... Removing node-pump (3.0.0-1) ... Removing node-end-of-stream (1.4.1-1) ... Removing node-errno (0.1.4-1) ... Removing node-escape-string-regexp (1.0.5-1) ... Removing node-extend (3.0.2-1) ... Removing node-extsprintf (1.3.0-1) ... Removing node-find-up (2.1.0-1) ... Removing node-forever-agent (0.6.1-1) ... Removing node-from2 (2.3.0-1) ... Removing node-fs-vacuum (1.2.10-2) ... Removing node-fs-write-stream-atomic (1.0.10-4) ... Removing node-get-caller-file (1.0.2-1) ... Removing node-get-stream (3.0.0-1) ... Removing node-getpass (0.1.7-1) ... Removing node-write-file-atomic (2.3.0-1) ... Removing node-sha (2.0.1-1) ... Removing node-graceful-fs (4.1.11-1) ... Removing node-har-schema (2.0.0-1) ... Removing node-supports-color (4.4.0-2) ... Removing node-has-flag (2.0.0-1) ... Removing node-isurl (1.0.0-1) ... Removing node-has-to-string-tag-x (1.4.1+dfsg-1) ... Removing node-has-symbol-support-x (1.4.1+dfsg-1) ... Removing node-has-unicode (2.0.1-2) ... Removing node-hosted-git-info (2.7.1-1) ... Removing node-iconv-lite (0.4.13-2) ... Removing node-iferr (1.0.2-1) ... Removing node-import-lazy (3.0.0.REALLY.2.1.0-1) ... Removing node-unique-filename (1.1.0+ds-2) ... Removing node-imurmurhash (0.1.4-1) ... Removing node-ini (1.3.5-1) ... Removing node-lcid (1.0.0-1) ... Removing node-invert-kv (1.0.0-1) ... Removing node-is-npm (1.0.0-1) ... Removing node-is-object (1.0.1-1) ... Removing node-is-plain-obj (1.1.0-1) ... Removing node-is-retry-allowed (1.1.0-1) ... Removing node-is-stream (1.1.0-1) ... Removing node-is-typedarray (1.0.0-2) ... Removing node-which (1.3.0-2) ... Removing node-isexe (2.0.0-4) ... Removing node-isstream (0.1.2+dfsg-1) ... Removing node-jsbn (1.1.0-1) ... Removing node-json-parse-better-errors (1.0.2-2) ... Removing node-json-schema (0.2.3-1) ... Removing node-json-stable-stringify (1.0.1-1) ... Removing node-json-stringify-safe (5.0.1-1) ... Removing node-jsonify (0.0.0-1) ... Removing node-jsonstream (1.3.2-1) ... Removing node-jsonparse (1.3.1-6) ... Removing node-lazy-property (1.0.0-3) ... Removing node-locate-path (2.0.0-1) ... Removing node-lockfile (1.0.4-1) ... Removing node-lowercase-keys (1.0.0-2) ... Removing node-lru-cache (5.1.1-4) ... Removing node-mem (1.1.0-1) ... Removing node-mime-types (2.1.21-1) ... Removing node-mimic-fn (1.1.0-1) ... Removing node-mimic-response (1.0.0-1) ... Removing node-minimist (1.2.0-1+deb10u1) ... Removing node-mkdirp (0.5.1-1) ... Removing node-promzard (0.3.0-1) ... Removing node-read (1.0.7-1) ... Removing node-mute-stream (0.0.8-1) ... Removing node-node-uuid (3.3.2-2) ... Removing node-npm-run-path (2.0.2-2) ... Removing node-oauth-sign (0.9.0-1) ... Removing node-object-assign (4.1.1-2) ... Removing node-opener (1.4.3-1) ... Removing node-osenv (0.1.5-1) ... Removing node-p-cancelable (0.3.0-1) ... Removing node-p-timeout (1.2.0-1) ... Removing node-p-finally (1.0.0-2) ... Removing node-p-locate (2.0.0-1) ... Removing node-p-limit (1.1.0-1) ... Removing node-path-exists (3.0.0-1) ... Removing node-path-is-inside (1.0.2-1) ... Removing node-performance-now (2.1.0+debian-1) ... Removing node-url-parse-lax (1.0.0-1) ... Removing node-prepend-http (2.0.0-1) ... Removing node-promise-inflight (1.0.1-1) ... Removing node-proto-list (1.2.4-1) ... Removing node-prr (1.0.1-1) ... Removing node-tough-cookie (2.3.4+dfsg-1) ... Removing node-punycode (2.1.1-2) ... Removing node-qs (6.5.2-1) ... Removing node-qw (1.0.1-1) ... Removing node-require-directory (2.1.1-1) ... Removing node-require-main-filename (1.0.1-1) ... Removing node-resolve-from (4.0.0-1) ... Removing node-retry (0.10.1-1) ... Removing node-tunnel-agent (0.6.1-1) ... Removing node-semver-diff (2.1.0-2) ... Removing node-semver (5.5.1-1) ... Removing node-set-blocking (2.0.0-1) ... Removing node-shebang-command (1.2.0-1) ... Removing node-shebang-regex (2.0.0-1) ... Removing node-signal-exit (3.0.2-1) ... Removing node-slash (1.0.0-1) ... Removing node-slide (1.1.6-2) ... Removing node-sorted-object (2.0.1-1) ... Removing node-validate-npm-package-license (3.0.1-1) ... Removing node-spdx-correct (1.0.2-1) ... Removing node-spdx-expression-parse (1.0.4-1) ... Removing node-spdx-license-ids (1.2.2-1) ... Removing node-ssri (5.2.4-2) ... Removing node-stream-iterate (1.2.0-4) ... Removing node-stream-shift (1.0.0-1) ... Removing node-strip-eof (1.0.0-2) ... Removing node-strip-json-comments (2.0.1-2) ... Removing node-text-table (0.2.0-2) ... Removing node-through (2.3.8-1) ... Removing node-timed-out (4.0.1-4) ... Removing node-tweetnacl (0.14.5+dfsg-3) ... Removing node-typedarray (0.0.6-1) ... Removing node-uid-number (0.0.6-1) ... Removing node-unpipe (1.0.0-1) ... Removing node-url-to-options (1.0.1-1) ... Removing node-uuid (3.3.2-2) ... Removing node-which-module (2.0.0-1) ... Removing node-wide-align (1.1.0-1) ... Removing node-xdg-basedir (3.0.0-1) ... Removing node-xtend (4.0.1-2) ... Removing node-y18n (3.2.1-2) ... Removing node-yallist (3.0.3-1) ... Removing node-run-queue (1.0.3-1) ... Removing node-aproba (1.2.0-1) ... Removing node-assert-plus (1.0.0-1) ... Removing node-rimraf (2.6.2-1) ... Removing node-glob (7.1.3-2) ... Removing node-minimatch (3.0.4-3) ... Removing node-brace-expansion (1.1.8-1) ... Removing node-balanced-match (0.4.2-1) ... Removing node-string-width (2.1.1-1) ... Removing node-wcwidth.js (1.0.0-1) ... Removing node-defaults (1.0.3-1) ... Removing node-clone (2.1.2-1) ... Removing node-concat-map (0.0.1-1) ... Removing node-readable-stream (2.3.6-1) ... Removing node-core-util-is (1.0.2-1) ... Removing node-fs.realpath (1.0.0-1) ... Removing node-inflight (1.0.6-1) ... Removing node-inherits (2.0.3-1) ... Removing node-isarray (2.0.4-1) ... Removing node-once (1.4.0-3) ... Removing node-path-is-absolute (1.0.0-1) ... Removing node-process-nextick-args (2.0.0-1) ... Removing node-string-decoder (1.2.0-1) ... Removing node-safe-buffer (5.1.2-1) ... Removing node-util-deprecate (1.0.2-1) ... Removing node-wrappy (1.0.2-1) ... Removing node-strip-ansi (4.0.0-1) ... Removing node-ansi-regex (3.0.0-1) ... Removing nodejs (10.23.1~dfsg-1~deb10u1) ... (Reading database ... 14507 files and directories currently installed.) Purging configuration files for npm (5.8.0+ds6-4+deb10u2) ... ##### 一度ログインしなおす ####### # npm run dev # いざコンパイル > @ dev /var/www/vue-laravel-spa > npm run development > @ development /var/www/vue-laravel-spa > mix Additional dependencies must be installed. This will only take a moment. Running: npm install vue-loader@^15.9.5 --save-dev --legacy-peer-deps npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.13 (node_modules/fsevents): npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"}) npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@2.3.1 (node_modules/chokidar/node_modules/fsevents): npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.3.1: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"}) Finished. Please run Mix again. # npm run dev # againとのことなので > @ dev /var/www/vue-laravel-spa > npm run development > @ development /var/www/vue-laravel-spa > mix 99% done plugins BuildOutputPlugin Laravel Mix v6.0.10 ✔ Compiled Successfully in 16791ms ┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬─────────┐ │ File │ Size │ ├───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼─────────┤ │ /js/app.js │ 1.4 MiB │ │ css/app.css │ 179 KiB │ └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴─────────┘成功しました
/public/js/app.js
と/public/css/app.css
が生成されました
- 投稿日:2021-01-23T19:00:00+09:00
ポートフォリオ ー店舗管理システム作ってみた
初めに
バックエンドをLaravel,フロントエンドをVue.jsを用いて実装しています。
この記事ではアプリ開発の説明や工夫した点を記載したいと思います。アプリの概要
実際に飲食店舗の従業員は活用することをイメージしながら作成した店舗管理システムです。
・店長の事務業務負荷
・実際に生じている店舗の問題点を解決できるようにすることをコンセプトとして作成しました。
「Cafe de Drip」という喫茶店で活用されることを想定しています。アプリURL:https://cafe-de-drip.herokuapp.com/
※ユーザー認証が必要なので閲覧できません....。GitHub:https://github.com/Tanaka-Kizuki/Store-management-system
実際に店舗で起きている問題点
◉勤怠管理システム(打刻式)がなくタイムカードもしくはシステム上に手打ち
→店長がシステム上に勤怠入力もしくは実績と入力に相違がないか確認・承認作業◉ノートを使った共有事項の伝達
→ノートを手書きで書く作業負荷◉日々の発注業務
→発注が出来る能力者が限られており、休みの日でも出勤もしくは遠隔発注上記問題点解決策(具体的なアプリ実装・機能)
機能一覧
◉ユーザー管理登録
○管理者権限
○新規登録(管理者のみ有効)
○ログイン、ログアウト機能
◉勤怠管理システム
○出退勤
○休憩開始、終了
○出退勤時刻、休憩時間より勤務時間の算出(15分繰り上げ)
○ユーザーの勤怠実積照合(ログイン従業員の指定月の勤務実積表示)
○日次勤怠照合(指定日に勤務していた従業員、勤務時間等表示)
◉コミュニケーションノート
○新規作成
○編集
○削除
◉発注システム
○アイテムの追加、編集
○発注(データベース登録)
○発注履歴の表示使用技術
◉フロントエンド
○HTML/CSS
○JavaScript
○Vue.js 4.3.1
◉バックエンド
○PHP 7.4.9
○Laravel 7.27.0
◉インフラ
○mysql 8.0.21
- 投稿日:2021-01-23T17:20:01+09:00
Laravelにおけるテストについて
ユニットテストとは?
関数やメソッドごとに行うテスト。単体テストともいう。
(逆にプログラム全体のテストを結合テストという)PHPUnitとは?
Laravelに標準で用意されている単体テストツール。
コマンドを打つことですべてのユニットテストを自動で実行してくれるユニットテストのメリット
1. 問題の早期発見
他の関数との結合度が高い場合などはユニットテストですべてを解決できるわけではないが、関数単体ではテストを行うことができる。2. ツールを使うことでテストを自動化できる
PHPUnitを使用することでコマンドを打つことで複数の単体テストを同時に実行してくれ、作業量が少なくて済む。3. テスト自体をコードとして残しておくこができる
ユニットテストはコードを書いて実行するので、コードを残しておけば同じテストを何度も利用することができる。テストの種類
テストには、UnitTest, FeatureTest, BrowserTestが存在する
UnitTest
/tests/Unit配下にテストを配置する。
一番粒度の細かなテスト。
Model, Policy, Middlewareなどのクラス一つにテストファイル一つが対応するように作成する。
その対象クラスのメソッド一つ一つを検証していく。FeatureTest
/tests/Feature配下にテストを配置する。
UnitTestより粒度が大きなテスト。1つのHTTPリクエスト単位でテストを実行する。
= ルーティングごとにテストファイルを作成する
= コントローラのアクションメソッドごとにテストするUnitTestでクラス内部を細かくテストし、FeatureTestでコントローラの動き全体(つまりリクエストを受けてからレスポンスを返すまで)をテストする。
1つのコントローラアクションに対応したテストクラス(ファイル)の中で、
・ログインした状態でアクセス時の動作
・未ログインアクセス時の動作
・検索パラメータ付けたアクセス時の動作
・ユーザに特定ロールを付けた状態の動作
など1つ1つのケースをテストケースとしてコードを書く。BrowserTest
/tests/Browser配下にテストを配置する。
実際にブラウザを使って画面にリクエスト、
ボタンをクリック、
マウスホバー、
フォーム送信などの操作をするテストをコードで実行できる。FeatureTestにさらに
・複数HTTPリクエストの遷移
・画面操作時のJsの動作
のような観点を加えてテストできるイメージ。Unit、FeatureはPHPUnitで動作するテストなのに対し、
BrowserTestはlaravel/duskというパッケージを使ったテスト。テストをしてみる
FeatureテストとUnitテストを試しながらPHPUnitの基本的な使い方を学んでいく。
テスト対象のコードの確認
テストの対象となるルーティング、コントローラ、モデルを例にとり確認しておく。
本に関するアプリケーション。マイグレーション
<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateBooksTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('books',function(Blueprint $table){ $table->id(); $table->string('author'); $table->string('title'); $table->string('description'); $table->integer('status')->default(\App\Book::Available); $table->integer('rent_count')->default(0); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('books'); }ルーティング
<?php use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; Route::resource('books','BookController');コントローラ
<?php namespace App\Http\Controllers; use App\Book; use Illuminate\Http\Request; class BookController extends Controller { public function index() { returnBook::all(); } public function store(Request $request) { $book = newBook(); $book->title = $request->title; $book->author = $request->author; $book->description = $request->description; $book->save(); return $book; } }モデル
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Book extends Model { }まずはテスト用データベースの作成
MySQLやPostgresとは別のインメモリのSQLiteデータベースを使用することで、テストするごとにデータが削除され無駄なデータが保存されない。
まず config/database.php の connections に以下の接続情報を追加する。
database.php
'sqlite_testing' => [ 'driver' => 'sqlite', 'database' => ':memory:', 'prefix' => '', ],そしてphpunit.xmlで、タグの中に、タグを使用すると、テスト時にenvファイルの設定を上書きすることができる。つまりテストのときは別のデータベースを利用することができるようになる。
<php> <server name="APP_ENV"value="testing"/> ・・・省略・・・ <!-- 以下を追記 --> <server name="DB_CONNECTION" value="sqlite_testing"/> </php>Featureテスト
Featureテストを用いてWebAPIのテストコードを実装してみる。
テストファイルの作成
$php artisan make:testBookTesttests/Featureディレクトリに、テストコードの雛形が作成される。ここにテストコードを実装していく。
テストコードを記述
以下は「/api/books」に正しくアクセスできるかを検証するコード
<?php namespaceTests\Feature; useIlluminate\Foundation\Testing\RefreshDatabase; useTests\TestCase; classBookTestextendsTestCase { useRefreshDatabase; publicfunctiontestFetchBook() { $response=$this->get('/api/books'); $response->assertStatus(200); } }getメソッドを使用することで第1引数に指定したパスにリクエストでき、戻り値がそのレスポンスとなる。
postメソッドでPOSTリクエストをすることも可能。その場合第2引数に送信するデータを配列形式で設定する。テストの検証
テストコード内のアサーションで検証することができる。
例1)ステータスコードの検証
$response->assertStatus(200);例2)JSONパラメータの検証
assertJsonFragment()メソッドを使用すると、引数に渡したJSONが、レスポンスに含まれているか検証する。
$response->assertJsonFragment([ 'title'=>'Laravel入門', 'author'=>'Lara太郎', 'description'=>'Laravel入門書です。' ]);テストの実行
以下のコマンドで実行可能
$php artisan testUnitテスト
Unitテストを使用して、単体テストを実装してみる。
テスト対象の追加
先ほどのBookモデルに、本の貸し出し・返却用のメソッドを追加する。
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Book extends Model { public const Available = 1; public const LoanedOut = 2; public function checkOut() { $this->increment('rent_count',1); $this->status=self::LoanedOut; $this->save(); } public function returnBook(){ $this->status=self::Available; $this->save(); } }Factory
Factoryとは?
Factoryはダミーレコードを生成できる機能。
以下の型によってダミーレコードとなるデータを生成する。「$factory->define」というメソッドにて、モデル(ダミーレコード)を生成する処理内容を設定する。
$factory->define(モデルクラス, function (Faker $faker) { 処理を用意する return [データ配列]; });defineメソッドは、第1引数に生成するモデルクラス、第2引数にクロージを用意する。
クロージャにはFaker\Genetaterクラスのインスタンスが渡されており、これを利用してフェイクデータを用意し、レコードに入れる値を連想配列にまとめてreturnする。
このreturnされた値を使ってモデルが生成され、データベースに保存される。Factoryを使用する
今回は、あらかじめ貸し出す本を登録しておくため、Factoryを使用して、booksテーブルにインサートしていく。
まず、Factoryファイルを作成。$php artisan make:factory BookFactory --model=Book--modelオプションで、ファクトリで生成するモデルを指定する。ここで指定したモデルが、ファクトリ内で定義される。
このモデルクラスを指定しないと、ファクトリでデータを生成しようとしても、エラーとなるため、必ず指定する。<?php /** @var \Illuminate\Database\Eloquent\Factory $factory */ use App\Book; use Faker\Generator as Faker; $factory->define(Book::class, function(Faker $faker){ return[ 'author'=>$faker->name, 'title'=>$faker->title.$faker->randomNumber().$faker->time(), 'description'=>$faker->paragraph, 'status'=>$faker->numberBetween(1,2), 'rent_count'=>$faker->randomNumber() ]; });カラム名をキーとして値を代入していく。$fakerとしている箇所はランダムな値が入る。
fakerの主なメソッド
Fakeメソッド 内容 randomNumber() ランダムな整数値を生成 numberBetween(min, max) min~maxまでの整数値を生成 ランダムなメールアドレスを生成 phone ランダムな電話番号を生成 name ランダムな人物名 sentence() ランダムな1文を生成 paragraph ランダムな1段落の文章を生成 ユニットテストの実装
ユニットテストのファイルを作成する。オプションで--unitをつけることでtests/Unitディレクトリに作成するファイルが格納される。
$php artisan make:test BookTest --unit<?php namespace Tests\Unit; use App\Book; use Illuminate\Foundation\Testing\RefreshDatabase; use Tests\TestCase; class BookTest extends TestCase { use RefreshDatabase; protected function setUp():void { parent::setUp(); // BookFactoryを使用してbookを100レコード用意する for($i=0; $i<100; $i++){ factory(Book::class)->create(); } } /** * 本の貸し出しテスト */ public function testCheckOut() { $book = Book::where('status',Book::Available)->first(); $count = $book->rent_count; $book->checkOut(); // 貸し出し回数が、元の+1になっていることを確認 $this->assertEquals($book->rent_count,$count+1); // ステータスが貸し出し中になっていることを確認 $this->assertEquals($book->status,Book::LoanedOut); } /** * 本の返却テスト */ public function testReturnBook() { $book = Book::where('status',Book::Available)->first(); $count = $book->rent_count; $book->returnBook(); // 返却時は、貸し出しが変化していないことを確認 $this->assertEquals($book->rent_count,$count); // ステータスが利用可能になっていることを確認 $this->assertEquals($book->status,Book::Available); } }(コード解説)
RefreshDatabaseをトレイトしておくと、テスト前に未実行のマイグレーションファイルを実行し、テスト後データベースを初期化してくれる。
use RefreshDatabase;setUpメソッドはテストが始まる前に必ず呼ばれるメソッドのため、ここでfactoryを発動しダミーレコードがテスト前にセッティングされるように設定する。
protected function setUp():void { parent::setUp(); // BookFactoryを使用してbookを100レコード用意する for($i=0; $i<100; $i++){ factory(Book::class)->create(); } }factory(モデル名::class)->createで実際にダミーレコードを生成することができる。
つまり、上記で書いたfactoryファイルはダミーなデータを準備する段階で実際にダミーレコードを生成するのはこの宣言があって初めて実行される。factory(Book::class)->create();ここでは設定されていないが、tearDown()メソッドは、テスト終了時に毎度呼ばれるメソッドで、各テスト後の後処理に使用する。
まとめ
一見複雑に見えるが、やっていることは
1. テストファイルの作成
2. テストしたいデータをテストファイル内で準備する
3. 「asser~メソッド」で検証する
4. テストの実行ただこれだけの実はシンプルな処理しかしていない。
コードが長くなって分かりづらいかもしれないが、上の4つに分解すると理解しやすい。参考
- 投稿日:2021-01-23T15:48:04+09:00
Laravel 7以降のBladeコンポーネントはどう便利になったか
Laravel 7で、Bladeコンポーネントが拡張された。最初知ったときは、わざわざHTML風の
文法になっているのがいまいちだと感じたが、よく調べてみるとしっかりとした意図のあ
る仕様で、便利そうだった。どう変わったのか、またどう便利になったのか、具体的に紹介する。
参考:
リリースノート 7.x Laravel の"Bladeコンポーネントタグと向上"以下。変更点
ほかにも細かいものはあるが、主に以下の3つが重要だろう。
1.
<x-.../>
とHTMLタグのように呼び出せるようになったHTMLタグのように書くことができる。この呼び出し方では、自動的に
resources/views/components
以下のビューがコンポーネントとして呼び出される。渡すデータも、HTML属性のように表記できる。PHPの変数を渡したい場合は、先頭に
:
を付加する。{{-- Laravel 6まで --}} @component('form.input.number', ['name' => 'foo', 'min' => 0, 'max' => $max]) @endocmponent{{-- Laravel 7から --}} <x-input.number name="foo" min="0" :max="$max" />あるいは、
<x-input.number name="foo" min="0" :max="$max"> </x-input.number>2. HTML属性を簡単に渡せる"属性バッグ"が追加された
渡した変数を
{{ $attributes }}
だけで表示できる。下記の例のようにオプションとして使う場合にはより有用だ。resources/views/form/input/number.blade.php{{-- Laravel 6まで --}} <input type="number" name="{{ $name }}" @isset ($min) min="{{ $min }}" @endisset @isset ($max) max="{{ $max }}"@endisset value="{{ old($name) }}">resources/views/components/input/number.blade.php{{-- Laravel 7から --}} <input type="number" {{ $attributes }} value="{{ old($name) }}">3. Bladeビューとしてではなく、PHPのクラスとしてコンポーネントを表現するコンポーネントクラスを作れるようになった
これにより、コンポーネントが受け取るデータを明示することができるようになったのが非常に強力だ。
ほかにも、コンポーネントクラスに実装したメソッドをビュー側で変数として使用することができる。
app/View/Components/Input/Number.php<?php namespace App\View\Components\Input; use Illuminate\View\Component; class Number extends Component { /** @var string */ public $name; /** * インスタンスを生成する * * @param string $name * @return void */ public function __construct(string $name) { $this->name = $name; } /** * ビューを取得する * * @return \Illuminate\Contracts\View\View */ public function render() { return view('components.input.number'); # あるいは、文字列をそのまま返すこともできる } }まとめ: どう便利になったのか
上記のサンプルコードを見れば大体わかると思うが、もう少し説明すると、
- 呼び出し側はHTML風の文法のおかげで、短くわかりやすく書けるようになった。
- コンポーネント側は属性バッグのおかげで、オプションの属性を短くわかりやすく書けるようになった。
- コンポーネントクラスのおかげで、コンポーネントが受け取るデータを型を含めて明示することができるようになった。
- また、関連するロジックをコンポーネントクラスに入れることができるようになった。
といったところだろうか。
ただ個人的には、コンポーネントクラスはそこまで必要ないと思っている。追加の属性値に関しては属性バッグでシンプルに書けるようになり、また紹介しなかったが
@props()
を使うことでも受け取るデータの名前に関しては明示できるようになっているためだ。どちらにしてもメリットが強力で、デメリットも特に見当たらないため、Laravel 7以上が使える環境であれば、Bladeコンポーネントの新機能を使わない理由はなさそうだ。
参考:
Bladeテンプレート 7.x Laravel の"コンポーネント"以下。この記事のライセンス
この文書はCC BY(クリエイティブ・コモンズ表示4.0国際ライセンス)で公開する。この文書内のサンプルコードはMITライセンスで公開する。
- 投稿日:2021-01-23T15:26:14+09:00
laravel with で limit take
laravel で with を使って関連モデルを読み込んだとき、
limit , take で取得数を制限したい場合があるしかし、普通にやっても動かないので、
https://github.com/staudenmeir/eloquent-eager-limit
を使おう
インストール
composer require staudenmeir/eloquent-eager-limit:"^1.0"database.php//以下の箇所をすべて false に変更 'strict' => false,キャッシュを消して有効に
php artisan config:clear php artisan config:cache使い方
Autotweet -> Social -> Answer
って感じで関連付けしたとき、
Answerを3件だけ取得したいSocial.phpclass Social extends Model { use \Staudenmeir\EloquentEagerLimit\HasEagerLimit; public function answer() { return $this->hasMany('App\Answer'); }Answer.phpclass Answer extends Model { use \Staudenmeir\EloquentEagerLimit\HasEagerLimit;こんな感じ
使い方は
HogeController.php$tweet = Autotweet::query()//単数形 User ->with([ 'social' => function ($q) { $q->with( [ 'answer' => function ($q2) { $q2->orderBy('id','DESC')->take(3);//3件のみ取得 }, ] ); }, ]) ->get();で使えます。
注意点
・database.php の strict を変更すること
・関連付けするモデル(この場合はSocial.phpとAnswer.php)両方に
use \Staudenmeir\EloquentEagerLimit\HasEagerLimit;
を設定することが大事
- 投稿日:2021-01-23T14:51:11+09:00
【PHP】Docker環境にphpMyadminを導入する
手順
docker-compose.ymlにphpMyadominのコンテナを追記します。
docker-compose.yml#docker-compose.ymlのバージョン version: "3.8" #docker volumeの設定 volumes: docker-volume: #services以下に各コンテナの設定を書く services: #Webサーバーのコンテナ web: image: nginx:1.18 ports: - "8000:80" depends_on: - app volumes: - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf - .:/var/www/html #アプリケーションのコンテナ app: build: ./docker/php volumes: - .:/var/www/html #データベースのコンテナ db: image: mysql:5.7 ports: - "3306:3306" environment: MYSQL_DATABASE: db_name MYSQL_USER: db_user MYSQL_PASSWORD: db_password MYSQL_ROOT_PASSWORD: root TZ: "Asia/Tokyo" volumes: - docker-volume:/var/lib/mysql # phpMyadominのコンテナ作成 phpmyadmin: image: phpmyadmin/phpmyadmin depends_on: - db environment: - PMA_ARBITRARY=1 - PMA_HOSTS=db - PMA_USER=db_user - PMA_PASSWORD=db_password ports: - "8080:80" volumes: - ./docker/phpmyadmin/sessions:/sessionsコードの下部にある
# phpMyadominのコンテナ作成
からが追記する箇所です。
portsを8080に設定しているので、localhost:8080
でphpmyadminの管理画面にアクセスできるように設定しています。
また、volumesにある./docker/phpmyadmin/sessions:/sessions
ではセッション情報をボリュームに設定して永続化するようにします。補足
参考までに作ってみた環境
↓https://github.com/yuyaamano23/Laravel_Docker_practice/tree/github-open
ちなみに僕は以下の記事を参考にphp+mysql+nginxの環境を構築しました。神記事です。
絶対に失敗しないDockerでLaravel+Vueの実行環境(LEMP環境)を構築する方法〜前編〜
絶対に失敗しないDockerでLaravel6.8+Vueの実行環境(LEMP環境)を構築する方法〜後編〜
Docker Composeでphpmyadminを導入する各々構築したDocker環境のプロジェクトにあるdocker-compose.ymlnに追記していただければ良いと思います。