20210509のMySQLに関する記事は11件です。

実務未経験がSNSサービスを作ってみた

はじめに 私は2020年8月からphp、11月頃からLaravelを勉強し始めました。今までは、勉強の中で、ECサイトや掲示板などを作成して1からCRUD処理ができるレベルになりました。今回は、学習のアウトプットと自分の思い描くサービスを作ってみたいと考え、SNSサービスを作成した記録を残します。 環境 制作期間は1ヶ月ほど  勉強時間は最低平日2時間、休日6時間 htmlとcssは最低限しか分からないです。 スキル MAMP/php/Laravel5.5/mysql/git/vim/linux 作ってみたもの WEBアプリ名 Destiny 保険 目的 保険が大好きで優柔不断な日本人に後悔のない保険選びをサポートすること 内容 保険の悩みを共有するSNSです。会員登録したユーザーは保険に対して抱えている悩みを投稿することができます。他のユーザーからコメントでアドバイスを受けることができます。プロフィール欄も充実しているためユーザーが保険のプロなのか?同じような悩みをかける主婦なのか?すぐに分かる事ができます。気になったユーザーがいた場合はチャット機能で2人だけの会話を頼むことができます。より深い内容の提案を受けることを期待できます。 機能 全ユーザー ・投稿を見ることができる ・コメントに「いいね」評価をいただけた数ランキングを見ることができる ・管理者にお問い合わせをすることができる ・悩み投稿を検索することができる。 会員登録したユーザーのみ ・保険に対する悩みを投稿することができる ・ユーザーの投稿にコメント(アドバイス)をすることができる。 ・他のユーザーとチャットすることができる ・投稿についたコメントを確認することができる ・プロフィール機能 投稿したユーザーのみ ・投稿を削除することができる ・投稿のコメントに「いいね」をすることができる 管理者のみ ・全ユーザー確認機能 ・全お問い合わせ確認機能 ・対応したお問い合わせのステータスを変更機能 トップ画面 悩み投稿の一覧ページ 保険の投稿をクリックすると詳細画面 保険の悩みを投稿するページ 個人的に気に入っている点 ・フッター 黒と白を貴重にしたシンプルなデザインと人生初のcopyrightがかっこいい、、 ・デフォルトのプロフィール写真 プロフィール写真を設定していないとかわいいピカチュウのシルエット写真になります。遊び心を入れました。 ・「Destiny 保険」というサービス名 ・コメントにいいねをたくさんいただいたランキング Fontawesomeでcrownのロゴを使いました! 色とロゴが合ってて抜群に好き ・チャット機能 反省点 各作業にかかった時間計測していない fatコントローラー cssがきたない サービスに導入したいこと 提案書作成機能 レスポンシブ対応 非同期通信 リファクタリング サーバーに公開する流れ xserverで公開する際に参考にした記事を参考に公開しました。 少しだけ躓いた場面があります。 ①ssh接続時  公開鍵の権限を600に変更すること サーバーIDはメールで送られてくるIDとは違うこと(エックスサーバーと契約すると様々なIDがあるため勘違いしてログインに失敗しました) ssh接続時に参考にした記事 ②サーバー公開後にローカルからimageデータをリモートサーバーに移す時 FTPのログインするときに設定を何度も間違えたせいで、ログインできなくなりました。 xserver公式のFTPに関するQ&A そのため、VSCodeでRemote sshで接続して、ローカルにあるimageフォルダーをドラッグアンドドロップで移動させました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Docker環境でmysqlを二つ立ち上げる方法

テスト環境と本番環境でDBを分けたいときがあります そんな時にDockerでDBを二つ立ち上げる方法について記載します Docker file まずは結論 version: "3.8" services: app: build: ./your/app/dockerfile depends_on: - mysql - test_mysql command: execute command ports: - '8000:8000' - '8080:8080' mysql: build: ./your/mysql/image/path environment: MYSQL_DATABASE: your_db MYSQL_USER: user MYSQL_PASSWORD: password MYSQL_ROOT_PASSWORD: password ports: - "3306:3306" - "33060:33060" volumes: - mysql-data:/var/lib/mysql:cached phpmyadmin: image: phpmyadmin/phpmyadmin environment: - PMA_ARBITRARY=1 - PMA_HOST=mysql - PMA_USER=user - PMA_PASSWORD=password depends_on: - mysql links: - mysql ports: - 8090:80 volumes: - /sessions - ./tools/phpMyAdmin/php.ini:/usr/local/etc/php/php.ini test_mysql: build: ./your/test/mysql/image/path environment: MYSQL_DATABASE: your_test_db MYSQL_USER: user MYSQL_PASSWORD: password MYSQL_ROOT_PASSWORD: password ports: - "3307:3306" volumes: - test-mysql-data:/var/lib/mysql:cached test_phpmyadmin: image: phpmyadmin/phpmyadmin environment: - PMA_ARBITRARY=1 - PMA_HOST=test_mysql - PMA_USER=user - PMA_PASSWORD=password depends_on: - test_mysql links: - test_mysql ports: - 8091:80 volumes: - /sessions - ./tools/phpMyAdmin/php.ini:/usr/local/etc/php/php.ini volumes: mysql-data: test-mysql-data: 実行方法 注意点 すでにある環境が立ち上げ済みで、dockerファイルを追記していたら、以下のコマンドで、既存のDBデータをすべて消して再度イメージをビルドしなおさないと私の環境ではエラーになりました 絶対に本番環境ではやらないでください。データがすべて消えます //イメージとデータの削除 docker-compose down --rmi all --volumes //ビルド docker-compose build --no-cache //コンテナ立ち上げ docker-composer up 本番環境:http://localhost:8090/ テスト環境:http://localhost:8091/ で二つphpMyAdminが立ち上がっていると思います 質問や間違いがあればコメントからお願いします!  宣伝 ツイッターもやってます 技術や製品開発に関する事などを呟いてますので、フォローお願いします https://twitter.com/wkyIghw8MlLpyJE
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

商品追加機能の実装について【NULL】

はじめに はじめまして! webエンジニア転職を目指して三ヶ月が経ちました。 スクールでは共同開発が始まり、カート機能を実装しております。 そこで、終盤において商品追加機能を担当し、 復習&アウトプットも兼ねてご覧の皆さんに共有したいと思い、記事投稿に至ります! 至らぬ点が多々あるとは思いますが、何かの実装の参考になれば幸いです。? 0, 目次 1, 概要 2, 環境 3, 参考テーブル 4, 【null値許容】の設定 参考にしたサイト 1, 概要 DB確認(Tinker) 本記事では、前回実装した商品データを元にDBへnull値も含めて追加していきたいと思います。 前回:【Laravel】商品追加機能の実装について 今回:↓ ・ id:16 の商品を追加 ・ null設定3箇所 2, 環境 macOS Big Sur 11.2.2  Apache 2.4.46  MySQL 5.7  PHP 7.2.34 Laravel 5.8   実は今回、共同開発において VirtualBoxを用いたVagrantによる仮想開発環境で統一したかったのですが、 投稿主のmacが最近出たばかりのM1チップが搭載されております。 そして、悲しいことに当時(2月中旬)はVirtualBoxなどバージョンが追いついておらず、 仕方なくAWS(Could9)での環境設定を余儀なくされました。。 3, 参考テーブル テーブルは事前に作ってあると思います。 今回の内容では、こちらのファイルの中身を変更する必要はありません。 カラム名など確認する際の参考として一応載せておきます。 ××××_××_××_××××××_create_m_products_table.php <?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateMProductsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('m_products', function (Blueprint $table) { $table->increments('id'); $table->string('product_name', 64); $table->unsignedInteger('category_id'); $table->integer('price'); $table->string('description', 256); $table->unsignedInteger('sale_status_id'); $table->unsignedInteger('product_status_id'); $table->timestamp('regist_date'); $table->unsignedInteger('user_id'); $table->char('delete_flag', 1)->default(0); $table->foreign('user_id')->references('id')->on('m_users')->onDelete('cascade'); $table->foreign('category_id')->references('id')->on('m_categories')->onDelete('cascade'); $table->foreign('sale_status_id')->references('id')->on('m_sale_statuses')->onDelete('cascade'); $table->foreign('product_status_id')->references('id')->on('m_product_statuses')->onDelete('cascade'); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('m_products'); } } 4, 【null値許容】の設定 $ make:migration --table (作ったテーブル名) change_(作ったテーブル名)_table Created Migration: ××××_××_××_××××××_change_m_products_table これでchangeテーブルが作成されました。 ファイルを開いたら、 ▶︎upメソッド ▶︎downメソッド それぞれにnull許容(変更)の設定をしていきます。 ××××_××_××_××××××_change_m_products_table <?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class ChangeMProductsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::table('m_products', function (Blueprint $table) { // それぞれのカラムにNULLを許容 $table->unsignedInteger('category_id')->nullable()->change(); $table->unsignedInteger('sale_status_id')->nullable()->change(); $table->unsignedInteger('product_status_id')->nullable()->change(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::table('m_products', function (Blueprint $table) { //カラム削除 $table->dropColumn(['category_id']); $table->dropColumn(['sale_status_id']); $table->dropColumn(['product_status_id']); }); } } と、ここでエラーが出てくるかと思います。 こちらは別記事でまとめてます。 簡単に解決できますので、こちらを参考にしてみてください!↓ 参考:composer.jsonのエラーについて 以上でnull値としてDBに登録できたかと思います! 参考にしたサイト •  Laravel 5.8 データベース:マイグレーション •  LaravelのMigrateでカラムにNULLを許容したり許容しなかったり変更 •  Laravel MySQL 既存カラムのNULL許容とデフォルト値をNULLに設定する
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails 6 + MySQL8.0 + Docker 環境でMySQLを日本語化

初学者向けの記事です。 私の備忘録として残します。 docker-compose.yml上で2つのことをしようとしてハマった ・「MySQL8.0の認証方法に対応」 ・「MySQLの文字コードを変更」 これを同時にやろうとしてハマりました。 やりたいこと1 「MySQLの認証方法変更」 MySQL8.0から command: --default-authentication-plugin=mysql_native_password を追加する必要がありました。 コード全体を確認 (docker-compose.yml) version: '3' services: db: image: mysql:8.0 command: --default-authentication-plugin=mysql_native_password volumes: - ./src/db/mysql_data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: password web: build: . command: bundle exec rails s -p 3000 -b '0.0.0.0' volumes: - ./src:/app ports: - "3000:3000" depends_on: - db やりたいこと2 MySQLの文字コードをutf8mb4に変えたい また、dockerでmysqlの文字コードを日本語対応のものに変更しようとすると、次のようなコマンドを打つ必要があるとわかりました。 (imageを引っ張ってくるとデフォルトの文字コードは「latin1」でした) command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci で、「commandを2つ書けば良いんだな」と思って調整していたのですが、うまくいきません。 というのも、docker-compose.ymlのcommandは「1つしか書けない」からなんですね。 Run a one-off command on a service 参考文献 思いついた解決策1(失敗):1つの長いcommandにする 下記リンクを参考に長い1つのcommandを作ろうと思いましたが失敗しました。 もう少し粘れば行ける気がするのですが、そもそも長いコマンドはあまり美しくないかも・・・と思って解決策2を試したところ、すんなり解決しました。 参考リンク 思いついた解決策2(成功):localのmy.cnfをmysqlのdbコンテナにコピーする まずlocalの適当な場所にmy.cnfを作ります。 そこにdbコンテナのmy.cnfをコピーして、先ほどコマンドでやりたかったことを追記します。 そしてdocker-compose.ymlを編集 1、commandを削除(全てmy.cnfに書いたので) 2、volumesに下記の一行追記 - ./src/db/my.cnf:/etc/mysql/my.cnf コード全体を確認 (docker-compose.yml) version: '3' services: db: image: mysql:8.0 volumes: - ./src/db/mysql_data:/var/lib/mysql - ./src/db/my.cnf:/etc/mysql/my.cnf environment: MYSQL_ROOT_PASSWORD: password web: build: . command: bundle exec rails s -p 3000 -b '0.0.0.0' volumes: - ./src:/app ports: - "3000:3000" depends_on: - db おわり これで無事文字コードの置き換えとMySQL8.0の認証を同時に行うことができました。 Rails 6 + MySQL8.0 + Dockerで開発をすれば誰でもこの状況になる気がするので、みなさん普通に解決してるんですよね。 私は1時間以上かかりました。 これからも精進します。 何か間違いがあればご指摘いただけますと幸いです。 備考 docker-compose.ymlを書き換えた時はdocker-compose downとupだけで動作確認できます。 私はよくわからなくて途中まで毎回buildしていました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【migrationエラー】RuntimeException : Changing columns for table...の解決法

エラー文 RuntimeException : Changing columns for table "(テーブル名)" requires Doctrine DBAL; install "doctrine/dbal". 原因 このようなエラーはnull設定などでカラム削除時に起きてしまうものだと思われます。 Laravelの公式にも書いてありますが、 カラムを削除する際はマイグレーションする前に「composer.json」ファイルにとある依存パッケージを追加する必要があるとのことです。 追加して更新するだけなので、軽く以下にまとめます。 解決法 エラー文通り以下の作業を行います。 ① 「composer.json」ファイルにdoctrine/dbalを追加 composer.json { "name": "laravel/laravel", "type": "project", "description": "The Laravel Framework.", "keywords": [ "framework", "laravel" ], "license": "MIT", "require": { "php": "^7.1.3", "fideloper/proxy": "^4.0", "laravel/framework": "5.8.*", "laravel/tinker": "^1.0", "doctrine/dbal": "v2.4.2" <-これ }, "require-dev": { ---以下省略--- あとはcomposerをアップデートするだけ。 composer update 以上で正常にマイグレーションできるかと思います。 一応自分用メモのつもりですが、何かの参考になれば幸いです! 参考にしたサイト •  composer =laravelに依存関係をインストール •  Laravel 5.8 データベース:マイグレーション
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MySQLのDB確認・作成コマンド【一覧】

mysqlに関するコマンドを毎度のこと調べてたので、『mysqlならここからコピペや!!』って感じで、自分用に見やすくまとめてみました。 要するに“コピペ用”です? MySQL接続コマンド ? MySQLのサービスに入る mysql -u root -p ? 入れなかった場合 //mysqlの起動 sudo service mysqld start //MySQLの再起動 sudo service mysqld restart //MySQLの確認 sudo service mysqld status //MySQLの停止 sudo service mysqld stop MySQLデータベースの作成 ・ 削除 ? データベースの作成と削除 //データベースの作成 create database データベース名; //データベースの削除 drop database データベース名; ? その他の作成と削除 //テーブルの作成 create table テーブル名(カラム名 データ型, カラム名 データ型); //テーブルの削除 drop from テーブル名; //データの削除 delete from テーブル名; (注意) ハイフン( - )が入るものは作れない。 アンダーバー( _ )ならOK。 MySQLデータベース確認 ? データベース名一覧表示(テーブルも同様) show databases; ? 現在のデータベース表示 select database(); ? データベース内のテーブル一覧表示 show tables from データベース名; ? データベース内のカラム一覧表示 show columns from テーブル名 from データベース名; MySQL格納データ確認 ? データベースに接続する use データベース名; ? 格納データを表示する select * from テーブル名; 自分用にまとめたものですが、何かの役に立てば幸いです!?
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Laravel】商品追加機能の実装について

はじめに はじめまして! webエンジニア転職を目指して三ヶ月が経ちました。 スクールでは共同開発が始まり、カート機能を実装しております。 そこで、終盤において商品追加機能を担当し、 復習&アウトプットも兼ねてご覧の皆さんに共有したいと思い、記事投稿に至ります! 至らぬ点が多々あるとは思いますが、何かの実装の参考になれば幸いです。? 目次 1, 完成品 2, 環境 3, 使用するソースコード   3-① Route   3-② Controller   3-③ View   3-④ Migration   3-⑤ Model 4, 各実装の説明 ①〜⑤ 参考にしたサイト まとめ 1, 完成品 ① 完成画面 ② DB確認(Tinker) 2, 環境 macOS Big Sur 11.2.2  Apache 2.4.46  MySQL 5.7  PHP 7.2.34 Laravel 5.8   実は今回、共同開発において VirtualBoxを用いたVagrantによる仮想開発環境で統一したかったのですが、 投稿主のmacが最近出たばかりのM1チップが搭載されております。 そして、悲しいことに当時(2月中旬)はVirtualBoxなどバージョンが追いついておらず、 仕方なくAWS(Could9)での環境設定を余儀なくされました。。 3, 使用するソースコード 3 - ① Route web.php <?php /* |-------------------------------------------------------------------------- | Web Routes |-------------------------------------------------------------------------- | | Here is where you can register web routes for your application. These | routes are loaded by the RouteServiceProvider within a group which | contains the "web" middleware group. Now create something great! | */ Route::get('/', function () { return view('welcome'); }); //商品追加 Route::get('newAdd', 'NewAddController@index')->name('newAdd.index'); Route::post('newProduct', 'NewAddController@store')->name('newProduct.post'); 3 - ② Controller NewAddController <?php namespace App\Http\Controllers; use App\User; use App\Models\Product; use App\Models\Category; use App\Models\ProductStatus; use App\Models\Sale; use Illuminate\Http\Request; use App\Http\Requests\ProductRequests; use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\Auth; use App\Http\Controllers\Controller; class NewAddController extends Controller { public function index(Request $request) { return view('products.newAdd', [ 'user' => Auth::user(), 'categories' => Category::all(), 'products_status' => ProductStatus::all(), 'sales' => Sale::all(), ]); } public function store(ProductRequests $request) { $newProduct = new Product; $newProduct->product_name = $request->product_name; $newProduct->description = $request->description; $newProduct->price = $request->price; $newProduct->category_id = $request->category_id; $newProduct->product_status_id = $request->product_status_id; $newProduct->sale_status_id = $request->sale_status_id; $newProduct->user_id = Auth::user()->id; $newProduct->save(); return view('welcome'); } } 3 - ③ View newAdd.blade.php @extends('layouts.app') @section('content') <main> <div class="page-header mt-5 text-center"> <h2>商品追加</h2> </div> <div class="row mt-5 mb-5"> <div class="col-sm-5 mx-auto"> <form method="POST" action="{{ route('newProduct.post') }}"> @csrf <div class="form-group-sm clearfix"> <label for="formGroupExampleInput2" class="mt-3 mb-0">商品名</label> <div class="product-info width-control"> <input type="text" name="product_name" class="content-half-width form-control-sm d-inline"> <!-- @if ($errors->has('product_name')) <div class="row justify-content-center"> <div class="cal-xs-4"> <span style="color:red">{{ $errors->first('product_name') }}</span> </div> </div> @endif --> </div> </div> <div class="form-group-sm clearfix"> <label for="formGroupExampleInput2" class="mt-3 mb-0">商品説明</label> <div class="product-info width-control"> <textarea name="description" class="content-width form-control-sm"></textarea> <!-- @if ($errors->has('description')) <div class="row justify-content-center"> <div class="cal-xs-4"> <span style="color:red">{{ $errors->first('description') }}</span> </div> </div> @endif --> </div> </div> <div class="form-group-sm clearfix"> <label for="formGroupExampleInput2" class="mt-3 mb-0">価格</label> <div class="product-info width-control"> <input type="text" name="price" class="content-half-width form-control-sm d-inline"> <!-- @if ($errors->has('price')) <div class="row justify-content-center"> <div class="cal-xs-4"> <span style="color:red">{{ $errors->first('price') }}</span> </div> </div> @endif --> </div> </div> <div class="form-group-sm clearfix"> <label for="formGroupExampleInput2" class="mt-3 mb-0">商品カテゴリー</label> <div class="product-info width-control"> <select class="content-half-width form-control-sm d-inline" id="changeSelect" name="category_id" onchange="entryChange2();"> <option value="">未選択</option> @foreach ($categories as $category) <option value="{{ $category->id }}">{{ $category->category_name }}</option> @endforeach <!-- @if ($errors->has('category_id')) <div class="row justify-content-center"> <div class="cal-xs-4"> <span style="color:red">{{ $errors->first('category_id') }}</span> </div> </div> @endif --> </select> </dov> </div> <div class="form-group-sm clearfix"> <label for="formGroupExampleInput2" class="mt-3 mb-0">商品状態</label> <div class="product-info width-control"> <select class="content-half-width form-control-sm d-inline" id="changeSelect" name="product_status_id" onchange="entryChange2();"> <option value="">未選択</option> @foreach ($products_status as $product_status) <option value="{{ $product_status->id }}">{{ $product_status->product_status_name }}</option> @endforeach <!-- @if ($errors->has('product_status_id')) <div class="row justify-content-center"> <div class="cal-xs-4"> <span style="color:red">{{ $errors->first('product_status_id') }}</span> </div> </div> @endif --> </select> </dov> </div> <div class="form-group-sm clearfix"> <label for="formGroupExampleInput2" class="mt-3 mb-0">販売状態</label> <div class="product-info width-control"> <select class="content-half-width form-control-sm d-inline" id="changeSelect" name="sale_status_id" onchange="entryChange2();"> <option value="">未選択</option> @foreach ($sales as $sale) <option value="{{ $sale->id }}">{{ $sale->sale_status_name }}</option> @endforeach <!-- @if ($errors->has('sale_status_id')) <div class="row justify-content-center"> <div class="cal-xs-4"> <span style="color:red">{{ $errors->first('sale_status_id') }}</span> </div> </div> @endif --> </select> </dov> </div> <div class="text-center mt-5"> <button type="submit" class="btn btn-primary w-50">追加</button> <p class="mt-5"> <a href="#" class="text-primary d-inline">商品一覧</a> </p> </div> </form> </div> </div> </main> @endsection 3 - ④ Migration ××××_××_××_××××××_m_products_table.php <?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateMProductsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('m_products', function (Blueprint $table) { $table->increments('id'); $table->string('product_name', 64); $table->unsignedInteger('category_id'); $table->integer('price'); $table->string('description', 256); $table->unsignedInteger('sale_status_id'); $table->unsignedInteger('product_status_id'); $table->timestamp('regist_date'); $table->unsignedInteger('user_id'); $table->char('delete_flag', 1)->default(0); $table->foreign('user_id')->references('id')->on('m_users')->onDelete('cascade'); $table->foreign('category_id')->references('id')->on('m_categories')->onDelete('cascade'); $table->foreign('sale_status_id')->references('id')->on('m_sale_statuses')->onDelete('cascade'); $table->foreign('product_status_id')->references('id')->on('m_product_statuses')->onDelete('cascade'); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('m_products'); } } 3 - ⑤ Model Product.php <?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class Product extends Model { protected $table = 'm_products'; public $timestamps = false; //商品追加のホワイトリスト protected $fillable = [ 'product_name', 'description', 'price', ]; // Userモデルを親に持つことを明記 public function user() { return $this->belongsTo('App\User'); } // Categoryモデルを親に持つことを明記 public function category() { return $this->belongsTo('App\Models\Category'); } // Saleモデルを親に持つことを明記 public function sale() { return $this->belongsTo('App\Models\Sale'); } // ProductStatusモデルを親に持つことを明記 public function productstatus() { return $this->belongsTo('App\Models\ProductStatus'); } } 他のモデルについては同様の処理(リレーション)のため、今回は割愛させて頂きます。?‍♂️ 当時の私は、下記サイトを参考に実装していました。 参考 : リレーションについて 4, 各実装の説明 ①〜⑤ 4 - ① Route web.php //商品追加 Route::get('newAdd', 'NewAddController@index')->name('newAdd.index'); Route::post('newProduct', 'NewAddController@store')->name('newProduct.post'); こちらでは Route::getでViewを呼び出しています。(indexメソッド) Route::postでDBへの登録をしています。(storeメソッド) それぞれメソッド、命名など異なりますので、読み間違え等に気をつけましょう。 4 - ② Controller NewAddController.php public function index(Request $request) { return view('products.newAdd', [ 'user' => Auth::user(), 'categories' => Category::all(), 'products_status' => ProductStatus::all(), 'sales' => Sale::all(), ]); } 完成品を確認して頂くと、[カテゴリー] [商品状態] [販売状態] が選択になっています。 なので、indexメソッドでは各Modelを通して 登録する [ユーザー情報] や選択肢で表示させるための [3つの情報] を取得し、Viewに渡します。 また、今回はそこまで複雑な処理ではないため上のように記述しましたが、 以下のようにcompact関数を使っても問題なく渡すことができます! NewAddController public function index(Request $request) { $user = Auth::user(); $categories = Category::all(); $products_status = ProductStatus::all(); $sales = Sale::all(); return view('products.newAdd', compact('categories', 'user', 'sales', 'products_status')); } 次にstoreメソッドですが、 NewAddController public function store(ProductRequests $request) { $newProduct = new Product; $newProduct->product_name = $request->product_name; $newProduct->description = $request->description; $newProduct->price = $request->price; $newProduct->category_id = $request->category_id; $newProduct->product_status_id = $request->product_status_id; $newProduct->sale_status_id = $request->sale_status_id; $newProduct->user_id = Auth::user()->id; $newProduct->save(); return view('welcome'); } public function store(ProductRequests $request) こちらの ProductRequests はフォームリクエストによるバリデーションをかけています。 今回の実装ではバリデーションについての解説は入れてませんので、 Request に書き換えてもらってOKです! $newProduct = new Product; ここの一文は「これからProductモデルに新しい値を追加していくよー」っていう感じです。笑 あとは $newProduct という変数に画面で入力(選択)した値が格納されていくようになっています。 よくエラーが起きてしまう原因...?↓↓↓ <?php namespace App\Http\Controllers; use App\User; use App\Models\Product; use App\Models\Category; use App\Models\ProductStatus; use App\Models\Sale; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use App\Http\Controllers\Controller; Controller上部ではモデルやリクエストインスタンスを持ってきているので、 ここが一つでも抜けていると does not exit エラーが起きてしまいます...。 気が抜けないですね。。 5 - ③ View Viewについては 「入力値」と「選択値」の2種類があるので、分けて説明していきます。 と、その前に... <form method="POST" action="{{ route('newProduct.post') }}"> フォームタグでPOST送信の設定を忘れずに。 action="{{ route( ' 命名したルート名 ' ) }}" でルーティングしてあげます! ↓↓ 入力値 ↓↓ newAdd.blade.php「入力値」 <div class="form-group-sm clearfix"> <label for="formGroupExampleInput2" class="mt-3 mb-0">商品名</label> <div class="product-info width-control"> <input type="text" name="product_name" class="content-half-width form-control-sm d-inline"> <!-- @if ($errors->has('product_name')) <div class="row justify-content-center"> <div class="cal-xs-4"> <span style="color:red">{{ $errors->first('product_name') }}</span> </div> </div> @endif --> </div> </div> ここはControllerで指定したnameと一致させるための中にそのまま同じnameを入れてあげます。 フォームタグで囲ってあるので、あとは上記のようにHTMLで入力欄を作ればOKです! if文以降はエラー時のバリデーションを設定してます。 不要でしたら削除しても構いません。 ↓↓ 選択値 ↓↓ nweAdd.blade.php「選択値」 <div class="form-group-sm clearfix"> <label for="formGroupExampleInput2" class="mt-3 mb-0">商品カテゴリー</label> <div class="product-info width-control"> <select class="content-half-width form-control-sm d-inline" id="changeSelect" name="category_id" onchange="entryChange2();"> <option value="">未選択</option> @foreach ($categories as $category) <option value="{{ $category->id }}">{{ $category->category_name }}</option> @endforeach <!-- @if ($errors->has('category_id')) <div class="row justify-content-center"> <div class="cal-xs-4"> <span style="color:red">{{ $errors->first('category_id') }}</span> </div> </div> @endif --> </select> </dov> </div> 5 - ④ Migration 使用したソースコード参照 5 - ⑤ Model Product.php //商品追加のホワイトリスト protected $fillable = [ 'product_name', 'description', 'price', ]; $fillableで書き換えれるように設定しましょう。 ここでは使いませんが、$guardedはその逆です。 Product.php // Userモデルを親に持つことを明記 public function user() { return $this->belongsTo('App\User'); } // Categoryモデルを親に持つことを明記 public function category() { return $this->belongsTo('App\Models\Category'); } // Saleモデルを親に持つことを明記 public function sale() { return $this->belongsTo('App\Models\Sale'); } // ProductStatusモデルを親に持つことを明記 public function productstatus() { return $this->belongsTo('App\Models\ProductStatus'); } 各リレーションを行っています。 詳しくは下記リンクを参考に。 個人的にすごく分かりやすかったのでオススメします! 参考 : リレーションについて 参考にしたサイト •  DBの操作について(挿入) まとめ 以上で商品追加の機能を実装できるかと思います! DBへ新しいデータを登録する作業は初めてで、最初は色々記事などを漁りましたが、 ほとんど共同開発とスクール課題等で得た短い経験と知識ですんなり実装することができました! もっと記述を簡単にできたり、ここの書き方間違ってる等たくさんあるかとは思いますが、何かの参考になれば幸いです?‍♂️
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Djangoでfirst commitするまでのメモ

たまに作る時用にメモ 前提事項 プロジェクト名:hogehoge プロジェクトのディレクトリを作成 $ mkdir hogehoge Pycharmでプロジェクト作成 [New Project]を選択 Pure Pythonでプロジェクトを作成 ※Djangoでプロジェクトを作成するとプロジェクトディレクトリ名をプロジェクト名が一緒になってしまうから  ディレクトリ名はhogehogeでプロジェクト名はconfigにしておきたい ・Locationはさっき作ったディレクトリを指定 ・create main.py welcome scriptのチェックボックスは外しておく Preferenceを開く(⌘,) Project:hogehoge > Python Interpreter から以下のパッケージをインストール ※インストール時にはSpecify Versionにチェックをいれて、バージョン固定をする(個人のお好きにどうぞ) django django-environ mysqlclient Pycharm内のタブからTerminalを開き、以下のコマンドを実行 (hogehoge) user ​hogehoge % django-admin startproject config . (hogehoge) user ​hogehoge % touch .env (hogehoge) user ​hogehoge % mkdir config/settings (hogehoge) user ​hogehoge % mv config/settings.py config/settings/_base.py (hogehoge) user ​hogehoge % touch config/settings/local.py config/settings/production.py (hogehoge) user ​hogehoge % touch .gitignore .envを更新 空白とシングルクォーテーションは必要ないことに注意 .env # Secret Key SECRET_KEY=django-insecure-hjgklfd..... # MySQL settings DATABASE_URL=mysql://[username]:[password]@127.0.0.1:3306/[databasename]?charset=utf8mb4&sql_mode=TRADITIONAL,NO_AUTO_VALUE_ON_ZERO コンフィグファイルを更新する 細かいところは自分のお好きに settings/_base.py import os ############### # Build paths # ############### BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) PROJECT_NAME = os.path.basename(BASE_DIR) # Application definition INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', ] MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] ROOT_URLCONF = 'config.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [ os.path.join(BASE_DIR, 'templates'), ], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] WSGI_APPLICATION = 'config.wsgi.application' # Password validation # https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', }, { 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', }, { 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', }, { 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, ] # Internationalization # https://docs.djangoproject.com/en/3.2/topics/i18n/ LANGUAGE_CODE = 'ja' TIME_ZONE = 'Asia/Tokyo' USE_I18N = True USE_L10N = True USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/3.2/howto/static-files/ STATIC_URL = '/static/' STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')] STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') # Default primary key field type # https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' settings/local.py from ._base import * import environ # Read .env if exists env = environ.Env() env.read_env(os.path.join(BASE_DIR, '.env')) ##################### # Security settings # ##################### SECRET_KEY = env('SECRET_KEY') DEBUG = True ALLOWED_HOSTS = [] ############ # Database # ############ DATABASES = { 'default': env.db() } ########### # Logging # ########### LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'filters': { 'require_debug_false': { '()': 'django.utils.log.RequireDebugFalse', }, 'require_debug_true': { '()': 'django.utils.log.RequireDebugTrue', }, }, 'formatters': { 'django.server': { '()': 'django.utils.log.ServerFormatter', 'format': '[%(server_time)s] %(message)s a', }, 'verbose': { 'format': '%(levelname)s %(asctime)s %(module)s ' '%(process)d %(thread)d %(message)s' }, # 開発用 'develop': { 'format': '%(asctime)s [%(levelname)s] %(pathname)s:%(lineno)d ' '%(message)s' }, }, 'handlers': { 'console': { 'level': 'INFO', 'filters': ['require_debug_true'], 'class': 'logging.StreamHandler', 'formatter': 'verbose', }, 'django.server': { 'level': 'INFO', 'class': 'logging.StreamHandler', 'formatter': 'django.server', }, 'mail_admins': { 'level': 'ERROR', 'filters': ['require_debug_false'], 'class': 'django.utils.log.AdminEmailHandler' } }, 'loggers': { 'django': { 'handlers': ['console', 'mail_admins'], 'level': 'INFO', }, 'django.server': { 'handlers': ['django.server'], 'level': 'INFO', 'propagate': False, }, } } settings/production.py from ._base import * import environ # Read .env if exists env = environ.Env() env.read_env(os.path.join(BASE_DIR, '.env')) ##################### # Security settings # ##################### SECRET_KEY = env('SECRET_KEY') DEBUG = False ALLOWED_HOSTS = ['*'] ############ # Database # ############ DATABASES = { 'default': env.db() } ########### # Logging # ########### LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'filters': { 'require_debug_false': { '()': 'django.utils.log.RequireDebugFalse', }, 'require_debug_true': { '()': 'django.utils.log.RequireDebugTrue', }, }, 'formatters': { 'django.server': { '()': 'django.utils.log.ServerFormatter', 'format': '[%(server_time)s] %(message)s a', }, 'verbose': { 'format': '%(levelname)s %(asctime)s %(module)s ' '%(process)d %(thread)d %(message)s' }, # 開発用 'develop': { 'format': '%(asctime)s [%(levelname)s] %(pathname)s:%(lineno)d ' '%(message)s' }, }, 'handlers': { 'console': { 'level': 'INFO', 'filters': ['require_debug_true'], 'class': 'logging.StreamHandler', 'formatter': 'verbose', }, 'django.server': { 'level': 'INFO', 'class': 'logging.StreamHandler', 'formatter': 'django.server', }, 'mail_admins': { 'level': 'ERROR', 'filters': ['require_debug_false'], 'class': 'django.utils.log.AdminEmailHandler' } }, 'loggers': { 'django': { 'handlers': ['console', 'mail_admins'], 'level': 'INFO', }, 'django.server': { 'handlers': ['django.server'], 'level': 'INFO', 'propagate': False, }, } } manage.pyを更新 manage.py - os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings') + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings.local') ローカルのMySQLにdatabaseを作成する .envのDATABASE_URLに記載したdatabasenameで作成すること .gitignoreを作成する gitignore.ioで作成 ワードは[Pycharm][Python][Django]など https://www.toptal.com/developers/gitignore 作成されたテキストを.gitignoreに貼り付ける 確認用の簡単なページを作成する staticファイルちゃんと使えるかとか最低限のとこは見とく URL追加 config/urls.py from django.contrib import admin from django.urls import path from django.views.generic import TemplateView urlpatterns = [ path('admin/', admin.site.urls), path('', TemplateView.as_view(template_name='home.html'), name='home'), ] template&staticファイルを作成 (hogehoge) user hogehoge % mkdir templates (hogehoge) user hogehoge % touch templates/_base.html (hogehoge) user hogehoge % touch templates/home.html (hogehoge) user hogehoge % mkdir -p static/css (hogehoge) user hogehoge % mkdir -p static/js (hogehoge) user hogehoge % touch static/css/home.css (hogehoge) user hogehoge % touch static/js/home.js templates/_base.html <!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>{% block head_title %}{% endblock %}</title> {% block extra_css %}{% endblock %} {% block extra_js %}{% endblock %} </head> <body> {% block content %}{% endblock %} </body> </html> templates/home.html {% extends "_base.html" %} {% load static %} {% block head_title %}ホーム | hogehoge{% endblock %} {% block extra_css %} <link rel="stylesheet" href="{% static 'css/home.css' %}"> {% endblock %} {% block extra_js %} <script src="{% static 'js/home.js' %}"></script> {% endblock %} {% block content %} <h1 onclick="h1Click()">Hello World!</h1> {% endblock %} static/css/home.css h1 { color: blue; } static/js/home.js function h1Click(){ alert('h1 Click'); } ここでサーバー起動してみる (hogehoge) user hogehoge % python manage.py runserver 無事にサーバー起動ができて、css&jsがきちんと効いていることが確認できたらGitHubにプッシュする GitHubにプッシュ GitHub上にhogehogeプロジェクトを作成しておくこと (hogehoge) user hogehoge % git init (hogehoge) user hogehoge % git add . (hogehoge) user hogehoge % git commit -m "first commit" (hogehoge) user hogehoge % git branch -M main (hogehoge) user hogehoge % git remote add origin git@github.com:[project]/hogehoge.git (hogehoge) user hogehoge % git push -u origin main 後はいい感じに開発していく
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PyCharm&Djangoでfirst commitするまでのメモ

たまに作る時用にメモ DjangoはstartprojectしてそのままコミットするとSECRET_KEYも含まれてしまうので、その辺りも考慮して作成。 前提事項 プロジェクト名:hogehoge プロジェクトのディレクトリを作成 $ mkdir hogehoge PyCharmでプロジェクト作成 [New Project]を選択 Pure Pythonでプロジェクトを作成 ※Djangoでプロジェクトを作成するとベースディレクトリ名と設定ディレクトリ名が一緒になってしまう。今回はベースディレクトリ名はhogehogeで設定ディレクトリ名はconfigにしておきたいのでPure Pythonで作成する ・Locationはさっき作ったディレクトリを指定 ・create main.py welcome scriptのチェックボックスは外しておく Preferenceを開く(⌘,) Project:hogehoge > Python Interpreter から以下のパッケージをインストール ※インストール時にはSpecify Versionにチェックをいれて、バージョン固定をする(個人のお好きにどうぞ) django django-environ mysqlclient 設定ファイルの構成を変更 PyCharm内のタブからTerminalを開き、以下のコマンドを実行 (hogehoge) user ​hogehoge % django-admin startproject config . (hogehoge) user ​hogehoge % touch .env (hogehoge) user ​hogehoge % mkdir config/settings (hogehoge) user ​hogehoge % mv config/settings.py config/settings/_base.py (hogehoge) user ​hogehoge % touch config/settings/local.py config/settings/production.py (hogehoge) user ​hogehoge % touch .gitignore .envを更新 変数定義の際、空白とシングルクォーテーションは必要ないことに注意 .env # Secret Key SECRET_KEY=django-insecure-hjgklfd..... # MySQL settings DATABASE_URL=mysql://[username]:[password]@127.0.0.1:3306/[databasename]?charset=utf8mb4&sql_mode=TRADITIONAL,NO_AUTO_VALUE_ON_ZERO コンフィグファイルを更新する 細かいところは自分のお好きに settings/_base.py import os ############### # Build paths # ############### BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) PROJECT_NAME = os.path.basename(BASE_DIR) # Application definition INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', ] MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] ROOT_URLCONF = 'config.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [ os.path.join(BASE_DIR, 'templates'), ], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] WSGI_APPLICATION = 'config.wsgi.application' # Password validation # https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', }, { 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', }, { 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', }, { 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, ] # Internationalization # https://docs.djangoproject.com/en/3.2/topics/i18n/ LANGUAGE_CODE = 'ja' TIME_ZONE = 'Asia/Tokyo' USE_I18N = True USE_L10N = True USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/3.2/howto/static-files/ STATIC_URL = '/static/' STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')] # Default primary key field type # https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' settings/local.py from ._base import * import environ # Read .env if exists env = environ.Env() env.read_env(os.path.join(BASE_DIR, '.env')) ##################### # Security settings # ##################### SECRET_KEY = env('SECRET_KEY') DEBUG = True ALLOWED_HOSTS = [] ############ # Database # ############ DATABASES = { 'default': env.db() } ############ # Static # ############ STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') settings/production.py from ._base import * import environ # Read .env if exists env = environ.Env() env.read_env(os.path.join(BASE_DIR, '.env')) ##################### # Security settings # ##################### SECRET_KEY = env('SECRET_KEY') DEBUG = False ALLOWED_HOSTS = ['*'] ############ # Database # ############ DATABASES = { 'default': env.db() } ############ # Static # ############ STATIC_ROOT = '/var/www/{}/static'.format(PROJECT_NAME) manage.pyを更新 manage.py - os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings') + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings.local') ローカルのMySQLにdatabaseを作成する .envのDATABASE_URLに記載したdatabasenameで作成すること $ mysql.server start $ mysql -u [username] -p mysql> create database [databasename]; .gitignoreを作成する gitignore.ioで作成 ワードは[PyCharm][Python][Django]など https://www.toptal.com/developers/gitignore 作成されたテキストを.gitignoreに貼り付ける 確認用の簡単なページを作成する staticファイルちゃんと使えるかとか最低限のとこは見とく URL追加 config/urls.py from django.contrib import admin from django.urls import path from django.views.generic import TemplateView urlpatterns = [ path('admin/', admin.site.urls), path('', TemplateView.as_view(template_name='home.html'), name='home'), ] template&staticファイルを作成 (hogehoge) user hogehoge % mkdir templates (hogehoge) user hogehoge % touch templates/_base.html (hogehoge) user hogehoge % touch templates/home.html (hogehoge) user hogehoge % mkdir -p static/css (hogehoge) user hogehoge % mkdir -p static/js (hogehoge) user hogehoge % touch static/css/home.css (hogehoge) user hogehoge % touch static/js/home.js templates/_base.html <!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>{% block head_title %}{% endblock %}</title> {% block extra_css %}{% endblock %} {% block extra_js %}{% endblock %} </head> <body> {% block content %}{% endblock %} </body> </html> templates/home.html {% extends "_base.html" %} {% load static %} {% block head_title %}ホーム | hogehoge{% endblock %} {% block extra_css %} <link rel="stylesheet" href="{% static 'css/home.css' %}"> {% endblock %} {% block extra_js %} <script src="{% static 'js/home.js' %}"></script> {% endblock %} {% block content %} <h1 onclick="h1Click()">Hello World!</h1> {% endblock %} static/css/home.css h1 { color: blue; } static/js/home.js function h1Click(){ alert('h1 Click'); } ここでサーバー起動してみる (hogehoge) user hogehoge % python manage.py runserver ・無事にサーバー起動ができていること ・css&jsがきちんと効いていること が確認できたらGitHubにプッシュする GitHubにプッシュ GitHub上にhogehogeプロジェクトを作成しておくこと (hogehoge) user hogehoge % git init (hogehoge) user hogehoge % git add . (hogehoge) user hogehoge % git commit -m "first commit" (hogehoge) user hogehoge % git branch -M main (hogehoge) user hogehoge % git remote add origin git@github.com:xxx/hogehoge.git (hogehoge) user hogehoge % git push -u origin main 後はいい感じに開発していく
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

mysqlでテーブルを作成

個人的な忘備録。 環境 windows mySQL 8.0.15 mySQL Workbench 8.0 手順 スキーマ作成 赤枠をクリックしてスキーマを作成 「test」でそのままapply スキーマ接続 mySQL commandline Cliantを起動しtestスキーマに繋げるため以下コマンド use test; テーブル作成 適当に以下を作成 mysql> create table list( -> id int, -> name varchar(200) -> ); 作成できた
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

開発用のMySQL Dockerコンテナのメモリ消費が大きくて辛かったのでperformance_schemaを無効にしてどれくらい減るか調べたメモ

開発時に手元のマシンでコンテナを2個、3個と同時に動かさないといけない場面があって辛い 特に MySQL 5.6。扱うデータが少量でも 400MB を越える。 データちょっとしか入れてないのに? MySQL ってそういうものなの……?? あれこれ調べてパフォーマンススキーマを無効にする方法に辿りついた 以下、どのくらい減るかを調べたメモです。 ※ 無効にして問題ないのかという点については断定を避け(詳しくないので)、この記事では無効にしたときにどのくらいメモリ消費が減るか調べたことについてのみ書きます。ただ、軽く調べた限りでは、障害の調査やパフォーマンスチューニングをしないのであれば、開発用途では無効にしても不都合はなさそうに思えました。 結果 ※ 以下、"ps" と書いているのは performance_schema の略です。 起動した後のメモリ使用量(docker stats で表示される値): MySQL のバージョン ps = ON(MiB) ps = OFF(MiB) 5.6.61 464.6 59.8 5.7.34 194.3 62.7 8.0.24 335.9 118.6 5.6.61 では無効にすることで 88%減りました また、5.7 でメモリ消費がかなり改善されたことが分かります。 show engine performance_schema status でパフォーマンススキーマ全体でのメモリ使用量を見てみると次のようになっており、上記で減った量とほぼ一致していました。 MySQL のバージョン performance_schema.memory (MiB) 5.6.61 403.9 5.7.34 131.3 8.0.24 208.4 調査方法 使ったもの ホスト: Ubuntu 18.04 MySQL の公式 Docker イメージ Sakila サンプルデータ ディレクトリ・ファイル配置 - (作業用ディレクトリ) - sakira-db/ - 0_sakila-schema.sql - 1_sakila-data.sql - conf.d/ - my.cnf conf.d/ と sakila-db/ をそれぞれマウントして読み込ませました。下記のスクリプト参照。 conf.d/my.cnf [mysqld] # デフォルトで ON performance_schema=OFF 調査用スクリプト client.sh #!/bin/bash CONTAINER_NAME=mysql-sakila docker exec -it -e MYSQL_PWD=root $CONTAINER_NAME \ mysql --protocol=tcp -uroot -Dsakila "$@" restart.sh #!/bin/bash CONTAINER_NAME=mysql-sakila TIMEOUT_SEC=120 # MYSQL_VER=5.6.51 # MYSQL_VER=5.7.34 MYSQL_VER=8.0.24 # 動いていたら止める if (docker ps --format "{{.Names}}" | grep '^'${CONTAINER_NAME}'$' > /dev/null); then docker stop $CONTAINER_NAME fi # mysqld 起動 docker run --rm -it \ -e MYSQL_ROOT_PASSWORD=root \ -v "$(pwd)/conf.d:/etc/mysql/conf.d" \ -v "$(pwd)/sakila-db:/docker-entrypoint-initdb.d" \ --name $CONTAINER_NAME \ -d \ mysql:$MYSQL_VER # mysqld の起動完了を待って exit for i in $(seq $TIMEOUT_SEC); do if (./client.sh -e "select 1" > /dev/null 2>&1); then printf "\n" echo "ok" exit 0 else printf "." sleep 1 fi done echo "failed" exit 1 ps_info.sh #!/bin/bash set -o xtrace ./client.sh -e " show variables like 'performance_schema' " # パフォーマンススキーマ全体でのメモリ使用量 ./client.sh -e " show engine performance_schema status " | grep 'performance_schema.memory' 参考 MySQL :: MySQL 8.0 リファレンスマニュアル :: 27 MySQL パフォーマンススキーマ (dev.mysql.com) (2016) performance_schemaをsysで使い倒す! | Think IT(シンクイット) (2016) t2.nano で MySQL5.6 を動かすために | ゲンジニア日記 (2016) MySQL5.6 performance_schemaとtable_definition_cacheの調整 | riscascape.net
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む