- 投稿日:2020-03-29T23:13:15+09:00
組み込み系からWeb系へのスキルチェンジ【随時更新】
はじめに
組み込みの開発しかほぼしたことしかない中で、Web系のスキルを身に着けるためにやったことをメモっておきます。
現状のWeb系のスキル。
- Perl/PHP/javascript/HTML5:ちょっと使えるレベル
- セキュアド:取得済
- ネスペ:一通り勉強はした(受かってはいない)
- github/Slack:プライベートで少し使ってるレベル(
業務?シャガイノサービスナンテシヨウキンシデスヨ)書籍
- TECHNICAL MASTER はじめてのPHPプロフェッショナル開発 PHP7対応 :チーム開発に即した形(もちろん会社やプロジェクトにもよるだろうけど)で書かれてたので、PLをやるのに役立ちそうだったので購入。推奨動作環境はMacOSで書かれています。
環境構築
手持ちがWindows10 homeしかなくDockerを入れれないので、VirtualBox+Ubuntuベースで環境構築しました。
Windows10にVirtualBoxとUbuntuをインストール
Windows10にVirtualBoxとUbuntuをインストールを参考にしました。
Ubuntuのバージョンは2020/3/22時点で最新のLSTの「Ubuntu 18.04.4 LTS」を使用しましたが、手順はほぼ一緒です。設定変更
- VirtualBoxの[設定]-[一般]-[高度]-[クリップボードの共有]と[ドラッグ&ドロップ]を「双方向」に
- VirtualBox上のUbuntu 18.04の画面サイズを自動で切り替えられるようにする
- ubuntsの右クリックで新規ファイルを作成できるようにする: Ubuntu 18.04の右クリックメニューから「空のドキュメント」を作成する
Docker
VirtualBox に Ubuntu 18.04 と Docker をインストールしたメモを参考にインストール。バージョンは19.03.8。
追加でdocker-composeをインストール
$ sudo apt install docker-composePHP
一旦、書籍1.に合わせてPHP7.2を入れる。
Ubuntu 16.04 で PHP 7.2 を使う手順MySQL
UbuntuにMySQLをインストールを参考にインストール。
バージョンは14.14。$ sudo apt install mysql-server mysql-client //rootユーザ設定 $ sudo mysql_secure_installationVisual Studio Code
簡単にUbuntuにVSCode (Visual Studio Code) をインストールする方法を参考にインストール。
バージョンは1.43.2。日本語化
Visual Studio Code のユーザーインタフェイス(UI) 表示を日本語にする
PHP IntelliSense
以下を参考に導入。
setting.jsonの設定は、LinuxのPHPのインストール先に合わせて以下になります。
~/.config/Code/User/setting.json{ "php.validate.enable": false, "php.suggest.basic": false, "php.executablePath": "/usr/bin/php" }うまくいかなかったとこ
Dcokerでdocker-entrypoint-initdb.dをマウントするときにPermission deniedエラーがでる。
docker-compose.ymlに以下を追加したら、エラーがでるようになった。(全文は書籍の内容なので割愛します。)
docker-compose.ymlvolumes: - ./Docker/mysql/sqls:/docker-entrypoint-initdb.d$ docker-compose up Creating network "phpbookapp_default" with the default driver Creating php-book-app-db ... Creating php-book-app-db ... done Attaching to php-book-app-db php-book-app-db | 2020-03-29 01:19:13+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.29-1debian10 started. php-book-app-db | 2020-03-29 01:19:13+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql' php-book-app-db | 2020-03-29 01:19:13+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.29-1debian10 started. php-book-app-db | ls: cannot open directory '/docker-entrypoint-initdb.d/': Permission denied php-book-app-db exited with code 2解決策
ホスト側のディレクトリにgroupとotherの読み取り・実行権限がなかったのが原因でした。。。
- 投稿日:2020-03-29T22:46:59+09:00
MySQLからcsvを出力する
環境
mysql : Ver 8.0.19 for Linux on x86_64 (MySQL Community Server - GPL)
SELECT文でcsvファイルを出力する
SELECT * FROM hoge INTO OUTFILE '/output/hoge.csv' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'dockerでMYSQLコンテナ立ち上げている場合、
OUTFILE
をマウント位置にすると良いcsvファイルを出力する際にエラーを吐いた場合
ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statementデータの入出力エラー
MySQLの設定を確認
mysql> SELECT @@global.secure_file_priv; +---------------------------+ | @@global.secure_file_priv | +---------------------------+ | NULL | +---------------------------+このNULLがダメらしい
設定を変更して解決する
DockerでMySQLコンテナを立ち上げて.sqlファイルからDBを作る
立ち上げているコンテナは上の通りなので、my.cnf
に以下を追記[mysqld] secure-file-priv = ""コンテナ再起動で設定を反映させてると設定欄のNULLが消える
mysql> SELECT @@global.secure_file_priv; +---------------------------+ | @@global.secure_file_priv | +---------------------------+ | | +---------------------------+これでSELECT文でcsvファイルが吐き出せるようになっているはず
参考資料
MySQLのバージョン確認方法
MySQLのSELECT文でcsvを出力する
MySQLでCSV出力しようとしたら --secure-file-priv option のエラーになった
MySQLでCSVファイルを使って結果出力やデータ入力を行う方法
- 投稿日:2020-03-29T19:59:13+09:00
Rails 自作アプリへの道 Part2
Rails 自作アプリを作った時の経過をまとめていきます。
環境
OS Ruby Rails Mac Mojave 10.14.16 2.6.3p62 6.0.2.2 参考
https://qiita.com/aplifyjp/items/ea0d9236d89fa24a7a1c前提
環境構築済項番1 『devise』の導入
code1.rb# Gemfileに『devise』を追加する $ cat Gemfile (省略) # gem 'bcrypt', '~> 3.1.7' # Use Active Storage variant # gem 'image_processing', '~> 1.2' (省略) $ vi Gemfile (省略) # gem 'bcrypt', '~> 3.1.7' gem 'devise' # Use Active Storage variant # gem 'image_processing', '~> 1.2' (省略) $ cat Gemfile (省略) # gem 'bcrypt', '~> 3.1.7' gem 'devise' # Use Active Storage variant # gem 'image_processing', '~> 1.2' (省略) $ bundle install # Gemfileに記述した『devise』をインストールする (省略) Using devise 4.7.1 (省略)項番2 アプリへの『devise』の機能の導入
code2.rb# アプリに『devise』の機能を導入する $ rails g devise:install create config/initializers/devise.rb create config/locales/devise.en.yml =============================================================================== Some setup you must do manually if you haven't yet: 1. Ensure you have defined default url options in your environments files. Here is an example of default_url_options appropriate for a development environment in config/environments/development.rb: config.action_mailer.default_url_options = { host: 'localhost', port: 3000 } In production, :host should be set to the actual host of your application. 2. Ensure you have defined root_url to *something* in your config/routes.rb. For example: root to: "home#index" 3. Ensure you have flash messages in app/views/layouts/application.html.erb. For example: <p class="notice"><%= notice %></p> <p class="alert"><%= alert %></p> 4. You can copy Devise views (for customization) to your app by running: rails g devise:views ===============================================================================項番3 モデル絡みの操作
code3.rb#『devise』の機能を取り込んだ『Sellerモデル』の作成 $ rails g devise Seller invoke active_record identical db/migrate/20200330100615_devise_create_sellers.rb create app/models/seller.rb invoke test_unit create test/models/seller_test.rb create test/fixtures/sellers.yml insert app/models/seller.rb route devise_for :sellers # db/migrate/20200330100615_devise_create_sellers.rbのt.confirmableのコメントを外す # インデックスも有効にする $ vi db/migrate/20200330100615_devise_create_sellers.rb $ rails db:migrate #『Sellerモデル』に必要なカラムを追加する $ rails g migration add_columns_to_sellers name:string admin_flag:boolean invoke active_record create db/migrate/20200330101922_add_columns_to_sellers.rb $ rails db:migrate # 初期データを作成する $ vi db/seeds.rb sellers = ["橋本"] sellers.each_with_index do |user, i| Seller.create( name: "#{user}", email: "#{i + 1}@gamil.com", password: "password", admin_flag: true ) end # 初期データを投入する $ rails db:seed項番4『devise』とは関係ない『controller』と『routes.rb』の操作
code4.rb$ rails g controller Home index show $ vi config/routes.rb Rails.application.routes.draw do get 'home/index' get 'home/show' end root to: "home#index"項番5『view』の操作
code5.rb# 基本となる『view』の作成 $ vi app/views/layouts/application.html.erb <!DOCTYPE html> <html> <head> <title>Ticket2App</title> <%= csrf_meta_tags %> <%= csp_meta_tag %> <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %> </head> <body> <header> <nav> <!-- seller_signed_in? はセラーがログインしているか調べるdeviseのHelperメソッド --> <% if seller_signed_in? %> <!-- current_seller は現在ログインしているSellerオブジェクトを返すdeviseのHelperメソッド --> <!-- *_path はSellerモデルを作成したときに、 deviseにより自動で作成されてますので、rails routesで確認できます --> Logged in as <strong><%= current_seller.email %></strong>. <%= link_to 'プロフィール変更', edit_seller_registration_path %> | <%= link_to "ログアウト", sign_out_path %> <% else %> <%= link_to "サインイン", new_seller_registration_path %> | <%= link_to "ログイン", new_seller_session_path %> <% end %> </nav> </header> <p class="notice"><%= notice %></p> <p class="alert"><%= alert %></p> </body> </html>
- 投稿日:2020-03-29T19:59:13+09:00
Rails 自作アプリへの道 Part1
Rails 自作アプリを作った時の経過をまとめていきます。
参考:https://kitsune.blog/rails-install
環境
| 1 | 2 |
|:-:|:-:|
| | |
| | |
| | |
| OS | Mac Mojave 10.14.16 |
| Ruby | 2.6.3p62 |
| Rails | 6.0.2.2 |
- 投稿日:2020-03-29T19:24:09+09:00
XAMPPのphpmyadminにアクセスした時、HY000/2002が出てアクセス拒否された場合の対処
起こったこと
xmappでApacheとMySQLを起動してさてphpmyadmin/index.htmlにアクセスすると
以下みたいなエラーが出てログイン画面すら出ない状態になっていました。
今回行った対応を順に書いていきます。
※この記事ではrootユーザでのログインを行っているが実際の運用ではrootユーザではなく別のユーザを別途定義した方が無難。ログイン画面を出す
デフォルトでxmappをインストールした場合、C:\xampp\phpMyAdmin\配下にconfig.inc.phpが置いてあります。
今回はその中の一部を編集する。config.inc.phpを開き、以下の項目があることを確認してください。
何も編集していない状態であればおそらく下記のような状態になっているかと思われます。(これとは違う場合もあるかもしれない)config.inc.php/* Authentication type and info */ $cfg['Servers'][$i]['auth_type'] = 'config'; $cfg['Servers'][$i]['user'] = 'root'; $cfg['Servers'][$i]['password'] = ''; $cfg['Servers'][$i]['extension'] = 'mysqli'; $cfg['Servers'][$i]['AllowNoPassword'] = true; $cfg['Lang'] = ''; /* Bind to the localhost ipv4 address and tcp */ $cfg['Servers'][$i]['host'] = '127.0.0.1'; $cfg['Servers'][$i]['connect_type'] = 'tcp'; /* User for advanced features */ $cfg['Servers'][$i]['controluser'] = 'pma'; $cfg['Servers'][$i]['controlpass'] = '';
$cfg['Servers'][$i]['auth_type']
は認証モードの設定でデフォルトではconfigとなっています。これをcookieと変更してください。これによって有効なMySQLユーザーをログイン画面で入力すればログインできるはずです。ついでに$cfg['Servers'][$i]['user'] = 'root';
はcookieでは不要なので空文字にしてください。config.inc.php(一部)$cfg['Servers'][$i]['auth_type'] = 'cookie'; $cfg['Servers'][$i]['user'] = ''; $cfg['Servers'][$i]['password'] = '';(HY000/2002): 対象のコンピューターによって拒否されたため、接続できませんでした。の対処
前述の設定をしたconfig.inc.phpを保存し、phpmyadminのページをリロードするとログイン画面が表示されるかと思います。
あらかじめ設定したrootユーザでログイン……、がっダメ!ここで小一時間詰まってしまいました。原因はおそらくhostの項目でローカルのipアドレス127.0.0.1になっているからかなと思いlocalhostに変更したりしましたが一向に解決せず。
そんな時下記の質問記事を発見しました。
xampp phpmyadmin access denied error(#2002)
どうやら、localhost:MySQLのポート番号(デフォルトでは3306?)
と記載しないといけなかったみたいです。つまり下記のように直すということですね。
※筆者のMySqlのポート番号は3306です。自分の環境に合わせたポート番号に変更してください。config.inc.php(一部)/* Bind to the localhost ipv4 address and tcp */ $cfg['Servers'][$i]['host'] = 'localhost:3306';config.inc.phpを保存し、IDとパスを入力してログイン…。成功!
所感
ポート番号込みで定義しないといけないというのは盲点でしたが当たり前ですね…。
とりあえずphpmyadmiにはアクセスできたので、この後は別途ユーザを作成し、
rootユーザのアクセスを制限しておく必要があるかと思います。
振り返れば簡単なことなのですがこれ調べるだけで半日終わっちゃって本来の勉強が進まない…。
- 投稿日:2020-03-29T18:30:48+09:00
MySQLのエラーでDjangoアプリがローカルで実行できなくなったときの話
久しぶりにDjangoのアプリケーションを立ち上げようと以下のコマンドを打ったところ
python.manage.py runserver
こんなエラーが。前は動いてたはずなのに何故
django.db.utils.OperationalError: (2003, "Can't connect to MySQL server on '127.0.0.1' ([Errno 111] Connection refused)")
MySQLの起動確認
$ mysql.server start Starting MySQL .... * The server quit without updating PID file (/home/linuxbrew/.linuxbrew/var/mysql/***.pid).PIDファイルとは,Linux上であるサービスが起動したときに作成されるファイルで,プロセス番号が割り振られているらしい.サービスが動いているかどうかの判断基準になる.
***は端末名空のPIDファイルを作ってみる
$ touch /home/linuxbrew/.linuxbrew/var/mysql/***.pid $ mysql.server restart * MySQL server PID file could not be found! Starting MySQL .rm: cannot remove '/tmp/mysql.sock': Operation not permitted 2020-03-20T18:09:18.611443Z mysqld_safe Fatal error: Can't remove the socket file: /tmp/mysql.sock. Please remove the file manually and start /home/linuxbrew/.linuxbrew/Cellar/mysql/8.0.18_1/bin/mysqld_safe again; mysqld daemon not started * The server quit without updating PID file (/home/linuxbrew/.linuxbrew/var/mysql/***.pid)./tmp/mysql.sock削除&再チャレンジ
$ sudo rm /tmp/mysql.sock $ touch /home/linuxbrew/.linuxbrew/var/mysql/***.pid $ mysql.server restart * MySQL server PID file could not be found! Starting MySQL ... * $ mysql -u root Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 8 Server version: 8.0.18 Homebrew Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.通った!
- 投稿日:2020-03-29T18:08:44+09:00
PHP 郵便番号と住所を検索 正規表現
郵便番号か住所で検索
内容
郵便番号または都道府県を選択し市町村を入力すると
郵便のデータが検索できます。10件を超えた場合に”前へ”、”次へ”を押すと各々のページに飛ぶようになっています。
SQL脆弱性があると思いますが、今のところこのまま学習を進めていきます。
// 変数を設定 $post_num ='';//郵便番号 $area ='';//都道府県選択 $city ='';//市町村 $town ='';//県域 $error1 = [];//エラー文 $error2 = [];//エラー文 $user_data = []; $abc_data = []; $query = ''; $host = 'localhost'; $username = ''; $passwd = ''; $dbname = ''; $link= mysqli_connect($host, $username, $passwd, $dbname); $page = 1; $count = '';//トータル件数 $totalpage = ceil($count/ 10);//切り上げ変数が存在するかを確認
//どちらかに値が入っていた場合 if(isset($_GET['post_num']) === true || isset($_GET['area']) === true) { //変数を代入する if(isset($_GET['post_num']) === true) { $post_num = $_GET['post_num']; } if(isset($_GET['area']) === true) { $area = $_GET['area']; } if(isset($_GET['city']) === true) { $city = $_GET['city']; } if(isset($_GET['town']) === true) { $town = $_GET['town']; } if(isset($_GET['page']) === true) { $page = $_GET['page']; }if(isset($_GET['post_num']) === true || isset($_GET['area']) === true)このif文を書かないと空欄の状態でも変数の確認をしてしまうため、
後述のエラー文が出てしまいます空白の削除をします
$post_num = str_replace(array(" "," "),"", $post_num); $area = str_replace(array(" "," "),"", $area); $town = str_replace(array(" "," "),"", $town);str_replace(array(半角、全角空白)、空、変数)となっており
変数の中の半角、全角空白を空要素と入れ替えます。つまり、空白があった場合に削除します。エラーメッセージ
if(empty($post_num) === true && ($area === '都道府県を選択' || empty($city) === true)) { $error1[] = '郵便番号を入力してください'; }else if ((preg_match('/^[0-9]{7}$/', $post_num) !== 1) && ($area === '都道府県を選択' || empty($city) === true)) { $error1[] = '7桁の数字で入力してください'; }else { print ""; }areaとcityの入力がしていない場合でないと条件を付けないと
2つの値が入っているときにもエラー文が出てしまう。}else if ((preg_match('/^[0-9]{7}$/', $post_num) !== 1) && ($area === '都道府県を選択' || empty($city) === true)) { $error1[] = '7桁の数字で入力してください';preg_match(正規表現、文字列)で文字列が正規表現と一致しているかを
確認する
一致していれば1、していなければ0で、失敗するとfalseを返します。
正規表現は0から9までの値を7桁でとなっている。
なので、post_numが7桁の数字出なかった場合、かつareaまたはcityの
値が空だった場合にエラー文が出るようになる。if ($area === '都道府県を選択' && (empty($post_num) === true ||(preg_match('/^[0-9]{7}$/', $post_num) !== 1))) { $error2[] = '都道府県を選択してください'; } if(empty($city) === true && (empty($post_num) === true ||(preg_match('/^[0-9]{7}$/', $post_num) !== 1))){ $error2[] = '市区町村名をを入力してください'; }前述とほぼ同じで、post_numに値が入っている場合にはエラー分が出ないようになっています。
データベースに接続
if(count($error1) === 0 || count($error2) === 0) { if($link) { mysqli_set_charset($link, 'utf8'); if($post_num !== '') { $query = "SELECT post_num, area , city, town FROM pt_table WHERE post_num = '$post_num'";エラー文がないときに接続します。文字化けを防止でutf8で表記します。
post_numが空ではない場合にsql文を代入します。WHERE post_num = '$post_num'";データベースにある郵便番号の値とpost_numが同じ場合になるのが条件。
} else { $limit = 10*$page-10; $query = "SELECT post_num, area , city, town FROM pt_table WHERE (area = '$area') AND (city = '$city') LIMIT ".$limit.",10";pageは1番最初のページ数を表しています。 LIMITは開始位置、終わりの位置までを指定。
つまり、10件ごとにページに表示します。変数limitは0、10、20、30と増えていきます。
$query = "SELECT post_num, area , city, town FROM pt_table WHERE (area = '$area') AND (city = '$city') LIMIT ".$limit.",10";データベースのarea,cityの値がそれぞれ一致している場合という条件。
変数limitを”$limit”と書いた場合には文字列となってしまいます。カンマで囲うと数字として扱えます。総件数を出すために文字列を取得
$abc = "SELECT post_num, area , city, town FROM pt_table WHERE (area = '$area') AND (city = '$city')"; $result = mysqli_query($link, $abc); while($row = mysqli_fetch_array($result)) { $abc_data[] = $row; } }まず、変数queryでデータを取得しようとすると最大10件しか取得できません。理由はLIMITを使って10件ずつ取得するプログラムになっているからです。なので、別の実行データを
1行ずつ取得し、文字列にしていきます。実行したデータを取得
$result = mysqli_query($link, $query); while($row = mysqli_fetch_array($result)) { $user_data[] = $row; }10件ずつ取得するデータを1行ずつ取得し文字列にします。
メモリを開放しデータベースから閉じる
mysqli_free_result($result); mysqli_close($link); }else { echo 'DB接続失敗'; } } }総件数
$count = count($abc_data);ページング
<?php if ($page > 1) { ?> <a href="?page=<?php echo ($page - 1); ?>&area=<?php print $area; ?> &city=<?php print $city; ?>">前のページへ</a> <?php } ?> <?php if ($page < $totalpage) { ?> <a href="?page=<?php echo ($page + 1); ?>&area=<?php print $area; ?> &city=<?php print $city; ?>">次のページへ</a> <?php } ?>ファイル名?post_num=&area=県名&city=市名とURLに表示させる事を目的にする。
GETで値を取得したときにはURLが表示され、その先頭は?が付きます。
現在のページが1よりも大きいは(page-1)つまり前のページにいきます。トータルページが今のページよりも多い場合には次のページに行きます
全コード
<?php // 変数を設定 $post_num =''; $area =''; $city =''; $town =''; $error1 = []; $error2 = []; $user_data = []; $abc_data = []; $query = ''; $host = 'localhost'; $username = 'codecamp31549'; $passwd = 'RXFXXBTL'; $dbname = 'codecamp31549'; $link= mysqli_connect($host, $username, $passwd, $dbname); $page = 1; $count = '';//トータル件数 $totalpage = ceil($count/ 10);//切り上げ /*変数が存在する確認*/ if(isset($_GET['post_num']) === true || isset($_GET['area']) === true) { if(isset($_GET['post_num']) === true) { $post_num = $_GET['post_num']; } if(isset($_GET['area']) === true) { $area = $_GET['area']; } if(isset($_GET['city']) === true) { $city = $_GET['city']; } if(isset($_GET['town']) === true) { $town = $_GET['town']; } if(isset($_GET['page']) === true) { $page = $_GET['page']; } /*空白削除*/ $post_num = str_replace(array(" "," "),"", $post_num); $area = str_replace(array(" "," "),"", $area); $town = str_replace(array(" "," "),"", $town); /*エラーメッセージ*/ if(empty($post_num) === true && ($area === '都道府県を選択' || empty($city) === true)) { $error1[] = '郵便番号を入力してください'; }else if ((preg_match('/^[0-9]{7}$/', $post_num) !== 1) && ($area === '都道府県を選択' || empty($city) === true)) { $error1[] = '7桁の数字で入力してください'; }else { print ""; } if ($area === '都道府県を選択' && (empty($post_num) === true ||(preg_match('/^[0-9]{7}$/', $post_num) !== 1))) { $error2[] = '都道府県を選択してください'; } if(empty($city) === true && (empty($post_num) === true ||(preg_match('/^[0-9]{7}$/', $post_num) !== 1))){ $error2[] = '市区町村名をを入力してください'; } /*データベースに接続*/ if(count($error1) === 0 || count($error2) === 0) { if($link) { mysqli_set_charset($link, 'utf8'); if($post_num !== '') { $query = "SELECT post_num, area , city, town FROM pt_table WHERE post_num = '$post_num'"; // var_dump($query); } else { $limit = 10*$page-10; $query = "SELECT post_num, area , city, town FROM pt_table WHERE (area = '$area') AND (city = '$city') LIMIT ".$limit.",10"; $abc = "SELECT post_num, area , city, town FROM pt_table WHERE (area = '$area') AND (city = '$city')"; $result = mysqli_query($link, $abc); while($row = mysqli_fetch_array($result)) { $abc_data[] = $row; } } // var_dump($query); $result = mysqli_query($link, $query); while($row = mysqli_fetch_array($result)) { $user_data[] = $row; } mysqli_free_result($result); mysqli_close($link); }else { echo 'DB接続失敗'; } } } $count = count($abc_data); ?> <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>郵便</title> </head> <body> <form action="./17-6.php" method="get"> <h1>郵便番号検索</h1> <h2>郵便番号から検索</h2> <?php print "総件数" . htmlspecialchars($count,ENT_QUOTES,'UTF-8') . "件";?> <input type="search" name="post_num" value=""> <input type="submit" value="検索"> <h2>地名から検索</h2> <label>都道府県を選択 <select name="area"> <option>都道府県を選択</option> <option>北海道</option> <option>兵庫県</option> <option>新潟県</option> </select> </label> <label>市区町村 <input type="seach" name="city"> <input type="submit" value="検索"> </label> </form> <p><?php foreach($error1 as $key1 => $string1) { print htmlspecialchars($string1,ENT_QUOTES,'UTF-8'); } ?></p> <p><?php foreach($error2 as $key2 => $string2) { print htmlspecialchars($string2,ENT_QUOTES,'UTF-8');; } ?></p> <?php foreach($user_data as $read) {?> <table> <style type="text/css"> table, td, th { border: solid black 1px; } table { width: 600px; } tr td { width: 150px; } </style> <tr> <th>郵便番号</th> <th>都道府県</th> <th>市町村</th> <th>町域</th> </tr> <tr> <td><?php print htmlspecialchars($read['post_num'],ENT_QUOTES,'UTF-8'); ?></td> <td><?php print htmlspecialchars($read['area'],ENT_QUOTES,'UTF-8'); ?></td> <td><?php print htmlspecialchars($read['city'],ENT_QUOTES,'UTF-8'); ?></td> <td><?php print htmlspecialchars($read['town'],ENT_QUOTES,'UTF-8'); ?></td> </tr> </table> <?php } ?> <p> <!--GETを使用するときは?からスタートする--> <?php if ($page > 1) : ?> <a href="?page=<?php echo ($page - 1); ?>&area=<?php print $area; ?> &city=<?php print $city; ?>">前のページへ</a> <?php endif; ?> <?php if ($page < $totalpage) : ?> <a href="?page=<?php echo ($page + 1); ?>&area=<?php print $area; ?> &city=<?php print $city; ?>">次のページへ</a> <?php endif; ?> </p> </body> </html> ```php
- 投稿日:2020-03-29T17:50:28+09:00
README データベース設計
マークダウンで記述します。
自分の勉強用でメモします。
初学者の方は参考にしてください。以下のようなテーブルを作成したとします。
usersテーブル
Column Type Options name string null: false, add_index: true string null: false, unique: true password string null: false password confirmation string null: false 意味を下記に記述した。
↓↓したのusersテーブルはテーブル名を記述する。
usersテーブル これはコメントアウトする。↓↓ここはテンプレートで大丈夫です。
|Column|Type|Options|
|------|----|-------||❶name|❷string|❸null: false, ❹add_index: true|
❶name
❶nameはカラム名。
そのカラムの名前。❷string
❷stringはデータ型です。
種類は以下のようにあります。string 文字列型
text テキスト(不定長文字列)型
integer 整数型
float 浮動小数点数型
decimal 固定長整数型
datetime 日時型
timestamp タイムスタンプ型
time 時刻型
date 日付型
binary バイナリ文字列型
boolean 真偽値型
references 他のテーブルへの外部キーの定義、_id が付いた整数などがあります。❸null: false
❸null: false カラムにnullを許可しない
カラムのオプションです!!
NULLとは(空の値)のこと。
(null false制約など)
以下があります。❹Usersテーブルのnameカラムにindexを張ることで、アルファベット順にnameを並べ替え検索しやすいようにしてくれます。
null: false カラムにnullを許可しない
unique: true カラムに同じ値を許可しない
foreign_key: true 他のテーブルへの外部キー制約をつける indexも自動付与
default: "oooooo" カラムに値が設定されなかった場合にデフォルトで格納される値を設定。
limit: 50 データ型の最大幅を指定。
対象となるデータ型は文字列タイプはstring型とtext型の2つ、数値タイプはinteger型とbinary型の2つ。
precision: 10, scale: 5 指定することで精度(最大桁数)とスケール(小数点以下の桁数)を指定。
対象となるデータ型は文字列タイプはdecimal型。以下同様です。
|❶email|❷string|❸null: false, ❹unique: true|
❶email=カラム名
❷string=文字列型
❸null: false=カラムにnullを許可しない
NULLとは(空の値)空欄のこと!!!
❹unique: true=同じアドレスはダメということ。アソシエーション
対象を1つ持っているなら、has_one
has_oneは自分のテーブルが対象テーブルを1つ持っている(複数持たない)場合に使います。対象テーブル側に自分のidのカラムがある場合に使います。
対象を複数持っているなら、has_manyhas_manyは自分のテーブルが対象テーブルを複数もつ場合に使います。対象テーブル側に自分のidのカラムがある場合に使います。
自分が対象に所属しているなら、belongs_tobelongs_toは、自分のテーブルが対象テーブルのレコードに所属する(対象テーブルのidカラムがある)場合に使います。
- 投稿日:2020-03-29T17:00:15+09:00
【SQL初心者向け】インデックスのしくみを理解する
記事概要
■作成までの経緯、状況
「インデックスは、辞書の目次みたいなものだから。使えば検索が早くなる」
SQLを使い始めてまだ間もないころ、先輩に言われた言葉です。
「お!なるほど!とりあえず貼ればいいのかあ」
と馬鹿の一つ覚えのようにテーブルにインデックスを貼りまくった結果、
その後のパフォーマンスチュー二ングにとても苦しみました。
インデックスの作成はできる。けれどしくみが説明できない。。
当時の自分への備忘録として、本記事の作成に至りました。
使用する用語はMySQLに準じます。■発生した問題
インデックスの作成方法はわかるが、なぜ効果があるのかがわからない。■期待する効果
インデックスのしくみを説明できるようにする。■問題を解決するための用法
Qiitaで記事を書く。■しくみ、動作原理
以下の流れでしくみを説明します。
1. テーブルを用意する。
2. データ検索の流れを理解する。
3. インデックスのしくみを理解する。
4. インデックスが使えない場合を理解する。しくみ1 「テーブルを用意する」
インデックスを作成するには、テーブルが必要です。
今回は、あるアニメの「登場人物」テーブルを用意します。
登場人物 イカリ シンジ アヤナミ レイ スズハラトウジ カツラギ ミサト アカギ リツコ カジ リョウジ イカリ ゲンドウ ・・・ ヒュウガ マコト ナギサ カヲル 2020/06/27 楽しみだなー( ´∀` )
しくみ2 「データ検索を理解する」
テーブルを検索する流れは以下の通りです。
① HDD上のデータがページ単位でキャッシュメモリに載る。
② キャッシュメモリに載ったテーブルをCPUが処理する。
③ メモリがパンパンになったら削除され、①に戻る。①の「ページ」とは、データをかたまりで扱う際の単位を意味します。
Oracleでは「ブロック」と言います。この図を見たときの疑問点として以下のものが挙げられます。
「②の時に検索したいデータがあれば、その時点で検索が終わるんじゃない?」これに対する答えは「検索は続くよどこまでも」です。
インデックスを作成していないと、データがソートされません。
そのため、「ほかにも同様のデータがあるんじゃ。。」
となり、結局テーブル全体が検索されます。これがフルスキャンです。
(メモリにキャッシュされている部分は除く)
だからパフォーマンスが落ちるのですね!!しくみ3 「インデックス作成を理解する」
数あるインデックスの中で、MySQLで使用されているのはB+treeです。
B-treeとも呼ばれますが、厳密には、B-treeを実用的扱いやすく改良したものがB+treeです。B-treeインデックスについての説明は以下の記事がとても分かりやすいです。
「B-treeインデックス入門」以下はメモリやHDDページを省略した簡単な図解です。
ここでは検索対象として「アヤナミ レイ」を2件用意しました。
HDD全体を検索するフルスキャンでは、検索終了までに何回もHDDを読み込む必要があります。
しかし、B-treeインデックスを使用した場合、図からもわかるように2か所のHDDページだけを直接読み込むことで検索が終了します。
インデックスのデータ構造はただテーブルがソートされていただけでなく、
このようなしくみで検索されていたから早くなるのです。しくみ4 「インデックスが使えない時を知る」
インデックスが役に立たない場合は以下の通りです。
・データ数が少ないとき
・後方一致検索
・前方一致検索(検索結果が多いときのみ)後方検査でインデックスが使用できない理由は、上記の図からもわかりますね。
要は「データは頭文字から照合されていくため、中間地や後方一致検索にインデックスを使用できないから」です。前方一致検索でインデックスが使用できない理由は、「頭文字が同じものが多数ある場合、結局検索する対象が多くなるから」です。
おわりに
最後までお読みいただき、ありがとうございました!
本記事の作成を通して、インデックスのしくみが理解できました。
内容に誤りがありましたら、ご指摘ください。参考書籍
オススメの技術書籍を楽天Roomで紹介しています。
「SQLの苦手を克服する本 データの操作がイメージできれば誰でもできる」
https://room.rakuten.co.jp/room_39a28b3432/items#!
- 投稿日:2020-03-29T17:00:15+09:00
拝啓「インデックスは作れるけど説明できない僕へ」
記事概要
■作成までの経緯、状況
「インデックスは、辞書の目次みたいなものだから。使えば検索が早くなる」
SQLを使い始めてまだ間もないころ、先輩に言われた言葉です。
「お!なるほど!とりあえず貼ればいいのかあ」
と馬鹿の一つ覚えのようにテーブルにインデックスを貼りまくった結果、
その後のパフォーマンスチュー二ングにとても苦しみました。
インデックスの作成はできる。けれどしくみが説明できない。。
当時の自分への備忘録として、本記事の作成に至りました。
使用する用語はMySQLに準じます。■発生した問題
インデックスの作成方法はわかるが、なぜ効果があるのかがわからない。■期待する効果
インデックスのしくみを説明できるようにする。■問題を解決するための用法
Qiitaで記事を書く。■しくみ、動作原理
以下のポイントでインデックスのしくみを説明します。
1. テーブルを用意する。
2. データ検索の流れを理解する。
3. インデックスのしくみを理解する。
4. インデックスが使えない場合を理解する。ポイント1 「テーブルを用意する」
インデックスを作成するには、テーブルが必要です。
今回は、あるアニメの「登場人物」テーブルを用意します。
登場人物 イカリ シンジ アヤナミ レイ スズハラトウジ カツラギ ミサト アカギ リツコ カジ リョウジ イカリ ゲンドウ ・・・ ヒュウガ マコト ナギサ カヲル 2020/06/27 楽しみだなー( ´∀` )
ポイント2 「データ検索を理解する」
テーブルを検索する流れは以下の通りです。
① HDD上のデータがページ単位でキャッシュメモリに載る。
② キャッシュメモリに載ったテーブルをCPUが処理する。
③ メモリがパンパンになったら削除され、①に戻る。①の「ページ」とは、データをかたまりで見た時の単位を意味します。
上記では、P2のデータをメモリに載せています。
Oracleでは「ブロック」と言います。この図を見たときの疑問点として以下のものが挙げられます。
「②の時に検索したいデータがあれば、その時点で検索が終わるんじゃない?」これに対する答えは「検索は続くよどこまでも」です。
インデックスを作成していないと、データがソートされません。
そのため、「ほかにも同様のデータがあるんじゃ。。」
となり、結局テーブル全体が検索されます。これがフルスキャンです。
(メモリにキャッシュされている部分は除く)
だからパフォーマンスが落ちるのですね!!ポイント3 「インデックス作成ロジックを理解する」
数あるインデックスの中で、MySQLで使用されているのはB+treeです。
B-treeとも呼ばれますが、厳密には、B-treeを実用的扱いやすく改良したものがB+treeです。B-treeインデックスについての説明は以下の記事がとても分かりやすいです。
「B-treeインデックス入門」以下はメモリやHDDページを省略した簡単な図解です。
ここでは検索対象として「アヤナミ レイ」を2件用意しました。
HDD全体を検索するフルスキャンでは、検索終了までに何回もHDDを読み込む必要があります。
しかし、B-treeインデックスを使用した場合、図からもわかるように2か所のHDDページだけを直接読み込むことで検索が終了します。
インデックスのデータ構造はただテーブルがソートされていただけでなく、
このようなしくみで検索されていたから早くなるのです。ポイント4 「インデックスが使えない時を知る」
インデックスが役に立たない場合は以下の通りです。
・データ数が少ないとき
・後方一致検索
・前方一致検索(検索結果が多いときのみ)後方検査でインデックスが使用できない理由は、上記の図からもわかりますね。
要は「データは頭文字から照合されていくため、中間地や後方一致検索にインデックスを使用できないから」です。前方一致検索でインデックスが使用できない理由は、「頭文字が同じものが多数ある場合、結局検索する対象が多くなるから」です。
おわりに
最後までお読みいただき、ありがとうございました!
本記事の作成を通して、インデックスのしくみが理解できました。
内容に誤りがありましたら、ご指摘ください。参考書籍
オススメの技術書籍を楽天Roomで紹介しています。
「SQLの苦手を克服する本 データの操作がイメージできれば誰でもできる」
https://room.rakuten.co.jp/room_39a28b3432/items#!
- 投稿日:2020-03-29T15:18:05+09:00
MysqlでThe server quit without updating PID file エラーについて
The server quit without updating PID file
エラー
mysql server start
をすると以下のようなエラーが発生
これはmysqlのバージョンを変えたりする時に発生するエラー。つまり別のバージョンのmysqlが動いているので、そちらの実行を止める必要があるということ。ERROR! The server quit without updating PID file (/usr/local/var/mysql/user-no-MacBook-Air.local.pid).現在実行中のプロセスを止める必要がある
ps aux | grep mysql #MySQL関連のプロセス確認以下のように表示されるので、実行されているプロセスを止める。
user #これが(31827)PID→# 31827 0.3 0.2 4901664 12920 ?? S 日09PM 22:37.06 /usr/local/Cellar/mysql/8.0.19/bin/mysqld --basedir=/usr/local/Cellar/mysql/8.0.19 --datadir=/usr/local/var/mysql --plugin-dir=/usr/local/Cellar/mysql/8.0.19/lib/plugin --log-error=user --pid-file=/usr/local/var/mysql/user.pid user 31691 0.0 0.0 4271692 672 ?? S 日09PM 0:00.03 /bin/sh /usr/local/Cellar/mysql/8.0.19/bin/mysqld_safe --datadir=/usr/local/var/mysql --pid-file=/usr/local/var/mysql/user.pid user 3205 0.0 0.0 4277256 812 s001 S+ 2:49PM 0:00.00 grep mysqlプロセスの所有権がユーザ名ではない場合は以下を実行して強制的に止める
kill -9 <PID>これで所有権をとめてから実行する
mysql.server startこちらが大変参考になりました。
MySQLエラー解決法(Mac編)
こちらも参考
pidのエラー解決ちなみにPIDはProsess ID の略
- 投稿日:2020-03-29T15:11:46+09:00
docker-composeで起動してるMySQLがうまく終了しなくなってたのを直した
概要
私が頻繁に使っているローカル開発環境用の
docker-compose.yml
に含まれるMySQLが気づいたらちゃんと終了しなくなっていて、たまにデータをぶっ壊していたから直しました。原因
mysqlコンテナを
command: bash-c 'ほげほげ'
で起動していたら、PID1で起動するもんで、終了時のkillをうまくハンドリングできずに、mysqlのプロセスまでkillが届かず落ちなくて、タイムアウトでホストから落とされていた(データ壊す危険)。docker-compose.ymlにやったこと
initオプションを指定して
/dev/ihit
越しに起動してあげればこいつがちゃんとハンドリングしてくれます。
3.5だったので、3.7へバージョン上げて、下記のようにinit: true
を指定しました。version: '3.7' services: mysql: image: mysql:5.7 init: true command: bash -c ' touch /var/log/mysql/general.log && chown mysql:mysql /var/log/mysql/general.log && tail -f /var/log/mysql/general.log & /entrypoint.sh mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --general-log=true --general-log-file=/var/log/mysql/general.log --sql-mode=ONLY_FULL_GROUP_BY,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION --innodb-use-native-aio=0'before
指定していなかった時代
root@4b13f5625011:/# ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 05:53 ? 00:00:00 bash -c touch /var/log/mysql/general.log && chown mysql:mysql /var/log/mysql/general.log && tail -f /var/log/mysql/general.log & /entrypoint.sh mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --general-log=true --general-log-file=/var/log/mysql root 7 1 0 05:53 ? 00:00:00 bash -c touch /var/log/mysql/general.log && chown mysql:mysql /var/log/mysql/general.log && tail -f /var/log/mysql/general.log & /entrypoint.sh mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --general-log=true --general-log-file=/var/log/mysql mysql 8 1 5 05:53 ? 00:00:00 mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --general-log=true --general-log-file=/var/log/mysql/general.log --sql-mode=ONLY_FULL_GROUP_BY,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION --innodb-use-native-aio=0 root 14 7 0 05:53 ? 00:00:00 tail -f /var/log/mysql/general.log root 65 0 0 05:53 pts/0 00:00:00 bash root 71 65 0 05:53 pts/0 00:00:00 ps -efafter
指定した時代
root@8771d0333475:/# ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 06:00 ? 00:00:00 /sbin/docker-init -- docker-entrypoint.sh bash -c touch /var/log/mysql/general.log && chown mysql:mysql /var/log/mysql/general.log && tail -f /var/log/mysql/general.log & /entrypoint.sh mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --general- root 7 1 0 06:00 ? 00:00:00 bash -c touch /var/log/mysql/general.log && chown mysql:mysql /var/log/mysql/general.log && tail -f /var/log/mysql/general.log & /entrypoint.sh mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --general-log=true --general-log-file=/var/log/mysql root 9 7 0 06:00 ? 00:00:00 bash -c touch /var/log/mysql/general.log && chown mysql:mysql /var/log/mysql/general.log && tail -f /var/log/mysql/general.log & /entrypoint.sh mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --general-log=true --general-log-file=/var/log/mysql mysql 10 7 2 06:00 ? 00:00:00 mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --general-log=true --general-log-file=/var/log/mysql/general.log --sql-mode=ONLY_FULL_GROUP_BY,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION --innodb-use-native-aio=0 root 13 9 0 06:00 ? 00:00:00 tail -f /var/log/mysql/general.log root 67 0 1 06:00 pts/0 00:00:00 bash root 73 67 0 06:00 pts/0 00:00:00 ps -ef結果
こうするとホストから
Ctrl + C
を叩き込んでもタイム・アウトすることなく、素直に落ちてくれるようになりました。参考
- Dockerの--initフラグについて https://christina04.hatenablog.com/entry/docker-init
- 投稿日:2020-03-29T15:01:15+09:00
MySQLが起動できない エラー備忘ログ その2
エラー
スタート(起動できない)
Starting MySQL ./usr/local/Cellar/mysql/8.0.19/bin/mysqld_safe: line 144: /usr/local/var/mysql/ユーザーMBP.err: Permission denied rm: /usr/local/var/mysql/ユーザーMBP.pid: Permission denied 2020-03-29T03:04:45.6NZ mysqld_safe Fatal error: Can't remove the pid file: /usr/local/var/mysql/ユーザーMBP.pid. Please remove the file manually and start /usr/local/Cellar/mysql/8.0.19/bin/mysqld_safe again; mysqld daemon not started /usr/local/Cellar/mysql/8.0.19/bin/mysqld_safe: line 144: /usr/local/var/mysql/ユーザーMBP.err: Permission denied ERROR! The server quit without updating PID file (/usr/local/var/mysql/ユーザーMBP.pid).Permission denied ってどゆう意味
簡単に言いますと、「ファイルへのアクセス権限がない」とのこと。
参考
https://qiita.com/takuyanin/items/18590600d077df707923権限を確認する
*mysqlの該当ファイルまで移動 % cd /usr/local/var/mysql *ファイルのアクセス権限をみてみる % ls -l -rw-r----- 1 mysql wheel 2948 3 29 14:14 ユーザーMBP.err -rw-r----- 1 mysql wheel 5 3 29 14:14 ユーザーMBP.pidこんな感じで確認できました。
権限のところが、mysqlとなってます。これがいいのかよくわかりませんが、、、
この辺りの権限を変えてみました。権限を変えてみる
ユーザー権限に変更
% sudo chown -R $USER /usr/local/確認
% ls -l -rw-r----- 1 ユーザー wheel 2948 3 29 14:14 ユーザーMBP.err -rw-r----- 1 ユーザー wheel 5 3 29 14:14 ユーザーMBP.pid起動確認 (mysql.server start)
% mysql.server start Starting MySQL .... SUCCESS!うまく行きました...
MySQLのステータスを確認する。(mysql.server status)
mysql.server status ERROR! Multiple MySQL running but PID file could not be found (754 857 )複数起動していますが、PIDファイル(754 857)というのがないですよーーって事で
現在実行されているmysqlのアクティブなプロセスのIDを確認!% ps ax | grep mysql 754 s004 S 0:00.03 /bin/sh /usr/local/Cellar/mysql/8.0.19/bin/mysqld_safe --datadir=/usr/local/var/mysql --pid-file=/usr/local/var/mysql/MacBook-Pro.pid 857 s004 S 0:03.55 /usr/local/Cellar/mysql/8.0.19/bin/mysqld --basedir=/usr/local/Cellar/mysql/8.0.19 --datadir=/usr/local/var/mysql --plugin-dir=/usr/local/Cellar/mysql/8.0.19/lib/plugin --log-error=MacBook-Pro.err --pid-file=/usr/local/var/mysql/MacBook-Pro.pid 1088 s004 S+ 0:00.01 grep mysql実行されているプロセスを遮断する。kill ××
kill 754 kill 857再びMySQLを起動させる。(mysql.server start)
Starting MySQL .... SUCCESS! % mysql.server status SUCCESS! MySQL running (1242)これで全てうまくいくことができました。
番外編(Operation not permitted)
% sudo chown -R $USER /usr/localを実行したときに、
chown: /usr/local: Operation not permittedこのように表示される場合があります。
Operation not permittedとは...
OS X 10.11 El Capitanより追加されたセキュリティ機能、SIP(System Integrity Protection)によって以下の領域がガードされているそうです。
- /bin
- /sbin
- /Systemこの配下では,rootユーザでも書き込みできません。
解決策
参考
https://qiita.com/iwaseasahi/items/9d2e29b02df5cce7285d最後に
皆様の参考になれば幸いです。
- 投稿日:2020-03-29T13:33:32+09:00
フリマアプリのDB設計
フリマアプリのDB設計
プログラミングスクールの最終課題でフリマアプリを制作したので、そのDBを公開します。
全部で7テーブルです。(かなり少なくまとめました、追加実装のコメントテーブル等は無し)
途中でDB設計を何度も変更して手間がかかってしまったので、最初にしっかり考えてから制作に取り掛かることをお勧めします!usersテーブル
Column Type Options nickname string null: false string null: false encrypted_password string null: false user_image string introduction text family_name string null: false first_name string null: false family_name_kana string null: false first_name_kana string null: false birth_day date null: false Association
- has_many :products dependent: :destroy
- belongs_to :destination dependent: :destroy
- belongs_to :card dependent: :destroy
destinationテーブル
Column Type Options user_id integer null: false, foreign_key: true family_name string null: false first_name string null: false family_name_kana string null: false first_name_kane string null: false post_code string null: false prefecture string null: false city string null: false address string null: false building_name string phone_number string Association
- belongs_to :user
cardテーブル
Column Type Options user_id integer null: false, foreign_key: true customer_id string null: false card_id string null: false Association
- belongs_to :user
categoryテーブル
Column Type Options name string null: false ancestry string Association
- has_many :products
※ancestryは、gem ancestryを使用するため。productテーブル
Column Type Options name string null: false price string null: false description string null: false status string null: false size string null: false shipping_cost string null: false shipping_days string null: false prefecture_id string null: false judgment string category_id integer null: false, foreign_key: true brand_id integer null: false, foreign_key: true shipping_id integer null: false, foreign_key: true user_id integer null: false, foreign_key: true Association
- belongs_to :user dependent: :destroy
- belongs_to :category dependent: :destroy
- belongs_to :brand dependent: :destroy
has_many :images dependent: :destroy
belongs_to_active_hash :prefecture
imageテーブル
Column Type Options image string null: false product_id integer null: false, foreign_key: true Association
- belongs_to :product
brandテーブル
Column Type Options name string index: true Association
- has_many :products
ER図
これよりもコンパクトに作成できるよ!って方はぜひ教えてください
以上、最後まで読んでいただきありがとうございました。
- 投稿日:2020-03-29T09:54:04+09:00
MySQLのCRUD
MySQLによるデータベースのCRUDを学習したのでメモします。(Windows環境)
まずxamppコントールパネルからshellを開き、mysql -u rootでMySQLにログインします。
データベースの作成からやっていきます。
データベース作成
create database node_todo;データベース確認
show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | node_todo | | performance_schema | | phpmyadmin | | test | +--------------------+node_todoデータベースにtodosテーブルを作成します。
データベースディレクトリに移動
use node_todo; Database changedテーブル作成
※必ず1つはカラムを設定しないといけないcreate table todos( -> id int not null auto_increment, -> content varchar(20) not null, -> primary key (id)); +---------------------+ | Tables_in_node_todo | +---------------------+ | todos | +---------------------+カラムは カラム名 データ型 条件式の形で記述。
idを識別子とします。
テーブル内容確認
describe todos; +---------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +---------+-------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | content | varchar(20) | NO | | NULL | | +---------+-------------+------+-----+---------+----------------+作成したカラムにレコードを追加してみます
insert into todos (content) values ('勉強する');確認します。
select * from todos; +----+----------+ | id | content | +----+----------+ | 1 | ???? | +----+----------+文字コードをutf8にセットしていなかったので日本語が認識されませんでした。
とりあえず英語でやります。+----+----------+ | id | content | +----+----------+ | 1 | ???? | | 2 | learning | +----+----------+レコードの変更
update todos set content = 'learn programing' where id = 2; +----+------------------+ | id | content | +----+------------------+ | 1 | ???? | | 2 | learn programing | +----+------------------+レコード削除
delete from todos where id = 1; +----+------------------+ | id | content | +----+------------------+ | 2 | learn programing | +----+------------------+これでとりあえずデータベースのCRUDが一通りできました。