備忘録04 Flutter Firestore DatabaseへのCRUD処理
概要
firebaseのDatabaseへのCRUD処理について記録する。
CRUD処理とは
CRUD処理とはデータベースへの
・Create(作成):新しいデータの作成
・Read(参照):既存のデータの読み取り
・Update(更新):既存のデータの更新
・Delete(削除):既存のデータの削除
のことである。
事前準備
- firebaseと紐付け
- パッケージのインストール
firebaseと紐付けは以下の記事でやり方を載せているため、そっちを参照
パッケージは「firebase_core」と「cloud_firestore」をインストールする。
firebase_coreはFirebaseへの接続を可能にするためのパッケージ(プラグイン)で
cloud_firestoreはFirebaseのDateBaseへの操作を可能にするためのパッケージ(プラグイン)の認識。間違ってたらご指摘お願いします。
以下コマンドでパッケージをインストールする。
flutter pub add firebase_core
flutter pub add cloud_firestore
firebase_core: ^2.24.2
firebase_auth: ^4.16.0
もし以下エラーが出た場合は、Podfileを修正したり、再起動したら治った。
ここも今後エラーとして残していきたい。
firebaseexception ([cloud_firestore/unknown] unable to establish connection on channel.)
# Uncomment this line to define a global platform for your project
platform :ios, '11.0' # ここのコメントアウトを外す。その後pod installを流す。
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
project 'Runner', {
'Debug' => :debug,
'Profile' => :release,
'Release' => :release,
}
コードの実装
今回はコレクション名が「collections」のデータを操作する。
正直独学なので、正しいか微妙なため、ご了承ください。
実装は、TopページとListページの二つで構成。
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:testapp/firebase_options.dart';
import 'package:testapp/select/listpage.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const TopPage(),
);
}
}
FirebaseAuth auth = FirebaseAuth.instance;
class TopPage extends StatelessWidget {
const TopPage({
super.key,
});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: const Text('CRUD処理'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
// ドキュメントIDを自動発番
FirebaseFirestore.instance
.collection('collections')
.add({'column1': '登録処理実施完了(ID自動発番)'});
// ドキュメントIDを指定して登録
FirebaseFirestore.instance
.collection('collections')
.doc('create')
.set({'column1': '登録処理実施完了(ID指定)'});
Navigator.of(context).push(
PageRouteBuilder(
pageBuilder: (context, animation, secondaryAnimation) {
return const ListPage();
},
),
);
},
child: const Text('登録')),
ElevatedButton(
onPressed: () {
// ドキュメントIDを指定して更新
FirebaseFirestore.instance
.collection('collections')
.doc('create')
.update({'column1': '更新処理完了'});
Navigator.of(context).push(
PageRouteBuilder(
pageBuilder: (context, animation, secondaryAnimation) {
return const ListPage();
},
),
);
},
child: const Text('更新')),
ElevatedButton(
onPressed: () {
// ドキュメントIDを指定して削除
FirebaseFirestore.instance
.collection('collections')
.doc('create')
.delete();
Navigator.of(context).push(
PageRouteBuilder(
pageBuilder: (context, animation, secondaryAnimation) {
return const ListPage();
},
),
);
},
child: const Text('削除')),
],
),
),
);
}
}
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class ListPage extends StatefulWidget {
const ListPage({super.key});
@override
_ListPageState createState() => _ListPageState();
}
class _ListPageState extends State<ListPage> {
late Future<QuerySnapshot> _futureCollections;
@override
void initState() {
super.initState();
_futureCollections =
FirebaseFirestore.instance.collection('collections').get();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('参照結果'),
),
body: FutureBuilder<QuerySnapshot>(
future: _futureCollections,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(child: CircularProgressIndicator());
} else if (snapshot.hasError) {
return const Center(child: Text('データ取得に失敗しました'));
} else if (!snapshot.hasData || snapshot.data!.docs.isEmpty) {
return const Center(child: Text('データはありません'));
} else {
final data = snapshot.data!.docs;
return ListView.builder(
itemCount: data.length,
itemBuilder: (context, index) {
final collection = data[index];
return ListTile(
title: Text(collection['column1']),
subtitle: Text(collection.id),
);
},
);
}
},
),
);
}
}
Create(登録)
登録処理はドキュメントIDを自動発番する方法とドキュメントIDを指定して登録する方法がある。
例えばアカウント作成したときのユーザーIDをドキュメントIDとして設定して、
それに紐づいたユーザー情報などを登録できたりする。
// ドキュメントIDを自動発番
FirebaseFirestore.instance
.collection('collections')
.add({'column1': '登録処理実施完了(ID自動発番)'});
// ドキュメントIDを指定して登録
FirebaseFirestore.instance
.collection('collections')
.doc('create')
.set({'column1': '登録処理実施完了(ID指定)'});
Update(更新)
ドキュメントIDを指定して、対象のカラムを更新する。
// ドキュメントIDを指定して更新
FirebaseFirestore.instance
.collection('collections')
.doc('create')
.update({'column1': '更新処理完了'});
Delete(削除)
ドキュメントIDを指定して、対象のデータを削除する。
// ドキュメントIDを指定して削除
FirebaseFirestore.instance
.collection('collections')
.doc('create')
.delete();
Read(参照)
firebaseからデータを参照する。今回は何も条件をつけずに全件取得。
// ドキュメントIDを指定して削除
@override
void initState() {
super.initState();
_futureCollections =
FirebaseFirestore.instance.collection('collections').get();
}
↓登録後
↓更新後
↓削除後
最後に
実際はもっとカラム数(フィールド)は多いし、参照する条件とか並び替えとかがあるんで、
今後はそちらも上げていきたい
Discussion