Vue3のSuspenseを使ってみた
Vue3のSuspenseについて興味があったので、試しに触ってみた内容をまとめます
Suspenseって?
非同期処理が解決されるまで、コンポーネントの代わりにフォールバックコンテンツをレンダリングする特別なコンポーネントです。 今まで、computedで変数を定義して、v-ifで表示制御していたのを簡単に書けるようにしたもののようです。
実際に書いてみた
親コンポネ
親コンポネでは以下のように書きます。
<template> <Suspense> <template #default> <ArticleList/> </template> <template #fallback> Loading... </template> </Suspense> </template> <script lang="ts"> import {defineComponent} from 'vue' import ArticleList from "./components/ArticleList.vue" export default defineComponent({ components: { ArticleList }, }) </script>
Suspenseは、2つのスロットを持っています。
default
最終的にレンダリングするコンテンツ
fallback
defaultに定義したコンテンツの非同期処理が完了するまでのコンテンツ
今回作ったサンプルだと、子コンポネの非同期処理が終わるまではLoadingと表示されます。
子コンポネ
非同期処理を行う子コンポネでは、以下のようにかきます。
<template> <div class="card-wrapper"> <div class="card" v-for="(article, key) in articles" :key="key"> <h1>{{ article.title }}</h1> <div>{{ article.content }}</div> </div> </div> </template> <script lang="ts"> import {defineComponent} from "vue"; export default defineComponent({ async setup() { const sampleArticles = [ {title: '記事A', content: '記事Aの内容'}, {title: '記事B', content: '記事Bの内容'}, {title: '記事C', content: '記事Cの内容'}, ] const fetchArticles = () => { return new Promise((resolve) => { setTimeout(() => { resolve(sampleArticles) }, 3000) }) }; const articles = await fetchArticles(); return { articles } } }); </script>
通常ではAPIから何らかのデータを取得して、取得したデータを表示すると思いますが 今回は、簡潔にするためにsetTimeoutで擬似的に非同期処理にしています。 ブログの記事一覧を引っ張ってくるAPIを叩いているイメージで書いています。
このように書くことで非同期処理が終わるまではLoadingと表示され、終わったら記事が表示されるようになります。
エラーが発生した際のハンドリング
非同期処理が失敗することもあると思います。
その場合は、onErrorCapturedでエラーを補足し、エラーを表示します。
onErrorCapturedは子孫コンポーネントからエラーが捕捉されるときに呼び出されるライフサイクルフックです。
<template> <div class="card-list"> <div v-if="error"> {{ error }} </div> <Suspense v-else> <template #default> <ArticleList/> </template> <template #fallback> Loading... </template> </Suspense> </div> </template> <script lang="ts"> import { defineComponent, ref, onErrorCaptured } from 'vue' import ArticleList from "./components/ArticleList.vue" export default defineComponent({ components: { ArticleList }, setup(){ const error = ref(null); onErrorCaptured((e) => { error.value = e return true; }); return { error } } }) </script>
まとめ
以上、Suspenseの使い方でした。 とてもシンプルに非同期処理の際の表示処理を書けるので便利ですね。
参考
Vue3 Composition APIのReactivity APIまとめ
vue3のComposition APIのrefとreactiveについて調べた際に、他のReactivity APIについても気になったので今回まとめました。
自分が理解できた箇所のみをまとめた浅い記事ですがご容赦ください。
- reactive
- ref
- computed
- readonly
- watchEffect
- watch
- unref
- toRef
- toRefs
- isRef
- isReactive
- isReadonly
- customRef
- markRaw
- shallowReactive
- shallowReadonly
- toRaw
- 終わりに
- 参考文献
reactive
オブジェクトをリアクティブなProxyオブジェクトにして返す関数です。
この際のリアクティブへの変換はディープコピーのようですが、返されるプロキシは元のオブジェクトと同一ではないようです。
const obj = reactive({count: 1}) console.log(obj.count) // 1 obj.count++ console.log(obj.count) // 2
ref
プリミティブな値をアクティブで可変なrefオブジェクトを返す関数です。
refオブジェクトにはvalueというプロパティがあり、これによってアクセスできるようです。
const count = ref(0) console.log(count.value) // 0 count.value++ console.log(count.value) // 1
computed
ゲッター関数を受け取り、ゲッターからの戻り値に対して不変のリアクティブなrefオブジェクトを返す関数です。
const count = ref(1) const plusOne = computed(() => count.value + 1) console.log(plusOne.value) // 2 count.value++ console.log(plusOne.value) // 3 plusOne.value++ // error
ゲッター関数とセッター関数を使えば、書き込み可能なrefオブジェクトを作成することもできます。
const count = ref(1) const plusOne = computed({ get: () => count.value + 100, set: val => { count.value = val - 1 } }) console.log(plusOne.value) // 101 plusOne.value = 100 console.log(count.value) // 99
readonly
オブジェクトまたはrefを受け取り、読み取り専用プロキシを返す関数です。
ネストされたプロパティも読み取り専用になるようです。
const original = reactive({ count: 0 }) const copy = readonly(original) original.count++ console.log(copy.count) // 1 // 読み取り専用だから書き換えられない copy.count++ // error
watchEffect
依存関係を事後的に追跡しながら関数をすぐに実行し、依存関係が変更されたときに関数を再実行します。
const count = ref(0) watchEffect(() => console.log(count.value)) // 0 setTimeout(() => { count.value++ // 1 }, 100)
watch
Vue2でのwatchとほぼ変わらないようです。
const state = reactive({ count: 0 }) watch( () => state.count, (count) => { sampleFunction(count) } )
複数を監視対象にすることもできるようです。
watch([fooRef, barRef], ([foo, bar], [prevFoo, prevBar]) => { /* ... */ })
unref
引数がrefの場合は内部値を返し、それ以外の場合は引数自体を返す関数です。
const refSample = ref(100) const notRefSample = 10 unref(refSample) // 100 unref(notRefSample) // 10
toRef
リアクティブなオブジェクトのある特定のプロパティをrefオブジェクトに変換する関数です。
const state = reactive({ hoge: 1, fuga: 2 }) const sampleRef = toRef(state, 'hoge') sampleRef.value++ console.log(state.hoge) // 2 state.hoge++ console.log(sampleRef.value) // 3
toRefs
リアクティブなオブジェクトの全てのプロパティをrefオブジェクトに変換する関数です。
const state = reactive({ hoge: 1, fuga: 2 }) const sampleRefs = toRefs(state) state.hoge++ console.log(sampleRefs.hoge.value) // 2 sampleRefs.hoge.value++ console.log(state.hoge) // 3 sampleRefs.fuga.value++ console.log(state.fuga) // 3
isRef
値がrefオブジェクトであるかどうかを確認する関数です。
const sampleRef = ref(1) const sampleReactive = reactive({hoge: 1}) const sample = 1 console.log(isRef(sampleRef)) // true console.log(isRef(sampleReactive)) // false console.log(isRef(sample)) // false
isReactive
値がreactiveによって作成されたProxyオブジェクトであるかどうかを確認する関数です。
readonlyによってラップしたreactiveオブジェクトでもtrueを返すようです。
const sampleRef = ref('hoge'); const sampleReactive = reactive({ fuga: 'fuga' }); const sample = 'piyo' const sampleRefAsReadonly = readonly(sampleRef); isReactive(sampleRef) // false isReactive(sampleReactive) // true isReactive(sample) // false isReactive(sampleRefAsReadonly) // true
isReadonly
値がreadonlyかどうかを確認する関数です。
const sampleRef = ref("hoge"); const sampleReactive = reactive({ fuga: "fuga" }); const sampleReadonly = readonly(sampleReactive); isReadonly(sampleRef) // false isReadonly(sampleReactive) // false isReadonly(sampleReadonly) // true
customRef
更新のトリガーを明示的に制御し、カスタムしたrefオブジェクトを返すことができる関数らしいです。
const outputLogRef = (value: string) => { return customRef((track, trigger) => ({ get() { console.log(value) track() return value }, set(newValue: string) { console.log(newValue) value = newValue trigger() } })) } const hoge = outputLogRef("") hoge.value = "hoge" // hogeが出力される hoge.value = "fuga" // fugaが出力される const fuga = hoge.value // fugaが出力される
markRaw
オブジェクトをマークして、reactiveなProxyオブジェクトに変換しないようにする関数らしいです。
const hoge = markRaw({}) console.log(isReactive(reactive(hoge))) // false
shallowReactive
ネストされたプロパティ以外をリアクティブにして返す関数です。
const state = shallowReactive({ hoge: 1, fuga: { piyo: 2 } }) // これはリアクティブ isReactive(state.hoge) // ネストされたプロパティはリアクティブじゃない isReactive(state.fuga) // false
shallowReadonly
ネストされたプロパティ以外をreadonlyにして返す関数です。
const state = shallowReadonly({ hoge: 1, fuga: { piyo: 2 } }) // これはreadonly isReadonly(state.hoge) // ネストされたプロパティはreadonlyじゃない isReadonly(state.fuga) // false
toRaw
reactiveまたはreadonlyオブジェクトの元のオブジェクトを返す関数です。
const sample = {} const reactiveSample = reactive(sample) console.log(toRaw(reactiveSample) === sample) // true
終わりに
Compotion APIのReactivity APIをまとめてみました。
Vue2のComposition APIのプラグインではまだ対応しておらず、全く見たことないものや
いつ使うのか全く分からないものもありましたが、適宜用途に合わせて使っていきたいと思います。
参考文献
Vue3 Composition APIのrefとreactiveをざっくりと理解する
導入
今週、社内でVue3についての勉強会がありました。
その中で、一番気になったComposition APIのrefとreactiveについて調べることにしました
自分が理解できた箇所のみをまとめた浅い記事ですがご容赦ください。
リアクティブとは?
refとreactiveの話をする前に、リアクティブとは何かということについて理解する必要があります。
リアクティブとは、「ある変数を書き換えた際に既に定められた関係性によって、他の変数が更新される / 事前に定めた動作が実行される」だと僕は理解しています。
簡単な例だと以下になります。
const sample = reactive({a: 1}) const sample2 = computed(() => sample.a + 100) console.log(sample2.value) // 101 sample.a = 10 console.log(sample2.value)// 110
リアクティブなデータなので、sample.aを書きかえた際にsample2が更新されています。
refとreactiveの基本
ref
プリミティブな値をアクティブで可変なrefオブジェクトを返す関数です。 refオブジェクトにはvalueというプロパティがあり、これによってアクセスできるようです。
const count = ref(0) console.log(count.value) // 0 count.value++ console.log(count.value) // 1
template内で使う場合は、refがレンダーコンテキストのプロパティとして返されるようで、valueプロパティでアクセスする必要はないようです。
<template> <div>{{ count }}</div> </template> <script> export default { setup() { return { count: ref(0) } } } </script>
reactive
オブジェクトをリアクティブなProxyオブジェクトにして返す関数です。 この際のリアクティブへの変換はディープコピーのようですが、返されるプロキシは元のオブジェクトと同一ではないようです。
const obj = reactive({count: 1}) console.log(obj.count) // 1 obj.count++ console.log(obj.count) // 2
refとreactiveの違い
リアクティブ化できる値
reativeはプリミティブな値はリアクティブにできませんが
refは、プリミティブな値以外(配列やオブジェクト等)でもリアクティブにできるようです。
// reactiveはプリミティブな値をリアクティブにすることはできない const number = reactive(0) console.log(number) // undefined // refはプリミティブな値以外(配列やオブジェクト等)でもリアクティブにできる const str = ref('hoge') const array = ref([1, 2, 3, 4]) const obj = ref({a:1, b:1}) console.log(isRef(str)) //true console.log(isRef(array)) //true console.log(isRef(obj)) //true console.log(obj.value.a) // 1 obj.value.a = 100 const sample = obj.value.a = 100 + 1 console.log(sample) // 101
リアクティブの消失
reactiveでリアクティブにしたデータを、リアクティブのまま分割して使うことは出来ないようです。 文章だとわかりにくいので、以下にサンプルのコードを書きます
count.ts(reactiveなオブジェクトをセットする関数)
import { reactive } from '@vue/composition-api' export function setCountReactive() { const obj = reactive({ count: 1 }) return obj }
home.vue
<template> <div> <button @click="incrementA()">足す</button> {{ obj.count }} <button @click="incrementB()">足す</button> {{ count }} </div> </template> <script lang="ts"> import { setCountReactive } from './count' export default { setup() { /// 通常パターン const obj = setCountReactive() function incrementA() { return obj.count++ } // リアクティブが消失してしまうパターン let { count } = setCountReactive() function incrementB() { return count++ } return { incrementA, incrementB, obj, count, } } } </script>
こういう場合に、リアクティブに扱いたい場合はToRefsを仕様して、refでラップしてあげればいいようです。
count.ts(reactiveなオブジェクトをセットする関数)
import { reactive, toRefs } from '@vue/composition-api' export function setCountReactive() { const obj = reactive({ count: 1 }) return toRefs(obj) }
ただし、refでラップする場合はvalueプロパティでアクセスする必要があります。
home.vue
<template> <div> <button @click="incrementA()">足す</button> {{ obj.count }} <button @click="incrementB()">足す</button> {{ count }} </div> </template> <script lang="ts"> import {setCountReactive} from './count' export default { setup() { /// 通常パターン const obj = setCountReactive() function incrementA() { return obj.count.value++ } // リアクティブが消失してしまうパターン let {count} = setCountReactive() function incrementB() { return count.value++ } return { incrementA, incrementB, obj, count, } } } </script>
refとreactiveの使い分け
ここまで調べて、refとreactiveはどのように使い分けるのか?という疑問がわきました。
まだ有用な使い分けの仕方はわかりませんが、refとreactiveの違いでも書いたように
プリミティブな値を使う場合はref、それ以外の場合はreactiveを使っておけば間違いはないのかなと思います。
ただ、「オブジェクトのある特定のプロパティだけリアクティブに扱いたい」などの場合はreactiveでtoRefsを使えばいいようです。
終わりに
今回は、refとreactiveについて書きました。
Vue3での変更点や便利そうな新機能など、まだまだキャッチアップできていない情報がたくさんあるので
今後も機会があれば、アウトプットしていきたいと思います。
参考
Object.assignの挙動で勘違いしていたこと
知ってる人からしたら、なにをいまさらという感じかもしれませんが Object.assignの挙動に関して勘違いしていたことがあり、業務中にハマったので備忘録程度に書きます。
勘違い1:Object.assignの返り値
Object.assignの返り値について勘違いしていました。 引数で渡したオブジェクトを合成した新しいオブジェクトを返す
のではなく
第2引数以降に渡したオブジェクトを、第1引数に渡したオブジェクトに合成して返す
ものでした。 MDNにも
Object.assign() メソッドは、すべての列挙可能なプロパティの値を、1つ以上のコピー元オブジェクトからコピー先オブジェクトにコピーするために使用されます。戻り値としてコピー先オブジェクトを返します。
Object.assign() - JavaScript | MDN
と書いてありました。
よって、以下のように
const obj1 = { a: 1, b: 2 }; const obj2 = { b: 4, c: 5 }; const obj3 = Object.assign(obj1, obj2); console.log(obj1); // { a: 1, b: 4, c: 5 } console.log(obj3); // { a: 1, b: 4, c: 5 }
obj1もobj3も中身が書き換わった状態になっています。
勘違い2:引数で渡したオブジェクトがネストされているときの挙動
Object.assignはシャローコピーのため、第2引数以降に渡したオブジェクトがネストされていた場合、オブジェクト参照がコピーされるようです。
const obj1 = {a:1, b:2}; const obj2 = {b:3, c:4, d:{a:5, b:6}}; Object.assign(obj1, obj2); console.log(obj1); // {a:1, b:3, c:4, d:{a:5, b:6}} obj1.d.a = 999; // obj1.d.aの値を更新する console.log(obj1); // {a:1, b:3, c:4, d:{a:999, b:6}} console.log(obj2); // {b:3, c:4, d:{a:999, b:6}} →オブジェクト参照がコピーされているため、obj2.d.aの値が変わっている
コピー先の変更についてコピー元に影響を及ぼしたくないときは ディープコピーしたオブジェクトをコピー元として渡すなりすればよさそうです。
おわりに
初歩的な内容にはなりましたが、このような勘違いしていたこと、業務中ハマった内容は 小さなことでも書いていきたいと思います。
参考
microCMS使ってみた
今回は以前から気になっていた、日本製Headless CMSであるmicroCMSを触ってみたのでそのことについて書きます
Headles CMSとは
Head (ビュー = 表示画面) less(ない) CMS(コンテンツ管理システム)で、表示画面がないCMSのことです。
今までのCMSは表示画面とコンテンツ管理が合わさったものでしたが、HeadlessCMSは表示画面が存在しないので、自分で自由に作成することができます。
また、サイトのある一部分のみコンテンツ管理することも可能です。
Contentfulなどが有名だと思います。
microCMSとは
導入でも書きましたが、microCMSは日本製のCMSです。
ドキュメントや、サポートまですべて日本語対応しているため、初めてHeadlessCMSを触ってみる場合には取り扱いやすいと思います。
また、完全に主観ですが管理画面が分かりやすいため、エンジニアだけでなくコンテンツを管理する編集者も使いやすいと思います。
実際に使ってみる
それでは実際にブログ記事を管理する想定で使ってみます。
アカウント作成などは省きます。
APIの作成
まずはAPIを作ります。
API名とエンドポイントを指定します。
APIで取得できるデータの形式を指定します。
今回は、記事一覧を取得するAPI作成するためリスト形式にします。
APIで管理する各フィールドを作成します。
シンプルに
- 記事タイトル
- 記事内容
- 投稿日時
を作成しました。
フィールドの種類はたくさんあるため、コンテンツの種類によって選択します。
フィールドに対して、複数のコンテンツを参照させることができます。
例えば、記事に対して複数タグなどをつけたい場合は、タグを返すAPIを作成しコンテンツを公開することで、記事一覧のAPIのタグのフィールドに複数のコンテンツを参照させることができます。
コンテンツ作成
APIは作成したので、コンテンツを作成します。
先程作成した、タグも複数紐付けることができています。
コンテンツは、予約公開することもできます。
APIプレビューで、APIのレスポンスを簡単にみることができます。
画面での表示
画面で表示させます。
APIキーを保護する
APIキーをenvファイルで保護します。
.envにAPIキーを記述
API_KEY=key
記事一覧ページ
記事を一覧表示するだけのページを作ります tailwindcssを使っています。
<template> <div class="max-w-screen-lg mx-auto mt-5 flex flex-col items-center"> <div> <article-card v-for="article in articles" :key="article.id" :article="article" /> </div> </div> </template> <script> import axios from 'axios' import ArticleCard from '~/components/ArticleCard.vue' export default { components: { ArticleCard }, async asyncData() { const { data } = await axios.get( 'https://bloglog.microcms.io/api/v1/blogs', { headers: { 'X-API-KEY': process.env.API_KEY } } ) return { articles: data.contents } }, data() { return { articles: [], } } } </script>
記事タイトル、投稿日、タグ、記事の内容が表示されていることが確認できました。
さいごに
紹介の部分でも書きましたが、microCMSは日本語のドキュメントが充実しているので、扱いやすいです。
早いペースで新機能が追加されたり、改善されているため今後もっと使いやすくなっていくのでは、と思います。
参考
LaraveのEloquentについて
LaravelのEloquentとは?
EloquentはActive RecordライクなORMで、DBとモデルを関連付けてデータ操作をすることが可能。
※Active Recordとは Active RecordはDBからデータを読み出すための手法。DBのtableまたはviewの1行が1つのクラスにラップされ、オブジェクトのインスタンスがそのデータベースの1つの行に結合される。SQLを意識せずにデータベースアクセスを行うことができる。
モデルの作成
Eloquentを利用するにはモデルが必要なのでモデルを作成する
php artisan make:model Task
モデルとDBのテーブルとの関連付けは、テーブル名を複数形、モデルを単数形で作成すると暗黙的に関連付けられる。
例) テーブル名 → tasks モデル名 → Task
テーブル名がスネークケースの場合は、モデルをキャメルケースで作成すると関連付けられる。
例) テーブル名 → task_sample モデル名 → TaskSample
上記2つを適用しない場合は、$tableプロパティで指定し関連付けることができる。
データ検索/更新などの基本メソッド
よく使う基本的なメソッドを以下にまとめる。
全件抽出 all
テーブルの全レコードを取得するメソッド 戻り値はCollectionで、Collectionの要素はModelクラスのインスタンス。
$tasks = Task::all();
PrimaryKey指定での抽出 find
,findOrFail
find
引数にPrimaryKeyを指定して、合致するレコードのみ取得する。 戻り値はModelのインスタンス。
$task = Task:find(10);
findOrFail
findと似てるが、該当レコードが見つからなかった場合、ModelNotFoundException
を投げる
try { $task = Task::findOrFail(10); } catch (ModelNotFoundException $e) { // 見つからなかった場合の処理 }
条件指定による抽出 whereXX
SQLのwhere区に相当する条件を引数に指定し、絞り込みを行えるメソッド。 XXにはテーブルのカラム名が入る。
$task = Task::whereTitle('タスクタイトル')->get();
レコードの登録 create
save
firstOrCreatre
create
配列を引数に指定して、レコードを登録できる。
Task::create([ 'title' => 'タスクタイトル', 'content' => 'タスクの内容' ]);
save
対象のモデルのインスタンスを新規作成し、各カラムの値を設定し登録できる。
$task = new Task; $task->title = 'タスクタイトル'; $task->content = 'タスクの内容';
firstOrCreatre
ある条件でレコードを抽出し、レコードが見つからない場合のみ新規登録する。
$task = Task::firstOrCreatre(['title' => 'タスクタイトル']);
レコードの更新 update
更新対象のインスタンスに対して、更新したいカラムと値の配列を引数に指定しレコードを更新できる。
$task = Task::find(1)->update(['title' => 'タスクタイトル2']);
レコード削除 delete
, destroy
delete
削除対象のインスタンスに使用し、レコードを削除できる。
$task = Task::find(1); $task->delete();
destroy
削除対象のPrimaryKeyを指定し、レコードを削除する。
Task::destroy(1);
関連があるテーブル群をまとめて操作する
DBのテーブルは他のテーブルと関連していることが多い。 例えば、ユーザー(users)は複数のタスク(tasks)を持っている、など。 Eloquentはテーブルの関係性を踏まえて処理することができるリレーションという機能を持っっている。 以下はユーザー(users)、タスク(tasks)、カテゴリー(categories)の例で記述していく。
1対1 hasOne
, belongsTo
例)書籍(books)テーブルと書籍詳細(book_details)テーブル
第1引数に関連付けるモデル名、第2引数に内部キー、第3キーに外部キーを指定することができる。
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Book extends Model { public function detail() { return $this->hasOne(BookDetail::class); } }
逆はbelongsTo
で指定することができる。
1対多 hasMany
例)ユーザー(users)テーブルとタスク(tasks)テーブル
<?php namespace App; use Illuminate\Database\Eloquent\Model; class User extends Model { public function tasks() { return $this->hasMany(Task::class); } }
hasOne
と同様に、第1引数に関連付けるモデル名、第2引数に内部キー、第3キーに外部キーを指定することができる。
逆は、belongsTo
で指定できる。
多対多 belongsToMany
例)タスク(tasks)テーブルテーブルとカテゴリ(categories)テーブル
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Task extends Model { public function categories() { return $this->belongsToMany(Category::class); } }
hasOne
と同様に、第1引数に関連付けるモデル名、第2引数に内部キー、第3キーに外部キーを指定することができる。
逆もbelongsToMany
で指定できる。
多対多では、結果コレクションに中間テーブル情報が付与されてくる。 これを取得したくないときは、モデルに$hiddenを定義することで除外できる。
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Task extends Model { // 中間テーブル情報を取得しない protected $hidden = ['pivot']; public function categories() { return $this->belongsToMany(Category::class); } }
中間テーブルのカラムを取得したい場合はモデルに取得したいカラムを指定しておき、取得時にpivotプロパティにアクセスする。
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Task extends Model { // 中間テーブル情報を取得しない protected $hidden = ['pivot']; public function categories() { return $this ->belongsToMany(Category::class, 'task_category_ref') ->withPivot('task_id', 'category_id') } }
Has Many Through
テーブルをまたぐリレーションを行うことができる。 以下の例で考える。
users ⇅ ⇅ roles tasks
rolesからusersを経由してtasksを取得したい時
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class Role extends Model { public function tasks() { return $this->hasManyThrough(Task::class, User::class); } }
第1引数にリレーションを行うモデル、第2引数には経由するモデルを指定する。
PHP勉強会に参加してきました!
昨日、PHP勉強会 #141に参加してきたので参加レポート的なものを書こうと思います。 PHP勉強会に参加するのは2回目です。
会場
いつもどおり、会場はGMO Yoursです。
タイムテーブル
Time | title |
---|---|
19:00 | 会場・飲み物の配布・名刺交換 |
19:30 | オープニング |
19:35 | 自己紹介タイム |
20:10 | メイン発表枠① |
20:30 | 懇親会前半 |
21:00 | メイン発表枠② |
21:20 | LT枠 |
タイムテーブルは大体こんな感じだったと思います。 始めて参加した時も感じましたが、自己紹介でお題を与えられそれに答えたり、発表の途中で懇親会を挟んだりすることで非常に和やかで楽しい雰囲気な勉強会になっていると思います。
ちなみに、今回の自己紹介のテーマは「この夏にハマったことは?」でした。
発表
いくつか自分が気になった発表をピックアップして紹介したいと思います。
PHP始めて1年、レガシーシステムにどう立ち向かっているか @mizuki_r
一番最初の発表はメイン発表枠の@mizuki_rさん。 自社プロダクトのビジネスモデルと乖離したレガシーシステムにどう立ち向かっているかというお話でした。 特に、ビジネス側が想像しているシステム、開発側が想像しているシステム、実際に動いているシステムがバラバラで、温度感スケジュールが合わないという話は非常に共感しました(前職で同じようなことがあったので)
P++とは何だったのか @tadsan
メイン発表枠2番目は@tadsanさん。 最近話題になったP++について、経緯と事の真相についてのお話でした。 話の主軸とは関係ないのですが、個人的には今当たり前のように使っているPHPの言語仕様がどのバージョンで追加されたのか。 バージョンアップによる言語仕様の変更がどのように行われているかを知れたのが学びになりました。
※@tadsanさんが書いたこちらのQiitaの記事もとても勉強になります。 qiita.com
ひとりで画面数1,000以上のSaaSを開発した方法 @Toshiyuki Tanakaさん
speakerdeck.com LT枠トップバッター、EC事業者向けの受注管理、物流倉庫向けの倉庫管理を統合し1つのシステムにしたサービスを提供している@Toshiyuki Tanakaさんの発表でした。 Webエンジニアが1人しかいない状況で、いかに開発していくかというお話でした。 UIを徹底的にパターン化しているというお話がとても興味深かったです。
ブラウザ上で動くPHP @niisantokyo @新倉 涼太さん
LT枠3番目?か4番目の弊社 新倉の発表です。 個人的にちょっと動作確認したいときに、ブラウザ上で動く環境があれば便利だねというお話でした。
JupyterProject Jupyter | Homeに関しては僕も使ってみたいと思いました。
総括
今回で2回目の参加でしたが、非常に楽しく有意義でした。 PHP勉強会に参加されてる方は、PHPに対する愛みたいなものを非常に感じます。 僕もそのうちLTで発表できたらなと思っています。
次回は2019年9月25日(水)に行われるようです。 ぜひ皆さん参加しましょう!