20210909のMySQLに関する記事は7件です。

【エラー備忘録】MySQLと接続できない。SQLSTATE[HY000] [2002] Connection refused

状況 いつものように$ php artisan serveでローカルサーバーを起動し、localhost:8000にブラウザでアクセスするとエラーに。 SQLSTATE[HY000] [2002] Connection refused データベースを確認しようとTable Plusを開くと、これもエラーに。 ターミナルで$ mysql -u root -pとコマンドを実行して接続を試みるが、やはりエラーに。 Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2) 原因 /tmp/mysql.sockが…と言われているが、要はMySQLと接続できていないというエラー内容。 そういえば、macの充電が切れて一度シャットダウンされていたことを思い出した。 MySQLの起動を行ってから接続のコマンドを実行すると、無事接続ができ、Table Plusでも問題なく接続できた。 // MySQLの起動 $ mysql.server start // MySQLに接続 $ mysql -u root -p // MySQLの停止 mysql.server stop localhost:8000を指定すると、こちらも問題なく表示された。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

SQLSTATE[HY000]: General error: 1824 Failed to open the referenced table '〇〇s' (SQL: alter table `△△s` add constraint `△△s_〇〇_id_foreign` foreign key (`〇〇_id`) references `〇〇s` (`id`))

経緯 Laravel8でsail artisan migrateを実行したときに出たエラーです。Usersテーブル(親テーブル)と、外部キーuser_idを持つPostsテーブル(子テーブル)があるとして書いていきます。2つのテーブルのためのマイグレーションファイルを作り、テーブルを設定し、sail artisan migrateと実行すると SQLSTATE[HY000]: General error: 1824 Failed to open the referenced table 'users' (SQL: alter table `posts` add constraint `posts_user_id_foreign` foreign key (`user_id`) references `users` (`id`)) というエラーが出ました。 原因 エラーの内容は、「『posts』テーブルは外部キー『user_id』を持ってて『users』テーブルを参照しようとしているけど見つからないよ」というものです。これは、Postsテーブル(子テーブル)のマイグレーションファイルを作った後に、Usersテーブル(親テーブル)のマイグレーションファイルを作ったことが原因です。これにより、先にpostsテーブルを作ろうとしてしまい、参照したいusersテーブルがまだないのでエラーとなってしまいました。 解決策 先にUsersテーブル(親テーブル)後でPostsテーブル(子テーブル)を作ればPostsテーブルはUsersテーブルを参照できて、問題が解決します。ですので、sail artisan migrate:rollback(後述しますが、このときにもエラー発生します。)でロールバックした後に、現在の状態では、マイグレーションファイルの名前の日付が、子テーブルのほうが早くなっていますが、日付順を入れ替えます。 before 2021_09_07_234727_create_posts_table.php 2021_09_08_234727_create_users_table.php after 2021_09_08_234727_create_users_table.php 2021_09_09_234727_create_posts_table.php これで再度マイグレーションをすると無事成功します。 ロールバック時のエラー ロールバックを実行しようとすると、 SQLSTATE[HY000]: General error: 3730 Cannot drop table 'users' referenced by a foreign key constraint 'posts_user_id_foreign' on table 'posts'. (SQL: drop table if exists `users`) というエラーが出るかもしれません。(この例では起きないですが)。これは、Postsテーブル(子テーブル)が消されるまえにUsersテーブル(親テーブル)を消そうとしているため、「Postsテーブルのuser_idがUsersテーブルを参照してるから消せないよ」と言っているものです。usersテーブルのマイグレーションファイルにある、down時の設定をし忘れていることが原因で、ロールバック時に子テーブルを先に削除するように設定すると解決します。 before 2021_09_08_234727_create_users_table.php public function down() { Schema::dropIfExists('users'); } after 2021_09_08_234727_create_users_table.php public function down() { Schema::dropIfExists('posts'); Schema::dropIfExists('users'); } 参考 https://stackoverflow.com/questions/52377469/failed-to-open-the-referenced-table https://stackoverflow.com/questions/32524101/laravel-change-migration-order
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

外部キーを持つテーブルをマイグレーションした時のエラー'Failed to open the referenced table'の解決方法

経緯 Laravel8でsail artisan migrateを実行したときに出たエラーです。Usersテーブル(親テーブル)と、外部キーuser_idを持つPostsテーブル(子テーブル)があるとして書いていきます。2つのテーブルのためのマイグレーションファイルを作り、テーブルを設定し、sail artisan migrateと実行すると SQLSTATE[HY000]: General error: 1824 Failed to open the referenced table 'users' (SQL: alter table `posts` add constraint `posts_user_id_foreign` foreign key (`user_id`) references `users` (`id`)) というエラーが出ました。 原因 エラーの内容は、「『posts』テーブルは外部キー『user_id』を持ってて『users』テーブルを参照しようとしているけど見つからないよ」というものです。これは、Postsテーブル(子テーブル)のマイグレーションファイルを作った後に、Usersテーブル(親テーブル)のマイグレーションファイルを作ったことが原因です。これにより、先にpostsテーブルを作ろうとしてしまい、参照したいusersテーブルがまだないのでエラーとなってしまいました。 解決策 先にUsersテーブル(親テーブル)後でPostsテーブル(子テーブル)を作ればPostsテーブルはUsersテーブルを参照できて、問題が解決します。ですので、sail artisan migrate:rollback(後述しますが、このときにもエラー発生します。)でロールバックした後に、現在の状態では、マイグレーションファイルの名前の日付が、子テーブルのほうが早くなっていますが、日付順を入れ替えます。 before 2021_09_07_234727_create_posts_table.php 2021_09_08_234727_create_users_table.php after 2021_09_08_234727_create_users_table.php 2021_09_09_234727_create_posts_table.php これで再度マイグレーションをすると無事成功します。 ロールバック時のエラー ロールバックを実行しようとすると、 SQLSTATE[HY000]: General error: 3730 Cannot drop table 'users' referenced by a foreign key constraint 'posts_user_id_foreign' on table 'posts'. (SQL: drop table if exists `users`) というエラーが出るかもしれません。(この例では起きないですが)。これは、Postsテーブル(子テーブル)が消されるまえにUsersテーブル(親テーブル)を消そうとしているため、「Postsテーブルのuser_idがUsersテーブルを参照してるから消せないよ」と言っているものです。usersテーブルのマイグレーションファイルにある、down時の設定をし忘れていることが原因で、ロールバック時に子テーブルを先に削除するように設定すると解決します。 before 2021_09_08_234727_create_users_table.php public function down() { Schema::dropIfExists('users'); } after 2021_09_08_234727_create_users_table.php public function down() { Schema::dropIfExists('posts'); Schema::dropIfExists('users'); } 参考 https://stackoverflow.com/questions/52377469/failed-to-open-the-referenced-table https://stackoverflow.com/questions/32524101/laravel-change-migration-order
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【TypeORM】多対多リレーションの中間テーブルをEntityにて明記する。select join(結果の型はEntity準拠)の実装例

背景 TypeORMで最も時間がかかった多対多テーブルの実装方法について、一通りの実装例を以下に記載する。 こういう人向け 筆者自身。こういう風にコーディングしましたと自他に後で見せるため。 上記公式ドキュメントを見たりしてそのまま実装しようとしたら「えっ…中間テーブルの消し方…どうなってんの!?」と思った方 TypeORMにて多対多テーブルをどんな風に他の人が組んでるのか知りたい方 前提 TypeORMのEntityをテーブルの設計書代わりとしたい(≒Entityファイルを見れば、どういったデータベース定義か自明となるようにしたい) 上記より、フレームワーク側が勝手に定義・作成するテーブルは許容しづらい。ヒトの定義でコントロールしたい。 その上で、typescriptとtypeormが生み出す「静的型付け」「Entityにもとづくテーブル自動生成」を行いたい DBはmysql、typeormバージョンは^0.2.37 実装例 この方の記事が分かりやすかったので、上記の「ユーザ」多対多「コース」を題材とする。 user import { Entity, PrimaryGeneratedColumn, Column, BaseEntity, JoinColumn } from "typeorm"; import { date_dictionary } from "./datadirectory" import { user_course } from "./user_course"; // ユーザテーブル。 @Entity({ name: "t_user",synchronize:true }) export class t_user extends BaseEntity { // primary keyやtype、サイズ、コメントも設定できる。 @PrimaryGeneratedColumn({ name: "id", type: "bigint", comment: '自動採番ID' }) id!: number; @Column({ nullable: false, type: "varchar", length: 12, comment: "ユーザ名" }) userName!: string; // 共通カラム使用。デフォルトだとカラム名が連結される(dateTypeUpdatorみたいになる)ので、prefix:falseにしている @Column(() => date_dictionary, { prefix: false }) dateType!: date_dictionary // 中間テーブルを対象に、一対多でタイプを宣言する。 @JoinColumn() user_course!: user_course[] } course import { Entity, PrimaryGeneratedColumn, Column, BaseEntity, JoinColumn } from "typeorm"; import { date_dictionary } from "./datadirectory" import { user_course } from "./user_course"; // コードマスタ定義。 @Entity({ name: "t_course",synchronize:true }) export class t_course extends BaseEntity { // primary keyやtype、サイズ、コメントも設定できる。 @PrimaryGeneratedColumn({ name: "id", type: "bigint", comment: '自動採番ID' }) id!: number; @Column({ nullable: false, type: "varchar", length: 12, comment: "コース名" }) courseName!: string; // 共通カラム使用。デフォルトだとカラム名が連結される(dateTypeUpdatorみたいになる)ので、prefix:falseにしている @Column(() => date_dictionary, { prefix: false }) dateType!: date_dictionary @JoinColumn() user_course!: user_course[] } 中間テーブルuser_course import { Entity, Column, BaseEntity, JoinColumn, ManyToOne, PrimaryColumn } from "typeorm"; import { date_dictionary } from "./datadirectory" import { t_user } from "./t_user"; import { t_course } from "./t_course"; // 多対多テーブルのユーザ・コーステーブルの中間テーブル。 @Entity({ name: "user_course",synchronize:true }) export class user_course extends BaseEntity { // Foreign keyのための設定。 @ManyToOne(()=> t_user, user => user.id,{}) // JoinColumnでnameをしておかないとuserIdIdみたいな新規カラムを生み出してくる。 @JoinColumn({ name: "userId" }) // primary keyやtype、サイズ、コメントも設定できる。 @PrimaryColumn({ nullable: false, type: "bigint", comment: "ユーザID" }) userId!: number; @ManyToOne(()=> t_course, course => course.id) @JoinColumn({ name: "courseId" }) @PrimaryColumn({ nullable: false, type: "bigint", comment: "コースID" }) courseId!: number; @Column({ nullable: false, type: "int", comment: "コース進捗度" }) progressNum!: number; // 共通カラム使用。デフォルトだとカラム名が連結される(dateTypeUpdatorみたいになる)ので、prefix:falseにしている @Column(() => date_dictionary, { prefix: false }) dateType!: date_dictionary // ユーザ・コースを、このテーブル視点から多対一で結ぶ。 @JoinColumn() user!:t_user @JoinColumn() course!:t_course } 上記Entity+「synchronize: true」によって自動生成される中間テーブルuser_course CREATE TABLE `user_course` ( `userId` bigint(20) NOT NULL COMMENT 'ユーザID', `courseId` bigint(20) NOT NULL COMMENT 'コースID', `creator` varchar(12) DEFAULT NULL COMMENT '作成者', `createdAt` datetime(6) DEFAULT current_timestamp(6) COMMENT '作成日時', `updator` varchar(12) DEFAULT NULL COMMENT '更新者', `updatedAt` datetime(6) DEFAULT current_timestamp(6) ON UPDATE current_timestamp(6) COMMENT '更新日時', `progressNum` int(11) NOT NULL COMMENT 'コース進捗度', PRIMARY KEY (`userId`,`courseId`), KEY `FK_67a940b1d7b3cc2f0e99ab6d23b` (`courseId`), CONSTRAINT `FK_63b2ec4f34c89d4b1219f85a806` FOREIGN KEY (`userId`) REFERENCES `t_user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT `FK_67a940b1d7b3cc2f0e99ab6d23b` FOREIGN KEY (`courseId`) REFERENCES `t_course` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ManyToOneによって外部キーもしっかり宣言されている。 あまり関係ない共通部品 import { Column, UpdateDateColumn, CreateDateColumn } from "typeorm"; // @Entityが無い、テーブルとしては登録されないクラス。共通カラムを別々の場所で使う時に使える。 export class date_dictionary { @Column({ nullable: true, type: "varchar", length: 12, comment: "作成者" }) creator!: string; @CreateDateColumn({ nullable: true, type: "datetime", comment: "作成日時" }) createdAt!: Date; @Column({ nullable: true, type: "varchar", length: 12, comment: "更新者" }) updator!: string; @UpdateDateColumn({ nullable: true, type: "datetime", comment: "更新日時" }) updatedAt!: Date; } select join join系のメソッドを色々試したが、「innerJoinAndMapMany」系が一番使いやすかった。 // ユーサ~中間テーブル~コースをjoinして取得する let manymanyResult = await con.createQueryBuilder(t_user, "user") .innerJoinAndMapMany("user.user_course",user_course,"user_course", "user.id = user_course.userId ") .leftJoinAndMapMany("user_course.course",t_course,"course", "course.id = user_course.courseId AND user.id = user_course.userId") .getMany(); console.dir(manymanyResult,{depth:null}) INNER JOINs entity's table, SELECTs the data returned by a join and MAPs all that data to some entity's property. This is extremely useful when you want to select some data and map it to some virtual property. It will assume that there are multiple rows of selecting data, and mapped result will be an array. You also need to specify an alias of the joined data. Optionally, you can add condition and parameters used in condition. ↓deepl翻訳 エンティティのテーブルをINNER JOINし、結合によって返されたデータをSELECTし、そのすべてのデータをあるエンティティのプロパティにマッピングします。これは、あるデータを選択し、それをある仮想プロパティにマッピングしたい場合に非常に便利です。複数行のデータが選択されていることを想定し、マッピングされた結果は配列になります。また、結合したデータのエイリアスを指定する必要があります。オプションとして、条件や条件に使用するパラメータを追加することができます。 JoinAndMapMany系:("エイリアス.joinするエイリアス", joinするEntity,"joinするエイリアス", "join条件",{param]) 一応上記で下記のように上手くいった。 manymanyResult取得結果 [ t_user { id: '1', userName: 'user1', dateType: date_dictionary { creator: null, createdAt: 2021-09-09T00:20:25.507Z, updator: null, updatedAt: 2021-09-09T00:20:25.507Z }, user_course: [ user_course { userId: '1', courseId: '1', progressNum: 1, dateType: date_dictionary { creator: null, createdAt: 2021-09-09T00:20:48.112Z, updator: null, updatedAt: 2021-09-09T01:02:27.733Z }, course: [ t_course { id: '1', courseName: 'Aコース', dateType: date_dictionary { creator: null, createdAt: 2021-09-09T00:19:55.973Z, updator: null, updatedAt: 2021-09-09T00:43:39.479Z } } ] }, user_course { userId: '1', courseId: '2', progressNum: 2, dateType: date_dictionary { creator: null, createdAt: 2021-09-09T00:21:00.955Z, updator: null, updatedAt: 2021-09-09T01:02:28.717Z }, course: [ t_course { id: '2', courseName: 'Bコース', dateType: date_dictionary { creator: null, createdAt: 2021-09-09T00:20:06.046Z, updator: null, updatedAt: 2021-09-09T00:43:43.822Z } } ] }, user_course { userId: '1', courseId: '3', progressNum: 0, dateType: date_dictionary { creator: null, createdAt: 2021-09-09T00:44:07.213Z, updator: 'test', updatedAt: 2021-09-09T05:32:08.983Z }, course: [ t_course { id: '3', courseName: 'Cコース', dateType: date_dictionary { creator: null, createdAt: 2021-09-09T00:43:34.510Z, updator: null, updatedAt: 2021-09-09T00:43:34.510Z } } ] } ] }, t_user { id: '2', userName: 'user2', dateType: date_dictionary { creator: null, createdAt: 2021-09-09T00:20:33.497Z, updator: null, updatedAt: 2021-09-09T00:20:33.497Z }, user_course: [ user_course { userId: '2', courseId: '2', progressNum: 1, dateType: date_dictionary { creator: null, createdAt: 2021-09-09T00:21:11.953Z, updator: null, updatedAt: 2021-09-09T01:02:29.373Z }, course: [ t_course { id: '2', courseName: 'Bコース', dateType: date_dictionary { creator: null, createdAt: 2021-09-09T00:20:06.046Z, updator: null, updatedAt: 2021-09-09T00:43:43.822Z } } ] }, user_course { userId: '2', courseId: '3', progressNum: 1, dateType: date_dictionary { creator: '', createdAt: 2021-09-09T00:43:58.108Z, updator: '', updatedAt: 2021-09-09T01:02:29.877Z }, course: [ t_course { id: '3', courseName: 'Cコース', dateType: date_dictionary { creator: null, createdAt: 2021-09-09T00:43:34.510Z, updator: null, updatedAt: 2021-09-09T00:43:34.510Z } } ] } ] } ] ユーザが2人いて、それぞれ受けているコースが異なる。これらを中間テーブルに入れたコース進捗度(progressNum)含めて取得することができる。 t_user[]として取得できるため、見た目以上に入力補完が容易。 中間テーブルのEntityを既に用意しているため、insert・update・deleteなりも好きにできる。 終わりに TypeORMは公式ドキュメントに書かれていないオプションやメソッド、実装の仕方が意外とやりやすかったりする。 公式ドキュメントのようなシンプルな書き方で上手く行けばいいが、内部でやっていることが多すぎてエラーややれないこと、一目見て分からないことが増えていくため、結局ヒトが裏側に気をつけることが必要になってしまう。 ただ静的型付けとEntityにもとづくテーブル自動生成は良いと考える。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MySQLで大文字小文字区別せず重複しないようにデータを保存する

やりたかったこと case insensitiveの (最後に_ciがつく) Collation(照合順序)を選択し、UNIQUE制約を貼ったときに、本当に重複しないかを試してみました。 Character setとCollationについて 他の記事で詳しく説明されているので今回は割愛します。 utf8mb4_general_ciなど、最後が_ciとなっているものは、大文字小文字を区別しないため、'example' = 'EXAMPLE'と判定されます。 実験 DockerでMySQLを立ち上げ、複数の照合順序のテーブルを作り、重複しないかデータを投入してみます。 MySQL 5.7のDocker準備 各種ファイルを作っておきます。 docker-compose.yml version: '3' services: db: image: mysql:5.7 environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: test MYSQL_USER: user1 MYSQL_PASSWORD: password ports: - 3306:3306 volumes: - ./db/my.cnf:/etc/mysql/conf.d/my.cnf - ./db/init:/docker-entrypoint-initdb.d - ./db/data:/var/lib/mysql デフォルトのCharacter SetとCollationを定義。 ./db/my.cnf [mysqld] character-set-server=utf8mb4 collation-server=utf8mb4_general_ci [client] default-character-set=utf8mb4 collationの異なる3つのテーブルを作成します。 ./db/init/init.sql DROP TABLE IF EXISTS `utf8mb4_bin`; CREATE TABLE `utf8mb4_bin` ( `id` INT(11) AUTO_INCREMENT, `email` VARCHAR(255), PRIMARY KEY (`Id`), UNIQUE `idx_email` (`email`) ) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin; DROP TAble IF EXISTS `utf8mb4_general_ci`; CREATE TABLE `utf8mb4_general_ci` ( `id` INT(11) AUTO_INCREMENT, `email` VARCHAR(255), PRIMARY KEY (`Id`), UNIQUE `idx_email` (`email`) ) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; DROP TABLE IF EXISTS `utf8mb4_unicode_ci`; CREATE TABLE `utf8mb4_unicode_ci` ( `id` INT(11) AUTO_INCREMENT, `email` VARCHAR(255), PRIMARY KEY (`Id`), UNIQUE `idx_email` (`email`) ) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; docker-compose upをするとMySQLが立ち上がります。 データを投入してみる MySQLが立ち上がったら接続し、それぞれのテーブルにメールアドレスを入れていきます。 INSERT INTO utf8mb4_bin (email) VALUES ('sample@example.com'); INSERT INTO utf8mb4_general_ci (email) VALUES ('sample@example.com'); INSERT INTO utf8mb4_unicode_ci (email) VALUES ('sample@example.com'); 次に重複判定されるかテストしてみると、utf8mb4_binのテーブル以外は重複判定されました。 INSERT INTO utf8mb4_bin (email) VALUES ('SAMPLE@example.com'); INSERT INTO utf8mb4_general_ci (email) VALUES ('SAMPLE@example.com'); -- Duplicate entry 'SAMPLE@example.com' for key 'idx_email' INSERT INTO utf8mb4_unicode_ci (email) VALUES ('SAMPLE@example.com'); -- Duplicate entry 'SAMPLE@example.com' for key 'idx_email' insertではなく、updateのタイミングでも重複判定されました。 INSERT INTO utf8mb4_general_ci (email) VALUES ('hoge@example.com'); UPDATE utf8mb4_general_ci SET email = 'SAMPLE@example.com' WHERE email = 'hoge@example.com'; -- Duplicate entry 'SAMPLE@example.com' for key 'idx_email' 最後にalter tableでも重複判定してくれました。 ALTER TABLE utf8mb4_bin MODIFY email VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; -- Duplicate entry 'SAMPLE@example.com' for key 'idx_email' おわりに collationはあまり意識せずデフォルト値のままだと大文字小文字区別してくれないので、逆に区別したいときは注意が必要です。 普段あまり意識せずに使ってきていたので、色々実験してみて理解が深まりました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

間違えてrails db:migrationをしてしまった時の戻し方

マイグレーションしてしまったバージョンを調べる hogehoge@MacBook-Pro room-api % rails db:version Current version: 20210909002314 今回のバージョンは20210909002314なので、これをdownさせればいい 元に戻す hogehoge@MacBook-Pro room-api % rails db:migrate:down VERSION=20210909002314 == 20210909002314 AddCancelToSamples: reverting ========================== -- remove_column(:samples, :cancel, :boolean) -> 0.0248s == 20210909002314 AddCancelToSamples: reverted (0.0281s) =================
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ほけん相談SNS『ほけんとーく』を作ってみた

はじめに このサービスをチームメンバーと一緒に開発しました。 これからサービスを作りたいという人に少しでも参考になれば幸いです。 自己紹介 現在24歳、都内の文系大学を卒業して、金融企業に務めております。 2020年8月にプログラミングスクールに通い始め、プログラミングの基本を勉強いたしました。 「ほけんとーく」とは 保険の悩み共有WEBアプリ「ほけんとーく」です。 保険に対する悩みを投稿することで、様々なユーザーからアドバイスをいただき解決のヒントとなるWEBアプリです。また、悩み投稿とコメントを共有することで、他のユーザーの悩み解決のヒントとなります。多くの人に見られたくない悩みは2人だけのチャット機能で相談することができます。 このアプリが目指すことは、ユーザーが保険の悩みを共有して①解決のヒントや、②安心感、③考えるきっかけ 以上のようなものを得ることです。 (直接保険営業マンとマッチングすることや、WEB上で保険の成立を目的とはしない) URL ほけんとーく ※スマホの場合は、ホーム画面に追加することを推奨しております。 ※WEBアプリのためインストール不要 開発のきっかけ 発案者が保険会社で代理店営業を行なっていた際の経験をもとに、以下の理由でサービスの開発に至りました。 ①保険に興味はあるけど、ほけんの窓口だと無理な保険を勧められそうで不安。 ②保険加入者の多くは会社の利益を優先する営業マンより、利益を求めない知人に勧められることがきっかけ。 ③営業マンではなく、一般の人が保険に対して意見交換する場がない。 ④世に似たサービスがなかった。 使用技術/使用ツール php7/Laravel5.5 HTML5/CSS/Bootstrap/javascript mysql git/GitHub/Linux slack/trello/調整くん/diagrams ER図 操作方法 全ユーザー共通(ログイン状況を問わない)  ①ホーム画面から悩み投稿の一覧を確認することができる。  ・左上のボタンをタップするとホーム画面に遷移します。 ・各ページに10投稿まで表示しております。 ・検索窓があり、興味がある投稿に絞って投稿を探すことができます。 ②投稿一覧ページから投稿をクリックしていただくと、悩み投稿に対する解決の提案を確認することができる。  ③ユーザー名をクリックしていただくとプロフィールページに遷移して、ユーザー情報を確認することができる。  ④メニューバーからランキングページに遷移して、週間提案コメントランキングと、週間ユーザーランキング(どちらもコメントに対するいいねの数による)  ⑤お問い合わせページから運営に問い合わせることができる。 ※いただいたお問い合わせは、管理者までメールと管理側のページで確認できる。 ⑥禁止事項ページに遷移して禁止事項の一覧を見ることができる。 ログインユーザーのみ  ①悩み投稿ページに遷移し、悩み投稿を行える。(削除と編集も可)  ②ログインユーザーのプロフィールページにてプロフィールを編集することができる。  ③他ユーザーのプロフィールページからフォローとフォロー解除することができる。  ④各ユーザーのプロフィールページからフォロー一覧ページに遷移することができる。  ⑤各ユーザーのプロフィールページからフォロワー一覧ページに遷移することができる。  ※フォローするボタンを押すことによってフォローすることができます。 ⑥他ユーザーのプロフィールページからチャットページに遷移し、個人チャットすることができる。(1度チャットを行ったユーザーはチャット相手選択ページに表示されます)  ※自身の発信したチャットについては削除と編集をすることが可能です。   チャットの右下の青いボタンを押すことで編集する。赤いゴミ箱ボタンを押すことにより削除が可能。 ⑦悩み投稿に対してコメントをすることができる。(削除と編集も可)  ⑧コメントに対して「いいね」をすることができる。  ⑨フォロー者の投稿とコメントを一覧で見ることができる。 ⑩パスワードを変更できる。 ⑪プロフィールページから家族が加入している保険の情報を追加できる。  ※ご不明点はメニューバーから遷移できるお問い合わせページからお願い致します。   ※禁止事項を必ずご確認いただいた上でのご利用をお願いいたします。 ポイント 悩み投稿画面の設計 悩みを抱えているユーザーが少ない負担で最適な解決方法が見つかるように、投稿時にアドバイスするユーザーが最低限知りたい内容を盛り込む設計にしました。  具体的には、ユーザーが悩み投稿をする画面で以下のような設問を設定しました。 「どんなタイプの悩み?」「誰の悩み?」「興味のある保険はなに?」(回答はすべてチェックボタンのため回答しやすいです) これらの設問に回答いただいた上で投稿内容をみることにより、他のユーザーが悩み解決につながる適切な回答が出来ると考えます。 ファイナンシャルプランナー(FP)やライフプランアドバイザー(LPA)が保険の提案、保険の見直しをする際に、多くの質問をして情報を聞き出し出します。その上で、個人ごとに最適なプランを設計いたします。  そのため、投稿時に多くのFP、LPAが知りたい最低限の内容を盛り込むことで、悩みを抱えているユーザーが少ない負担で解決に繋がりやすい設計にしました。  保険の内容に特化したプロフィール機能の設計 アドバイスするユーザーが悩み投稿からだけでなく、悩み投稿ユーザーの背景を汲み取れるような設計。また、実際に対面で話したいとなったときに会える距離なのかが分かるために活用されることを見込んで作成いたしました。 具体的には、 プロフィール画面に以下の情報を盛り込みました。 ・年齢 ・お住みの都道府県 ・家(例、持ち家の一軒家、賃貸のマンション) ・家族構成 ・家族が加入している保険 これらの情報を用いることで最適な解決方法が提案できると考えます。 例えば、お子様がまだ小さく、この都道府県は物価も高いから、これくらいの生命保険が必要かな〜と考える事ができます。 開発で苦労した点 ・メンバーの目線あわせ 私が作りたいものをメンバーに共有することに時間がかかりました。 特に共有するために作成したDB設計や、仕様書、ページ遷移表は時間が大変かかりました。 それ以外にも、git開発のルールを共有、コーティングルールの共有、日時のslackの連絡。週次のZoom会議などで意思統一して開発を進めていきました。 結果、細かい目線合わせをすることにより、サービスが良い方向に繋がりました。 優秀なメンバーに心から感謝しております。 ・DBのカラム名を変更した際のファイルの修正作業 DBのカラム名が適切でない時に修正作業に苦労しました。様々なファイルに影響を与えていたため、手作業だと完璧に行えない可能性があり方法を模索しました。その時にgrepコマンドの使い方を知り、使いこなし修正できたことが勉強になりました。 grepコマンドを使いこなす方法 今後の計画 ・使っていただくユーザーを増やす  ・非同期通信 ・ランキング機能のパターンを増やす(月間ユーザー、月間コメント)  ・WEBサイト上にLPAによるブログ作成  ・pwa化  ・スマホアプリ化  ・チャット機能の改修
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む