Flutterアプリケーション開発概論

【memberIds】自分が所属するチームだけを取得するための配列を用意する

21LINE風チームタスク管理アプリを作りながら、ログイン・データベース・権限管理を学ぶ
FlutteriOSAndroidMacOSWindows基礎から学ぶ開発アプリ開発

このページでやること

このページでは、memberIds という配列を使って、「自分が所属しているチームだけ」を表示できるようにする考え方を理解します。

配列とは、複数の値をひとまとめにして持つデータです。

今回のアプリでは、各チームの中に次のような形で memberIds を保存します。

memberIds: [uid1, uid2, uid3]

これは、「このチームには、この3人が参加しています」という意味です。


今日のゴール

今日のゴールは、次の流れを理解することです。

チームを作る
↓
teams/{teamId} に memberIds を保存する
↓
ログイン中ユーザーの uid を使う
↓
自分が参加しているチームだけ取得できる

あとでトーク一覧画面では、次の検索に使います。

.where('memberIds', arrayContains: uid)

今は、まずこの memberIds を正しく保存するところまで進めます。


このページで出てくる単語

単語一言説明
memberIdsチーム参加者のuid一覧
配列複数の値をまとめたデータ
uidユーザーごとのID
arrayContains配列の中にその値が入っているか調べる条件
teams/{teamId}チーム情報を保存する場所
ownerIdチームを作った人のuid

uid は、Firebase Authenticationがユーザーごとに作るIDです。


npmや環境変数はこのページで必要?

このページでは、npmは使いません。

環境変数も設定しません。

必要なのは、すでに使っている次の2つです。

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';

このページでやることは、teams/{teamId} を作るときに memberIds を入れることです。


Step 1:main.dartを開く

次のファイルを開きます。

lib/main.dart

VS Codeを使っている場合は、ターミナルで次を実行してもOKです。

code lib/main.dart

Step 2:createTeam()を探す

main.dart の中で、次の関数を探します。

createTeam

VS Codeなら、次で検索できます。

command + F

検索文字はこちらです。

Future<void> createTeam

この createTeam() の中で、チーム情報を保存しています。


Step 3:teams/{teamId} を作る場所を見る

createTeam() の中に、次のようなコードがあります。

final teamRef = await FirebaseFirestore.instance.collection('teams').add({
  'name': teamName,
  'ownerId': user.uid,
  'memberIds': [user.uid],
  'createdAt': FieldValue.serverTimestamp(),
  'updatedAt': FieldValue.serverTimestamp(),
});

この中で、一番大事なのはここです。

'memberIds': [user.uid],

これが、今回の主役です。


Step 4:memberIds とは何か

memberIds は、そのチームに所属しているユーザーの uid 一覧です。

たとえば、チーム作成者が abc123 なら、保存される形はこうです。

memberIds: [abc123]

まだ1人しかいないので、配列の中には1つだけ入ります。

あとでメンバーが増えると、こうなります。

memberIds: [abc123, xyz789, pqr456]

つまり、

このチームに所属している人のuidを、全部まとめて持っている

ということです。


Step 5:なぜ memberIds が必要なのか

トーク一覧画面では、「自分が所属しているチームだけ」を表示したいです。

たとえば、ログイン中ユーザーの uidabc123 だとします。

そのとき、次のように探します。

memberIds に abc123 が入っているチームだけ

このために、teams/{teamId} の中に memberIds を保存しておきます。

もし memberIds がなければ、どのチームに自分が入っているかを探しにくくなります。


Step 6:arrayContains でどう使うのか

あとでチーム一覧を表示するとき、Firestoreでは次のような検索を使います。

.where('memberIds', arrayContains: uid)

これは、こういう意味です。

memberIds という配列の中に
今ログインしているユーザーの uid が入っているチームだけ取る

たとえば、

ログイン中ユーザー uid = abc123

チームデータがこうなら、

チームA memberIds: [abc123, xyz789]
チームB memberIds: [zzz111]
チームC memberIds: [abc123]

取得されるのはこうです。

チームA
チームC

チームBは取られません。


Step 7:今の段階では、まず保存できればOK

このページでは、まだ .where('memberIds', arrayContains: uid) を実装しません。

今のゴールは、チーム作成時に memberIds をちゃんと保存することです。

つまり、次の状態になっていればOKです。

final teamRef = await FirebaseFirestore.instance.collection('teams').add({
  'name': teamName,
  'ownerId': user.uid,
  'memberIds': [user.uid],
  'createdAt': FieldValue.serverTimestamp(),
  'updatedAt': FieldValue.serverTimestamp(),
});

この1行が入っていれば、あとでチーム一覧を出せる準備が整います。


Step 8:なぜ ownerId だけではだめなのか

ownerId があるなら、それで十分では?」と思うかもしれません。

でも、ownerId はチームを作った人1人しか持てません。

ownerId: abc123

これだと、あとから参加したメンバーを表せません。

たとえば、チームに3人いる場合はこうしたいです。

ownerId: abc123
memberIds: [abc123, xyz789, pqr456]

つまり、

項目役割
ownerIdチーム作成者を記録する
memberIds所属メンバー全員を記録する

役割が違うので、両方必要です。


Step 9:members と memberIds の違い

ここも大事です。

今回のアプリでは、members サブコレクションも使っています。

teams/{teamId}/members/{uid}

では、membersmemberIds は何が違うのでしょうか。

データ役割
memberIds自分の参加チームを検索するため
members名前、メール、権限を保存するため

memberIds は検索用です。

members は詳細情報用です。

この2つを組み合わせることで、

チーム一覧は速く探せる
↓
チームの中では詳しいメンバー情報も見られる

ようになります。


Step 10:完成コードの確認

createTeam() の中の teams 作成部分が、次のようになっていればOKです。

final teamRef = await FirebaseFirestore.instance.collection('teams').add({
  'name': teamName,
  'ownerId': user.uid,
  'memberIds': [user.uid],
  'createdAt': FieldValue.serverTimestamp(),
  'updatedAt': FieldValue.serverTimestamp(),
});

この中で見る場所は3つです。

name
ownerId
memberIds

特に memberIds: [user.uid] が入っているかを見てください。


Step 11:保存する

main.dart を保存します。

Macの場合:

command + S

Windowsの場合:

Ctrl + S

Step 12:実行する

ターミナルで実行します。

flutter run

すでに起動している場合は、ターミナルで r を押します。

r

必要なら R でホットリスタートします。

R

Step 13:チームを作る

アプリでログインします。

右下の + ボタンを押して、チームを作ります。

例として、次のように入力します。

開発チーム

作成後、Firebase Consoleで確認します。


Step 14:Firestoreで memberIds を確認する

Firebase Consoleを開きます。

https://console.firebase.google.com/

次の順番で確認します。

Firestore Database
↓
データ
↓
teams
↓
作成したteamId

中に、次の項目があるか確認します。

name
ownerId
memberIds
createdAt
updatedAt

特にここを見ます。

memberIds

中に、自分の uid が入っていれば成功です。

たとえば、こうです。

memberIds: ["abc123"]

Step 15:1か所だけ変更してみる

試しに、保存されるチーム名を少し変えて作ってみます。

新しいチームをもう1つ作ります。

例:

営業チーム

Firestoreを見ると、別の teamId で新しいドキュメントができているはずです。

その中にも、次の形で memberIds が入ります。

memberIds: ["同じ自分のuid"]

つまり、チームが違っても、自分が所属していれば自分のuidが入ります。

この感覚がつかめればOKです。


よくあるエラーと直し方

エラー原因直し方
memberIds がない保存コードに書いていない'memberIds': [user.uid], を追加する
memberIds が文字になっている配列ではなく文字列で保存している[user.uid] のように配列で書く
permission-deniedFirestore Rulesで拒否されている開発用Rulesを確認する
user.uid が取れないログインしていない先にログインする
チーム作成できないcreateTeam() が正しくつながっていないshowCreateTeamSheet()createTeam() を確認する

memberIds** が文字列になってしまう例**

これはダメです。

'memberIds': user.uid,

これだと、ただの文字列になります。

今回欲しいのは配列なので、こう書きます。

'memberIds': [user.uid],

四角い [] がついているのが大事です。


最短作業まとめ

読むのが大変な人は、ここだけ見てください。

1. teams作成コードを確認

final teamRef = await FirebaseFirestore.instance.collection('teams').add({
  'name': teamName,
  'ownerId': user.uid,
  'memberIds': [user.uid],
  'createdAt': FieldValue.serverTimestamp(),
  'updatedAt': FieldValue.serverTimestamp(),
});

2. memberIds は必ず配列で書く

'memberIds': [user.uid],

3. 保存して実行

flutter run

4. Firestoreで確認

Firestore Database
↓
teams
↓
作成したteamId
↓
memberIds

チェックリスト

□ main.dartを開いた
□ createTeam()を探した
□ teams/{teamId} の作成コードを見つけた
□ ownerIdがある
□ memberIdsがある
□ memberIdsに [user.uid] を入れた
□ memberIdsが配列になっている
□ 保存した
□ flutter runで起動した
□ チームを作成した
□ FirestoreでmemberIdsを確認した

ミニ確認問題

Q1. memberIds は何を保存するための項目ですか?

回答

そのチームに所属しているユーザーの uid 一覧を保存するための項目です。


Q2. なぜ memberIds は配列で保存しますか?

回答

チームには複数人が所属するからです。

1人だけではなく、複数の uid をまとめて持てるようにするためです。


Q3. ownerId だけでは足りない理由は何ですか?

回答

ownerId はチームを作った人1人しか表せません。

所属メンバー全員を表すには memberIds が必要です。


Q4. このページでnpmや環境変数は必要ですか?

回答

必要ありません。

このページでは、memberIds を配列で保存する形を整えるだけです。


このページのまとめ

  • memberIds は、チーム所属ユーザーの uid 一覧。
  • memberIds は配列で保存する。
  • チーム作成時は、最初に作成者の uid を入れる。
  • ownerId は作成者だけを表す。
  • memberIds は所属メンバー全体を表す。
  • あとで arrayContains を使って、自分が所属しているチームだけ取得できる。
  • members は詳細情報用、memberIds は検索用。
  • このページではnpmや環境変数は不要。

次のページでやること

次のページでは、where('memberIds', arrayContains: uid) を使って、ログイン中ユーザーが所属しているチームだけを一覧表示します。

教材トップへ戻る