- 投稿日:2021-01-13T22:00:46+09:00
Laravelで手軽にログイン認証機能を実装する
【前提条件】
Lamp環境が正常にインストール出来ている。
Node.jsのインストールが出来ている。
データ・ベースの設定が出来ている。
artisanコマンドがある程度扱える。Node.jsがインストール出来ていない方は@seiba様の記事を参照して下さい
【引用リンク】
https://qiita.com/seibe/items/36cef7df85fe2cefa3ea1、バージョンを確認する
まずはLaravelのバージョンを確認しましょう、以下のコマンドを入力して下さい。
php artisan --versionLaravelのバージョンが6系か7系かを確認します。
2、Laravel/uiをインストールする。
6系の場合は以下のコマンドでインストール
composer require laravel/ui:^1.0 --dev7系の場合は以下のコマンドでインストール
composer require laravel/ui:^2.43、認証機能を実装する
6系、7系共通で以下のコマンドを入力してログイン機能を実装する
php artisan ui vue --authこの時点ではログイン機能は完成していません、この時点でREGISTER場面を
見てみると………フロントエンド部分が実装されていません。
4、フロントエンド部分を実装する〜完成
npmをインストールする
npm installnpmをビルドする
npm run dev最期に忘れずにmigrationコマンドででログイン情報を格納するテーブルを作成する。
php artisan migration完成です
Laravelを立ち上げてみて右端のRegisterをクリックしてみる
すると先程は実装されていなかったフロントエンド部分の実装がなされている。
実際に登録してみる
番外編:どのようにデータが格納されているか
実際にパスワードが格納されているテーブルを見てみるとパスワードが暗号化されて格納されており、手軽に実装出来てかなり高度な認証機能である事がわかる。
| 1 | ララベルユーザー | laravel@gmail.com | NULL | $2y$10$KPPRJJH0fOYl1JocEdQscu3NNl5BrJU.MpEu4AY1I2ye6F5z18Zsq | NULL | 2021-01-13 12:40:02 | 2021-01-13 12:40:02 | +----+--------------------+-------------------+-------------------+--------------------------------------------------------------+----------------+---------------------+---------------------+参考サイト
【公式版】Laravel公式チュートリアル日本語訳
https://readouble.com/laravel/7.x/ja/authentication.html
- 投稿日:2021-01-13T18:14:04+09:00
Mysql2::Error: Incorrect string valueのエラーの対処
はじめに
データベースを作成してマイグレーションも実行し、「いざ、データ(日本語)を入れて動かそう!」としたところで、以下のようなエラーが。。。
Mysql2::Error: Incorrect string value: '\xE3\x82\xB2\xE3\x82\xB9...' for column 'name' at row 1どうやら文字コードが不適切らしい。。。
ということで、本記事では、このエラーについて、僕が試したことや解決策を書いていこうと思います!技術・環境
Docker/docker-compose
ruby 2.7.2
rails 6.0.2.3試したこと
①テーブルの文字コードを調べてみました。
まずは、MySQLに接続する。
$ docker-compose run web rails db次に、データベースの文字コードを調べてみる。
> show variables like '%char%'; +--------------------------+----------------------------+ | Variable_name | Value | +--------------------------+----------------------------+ | character_set_client | utf8mb4 | | character_set_connection | utf8mb4 | | character_set_database | latin1 | | character_set_filesystem | binary | | character_set_results | utf8mb4 | | character_set_server | latin1 | | character_set_system | utf8 | | character_sets_dir | /usr/share/mysql/charsets/ | +--------------------------+----------------------------+やはり、データベースの文字コードが「latin1」だった。。。
※MySQLはdefaultで「latin1」が文字コードに設定されています。②データベースの文字コードをutf8mb4に修正
僕はDockerを使用していたので、以下のようにdocker-compose.ymlを修正。
※以下の公式ドキュメントを参考にしました。
https://hub.docker.com/_/mysqldocker-compose.ymlversion: "3" services: db: image: mysql:5.7 # この下の一行を追記しました command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci environment: MYSQL_ROOT_PASSWORD: password MYSQL_USER: root ports: - "3306:3306" volumes: - ./db/mysql/volumes:/var/lib/mysql web: build: . command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" volumes: - .:/share-read ports: - "3000:3000" depends_on: - db volumes: mysql-data: driver: localデータベースの文字コードを再度調べてみる。
> show variables like '%char%'; +--------------------------+----------------------------+ | Variable_name | Value | +--------------------------+----------------------------+ | character_set_client | utf8mb4 | | character_set_connection | utf8mb4 | | character_set_database | utf8mb4 | | character_set_filesystem | binary | | character_set_results | utf8mb4 | | character_set_server | utf8mb4 | | character_set_system | utf8 | | character_sets_dir | /usr/share/mysql/charsets/ | +--------------------------+----------------------------+「よし!修正完了!」と思ったが、まだエラーが出てしまう。
もしかしたらテーブル自体の文字コードが「latin1」のまま?と思い調べてみると。。。> SHOW CREATE TABLE users; | users | CREATE TABLE `users` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, `email` varchar(255) DEFAULT NULL, # 中略 PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 |やはり、テーブルの文字コードが変わっていなかった。。。
③テーブルの文字コードをutf8mb4に修正
ということで、テーブルの文字コードを修正するのですが、10個くらいテーブルがあって一つ一つ修正するのは大変!
また、まだテーブルにデータを格納してなかったこともあり、今回はマイグレーションをやり直そうことにしました。$ docker-compose run web rails db:reset $ docker-compose run web rails db:migrateということで無事解決しました。
もし同じようなエラーが出てしまった方は、参考にしてみてください。
- 投稿日:2021-01-13T14:04:02+09:00
Bitnami Mantis のDBリストアについて
DBのリストア
テーブルがすでに存在するということで、怒られる
>mysql -u root -p bitnami_mantis < bitnami_mantis.sql Enter password: ******** ERROR 1050 (42S01) at line 30: Table 'mantis_api_token_table' already existsDB再作成
DBへ接続、DROP、確認
>mysql -u root -pパスワード mysql> drop database bitnami_mantis; Query OK, 32 rows affected (0.36 sec) mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | +--------------------+ 4 rows in set (0.02 sec) mysql> quit ByeDB作成
mysql> create database bitnami_mantis; Query OK, 1 row affected (0.01 sec) mysql> quit ByeDUMPをリストア
>mysql -u root -pパスワード -D bitnami_mantis < bitnami_mantis.sql mysql: [Warning] Using a password on the command line interface can be insecure.#参考)
データのみバックアップ
>mysqldump -u root -pパスワード -t bitnami_mantis > hogehoge.dump
リストア(なんかエラーが出る)
>mysql -u root -p bitnami_mantis < hogehoge.dump Enter password: ******** ERROR 1062 (23000) at line 33: Duplicate entry '1' for key 'mantis_bug_file_table.PRIMARY'
- 投稿日:2021-01-13T12:03:24+09:00
Formオブジェクトを用いて作成したデータを、特定のデータのみ削除する方法
要点
- メルカリクローンのアプリを作るときの参考に
- dependent: :destroy を用いて外部キーの削除制限を外す
- 下記のエラーを解消する方法
ActiveRecord::InvalidForeignKey (Mysql2::Error: Cannot delete or update a parent row: a foreign key constraint fails (`-アプリ名-_development`.`-中間テーブル名-`, CONSTRAINT `fk_rails_~~~~~` FOREIGN KEY (`-商品のテーブル名-_id`) REFERENCES `-商品のテーブル名-` (`id`))):はじめに
メルカリのようなフリマアプリを作成中で、Formオブジェクトを用いて商品にタグ付けして出品できる機能を実装する所まで行いました
各モデルとコントローラーは以下のようになります
- Item/商品
- Tag/タグ
- TagItemRelation/商品とタグの中間テーブル
- TagsItem/ ItemとTagを同時に保存するためのFormオブジェクト
/app/model/item.rbclass Item < ApplicationRecord has_many :tag_item_relations has_many :tags, through: :tag_item_relations end/app/model/tag.rbclass Tag < ApplicationRecord has_many :tag_item_relations has_many :items, through: :tag_item_relations validates :tag_name, uniqueness: true end/app/model/tag_item_relation.rbclass TagItemRelation < ApplicationRecord belongs_to :item belongs_to :tag end/app/form/tags_item.rbclass TagsItem include ActiveModel::Model attr_accessor :item_name, :tag_name with_options presence: true do validates :item_name end def save item = Item.create(item_name: item_name) tag = Tag.where(tag_name: tag_name).first_or_initialize tag.save TagItemRelation.create(item_id: item.id, tag_id: tag.id) end endコントローラー
/app/controller/items_controller.rbclass ItemsController < ApplicationController def index @items = Item.all.order('created_at ASC') end def new @item = TagsItem.new end def create @item = TagsItem.new(items_params) if @item.valid? @item.save redirect_to root_path else render :new end end private def items_params params.require(:tags_item).permit( :item_name, :tag_name ) end endその後商品閲覧機能と
問題の商品削除機能を実装した/app/controller/items_controller.rbclass ItemsController < ApplicationController before_action :set_item, only: [:show, :destroy] ### 中略 def show @tags_item = TagItemRelation.find(params[:id]) end def destroy if current_user.id == @item.user_id @item.destroy redirect_to root_path else render :show end end private ### 中略 def set_item @item = Item.find(params[:id]) @tag = Tag.find(params[:id]) end endしかし実際に出品した商品を削除してみると、、、
ActiveRecord::InvalidForeignKey (Mysql2::Error: Cannot delete or update a parent row: a foreign key constraint fails (`-アプリ名-_development`.`tag_item_relations`, CONSTRAINT `fk_rails_~~~~~~` FOREIGN KEY (`item_id`) REFERENCES `items` (`id`))):のエラーが出てしまい、商品の削除ができませんでした
調べたこと
エラー内容をよく読んでみると、商品idは中間テーブルの外部キー(foreign key)に含まれて
デリートやアップデートができないよ!と書かれているのがわかりますそこで外部キーについて調べてみると、、、
外部キー(外部制約キーとも)は、よくマイグレーションファイルなどに書いてるデータベースのキーで
データベースの特定の項目に好き勝手な値を入れることを防ぎ、外部の項目から選んで入れる制約を持ち
主に外部キーのテーブルから主キーのテーブルのデータに対して、変更を制限するものだそうです
今回の場合外部キーのテーブルはtag_item_relations、主キーのテーブルはitemになることが分かりますね外部キーの設定変更
今回のエラーの原因はマイグレーションファイルに記載した外部キー(foreign_key: trueのやつ)でした
ですがマイグレーションファイルごと書き換えてしまうと別の不具合が起きてしまう恐れがあります
今回はdestoryで外部キーとして設定している項目を削除させるように、dependent: :destroyを設定しようと思います
この簡単な設定により不具合なく商品の削除ができるようになります/app/model/item.rbclass Item < ApplicationRecord has_many :tag_item_relations, foreign_key: :item_id, dependent: :destroy has_many :tags, through: :tag_item_relations end参考にしたサイト
関連記事
- 投稿日:2021-01-13T08:02:14+09:00
多対多リレーションを修正するストアドプロシージャ
下の画像の右側と左側が多対多のテーブルのレコードで、真ん中の薬のカプセルみたいなやつが、中間テーブルのレコードとします。
具体的にいうと、左側の「LIZ」、「LITA」はアーティストで、右側の「KING」というのは楽曲です。
「KING」という2つのレコードは同じものを意図しているのにもかかわらず、IDが異なるので違うものとして扱われてしまっています。
なのでMAINを残し、SUBを消すために、以下のように中間テーブルをUPDATEしたのち、いらなくなったSUBレコードを削除します。
これをするSQLは以下のようになります。
-- 左側のテーブル : artists -- 中間テーブル : music_artists -- 右側のテーブル : music update music_artists set music_id = {main} where music_id = {sub}; delete from music where id = sub;これでうまくいきそうですが、以下のような場合にうまくいきません。
UPDATEすると複合主キーの主キー制約に反するので、UPDATEできないのです。上記のパターンが
- UPDATE → DELETE
のパターンが必要であるのに対し、今回のパターンでは
- DELETE → DELETE
する必要があります。
これを振り分けるためには、ストアドプロシージャでカーソル操作する必要があります。
MySQLです。CREATE PROCEDURE `join_music`(main INT, sub INT) BEGIN DECLARE current_artist_id INT; DECLARE done INT DEFAULT FALSE; DECLARE cur CURSOR FOR SELECT artist_id FROM music_artists WHERE music_id = sub; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; OPEN cur; cur_loop: LOOP IF done THEN LEAVE cur_loop; END IF; FETCH cur INTO current_artist_id; IF EXISTS (SELECT * FROM music_artists WHERE artist_id = current_artist_id AND music_id = main) THEN DELETE FROM music_artists WHERE artist_id = current_artist_id AND music_id = sub; ELSE UPDATE music_artists SET music_id = main WHERE artist_id = current_artist_id AND music_id = sub; END IF; END LOOP; CLOSE cur; DELETE FROM music WHERE id = sub; ENDちょっとパターンを考慮するだけでこんな複雑になるんですね。