コネヒト開発者ブログ

コネヒト開発者ブログ

僕のKotlinコントリビュータへの道のり

f:id:tommy_kw:20161106193050p:plain

こんにちは!Androidエンジニアの富田です。先月KotlinのPRが一つマージされてコントリビュータになりました!実はコントリビュータになると決心して、今年の1月からKontributeをスタートしたのですが、コントリビュータになるまでになんと「11ヶ月」もかかりました。珍しい事例だと思いますので、僕のコントリビュータまでの道のりを時系列で紹介したいと思います!

なぜKontributeしようと思ったのか?

昨年末に書いたKotlinを導入したお話というブログでたくさんのはてぶをいただき、もっと自分が会社に対して何かできることがないかと考えた時にKontributeが良いのではないのかと考えました。Kontributeの結果として、以下の2点がアウトプットできれば嬉しいと思い活動を進めました。

  • 当時は社内でOSSのコントリビュータが少なかったため、Kontributeをすると刺激を与えられるのかなと考えました。
  • 会社の知名度向上に貢献できればと考えました。

コントリビュータになるまで

Kontribute開始(2017/1〜2017/3)

Kontributeを開始しました!が、この時期は3点の問題があり、全く進捗がありませんでした。

  • 環境構築*1で心が折れる
  • どんなIssueから取り掛かればいいのかわからない
  • できそうなIssueがあっても、1、2日くらいで他のコントリビュータさんにIssueを対応されてしまう

Kontributeするための環境構築でハマっていました。今年の8月以前までビルドツールがAntでビルドが全然通らない、またテストの動かし方がわからず泣きそうでした。現在ビルドツールがAntからGradleに変わっているため、環境構築でハマることは少ないと思います。

KotlinのReadMeを見てもらうと、取り組みやすいIssueが既に管理されており、YouTrack*2の「Up For Grabs」タグが付いたものからチャレンジしてみてねとReadMeに記載されています。

We love contributions! There's lots to do on Kotlin and on the standard library so why not chat with us about what you're interested in doing? Please join the #kontributors channel in our Slack chat and let us know about your plans. If you want to find some issues to start off with, try this query which should find all Kotlin issues that marked as "up-for-grabs".

「Up For Grabs」タグが付いたIssueは以下の通りですが、何から取り掛かればいいのか当時は全くわかりませんでした。 f:id:tommy_kw:20171204225120p:plain

そのためしらじさんのHow to Kontributeブログを参考にさせていただき、まずはIntention/Inspection*3にチャレンジしようとPRを見たり、Issueを漁る時期が続いていました。

他のコントリビュータさんのPRのコードを眺めていると少しずつIntention/Inspectionについて理解ができ、それらのIssueにトライしてみました。しかし、Issueに着手する際には、Youtrack上で「僕がこのIssueをやります!」と宣言する必要があるのですが、本当にこのIssueを自分が対応できるのだろうか?と不安で調べている間に1、2日経ち、別のコントリビュータさんがすでにIssueを対応されていたケースが多かったです。

取り組み方を変えた(2017/4〜2017/7)

Intention/Inspectionの簡単なIssueであれば取り掛かれるレベルになったのですが、このままではいつまで経ってもコントリビュータになれないという危機感があり、取り組み方を変えてみました。

  • 朝1時間、昼30分、夜1時間とほぼ毎日Kontributeの時間に使う
  • 1、2日経つと誰かしらにIssueを対応されてしまうので、Youtrack上で「やります!」と宣言する

3月以前は、夜に活動していましたが次の日になると対応できそうだったIssueが既に別のコントリビュータの方が対応しているケースが多かったです。そのため朝昼晩とIssueをウォッチする時間を作りました。また、なんとなく自分でもできるかも!というIssueに対しては、「やります!」とまず宣言するようになりました。 f:id:tommy_kw:20171204203803p:plain

やっとPRを投げれるようになったのですが、まだまだマージしてもらうまでに至らず(まだレビュー中)、どうやって進めていくべきか悩んでいました。

救世主現る(2017/8〜2017/10)

なかなか成果が出ない中、救世主takahiromさんが現れました!!!!!!

takahiromさんはKotlinコントリビュータであり、Kontributeもくもく会を主催されていて僕も8月から2週間に1回の頻度で参加させていただきました。 f:id:tommy_kw:20171204201317p:plain

環境構築、PsiViewer*4、Issueについてなど教えていただきKontributeへの加速度が増しました!僕にとってはtakahiromさんやもくもく会のみなさんに教えてもらったことが大きな転機となりました。ありがとうございました!!

コントリビュータになった!(2017/11〜2017/12)

ついに11月に一つPRがマージされました!stdlibのサンプルコードの提供なのですが、僕にとっては大きな一歩です。 github.com

そして現在は以下のPRを投げています。引き続きトライしてマージされるPRの数が5、10個となるように頑張りたいと思います! f:id:tommy_kw:20171204091216p:plain

まとめ

いかがでしたか?僕のようにコントリビュータになるまで、「11ヶ月」もかかるのは珍しいと思いますが、今は環境構築でハマることも少ないと思いますし、やりやすいIssueが見つかればきっとすぐにコントリビュータになれると思います!

僕がKontributeできた要因は、継続的なトライとそれを支えて下さった社内のメンバーや社外のエンジニアさんたちのおかげです。 最終的なアウトプットの目標に掲げていた、「社内のメンバーに刺激を与えたい」、「会社の知名度向上」こちらについては、時間がかかりすぎてしまった部分はありますが、微力ながら貢献できたかなと思っています。今後の目標は、引き続きKontributeを続けて情報共有をすることです!

明日は@dachi_023さんによる「WebViewをES2015+Reactで実装した時のTips」です! qiita.com

*1:https://github.com/JetBrains/kotlin#build-environment-requirements

*2:YouTrackとは、JetBrainsのIssue管理ツール。githubのKotlinのページではIssuesタブが非表示となっています。

*3:Intentionとは、構文上の問題を改善、また最適化するための動作を提案するの機能で、いわゆるAlt+Enterのショートカットです。Inspectionは、コンパイルをする前に特定のコードの精査を行い、エラー、警告の規約違反を指摘します。Intentionで指摘されたコードの修正を行うことができます。

*4:https://plugins.jetbrains.com/plugin/227-psiviewer

リファクタリング対象を選ぶ戦略を決めよう

f:id:fortkle:20150929115239j:plain

この記事はConnehito Advent Calendar 2017の5日目の記事です。

こんにちは、ゲスの極み乙女。のライブに最近行きまくってる @fortkle です!楽曲”だけ”なら絵音は天才ですね!

さて、今日はリファクタリングについて書いていこうと思います。

フェーズによる目的の違い

スタートアップ初期の開発では、「コードが綺麗なこと」よりも「とにかく早く出してユーザーに受け入れられること」の方が重要です。

一方、サービスがある程度立ち上がった後の開発では、継続的に開発/運用するためにコードの品質を高めていく必要があります。なぜなら、コードの品質が低いと「予期せぬバグ」が発生したり、「生産性」が落ちたりするからです。

よくある問題:リファクタリング疲れ

コードの品質を高めていくために継続的なリファクタリングをしていく必要がありますが、こんな経験はないでしょうか。

  • どこからリファクタリングすればいいのか分からない
  • とりあえず目に入ったところから手当たり次第にリファクタリングを行う
  • たしかにコードは綺麗になったはずなのに、リファクタリングの努力に対して効果が実感できない
  • 効果が感じられないのでだんだん疲弊してくる

これは「リファクタリングの努力をどこに集中させるのか」という戦略が欠如しているために発生する問題です。

戦略を決めよう!

こうした問題を避けるにはどうすればよいでしょうか。 最初の努力で最大の効果を出せるようなリファクタリングを行うためにはどういった戦略が必要でしょうか。

重要なのは「推測するな、計測せよ」ということです。 データを計測することによって、「どれだけ効果が出たのか」が分かります。さらに「次のリファクタリング対象はなにか」を導くための戦略を考えることができます。

実際に戦略を考えてみよう!

データを集める

戦略を立てるために有益なデータには以下のようなものがあります。 またデータを計測するために、実際にコネヒトで使っている/検討しているツールも列挙します。

  • 不具合(バグ)
  • エラー
  • コーディング規約に対する違反
  • 性能
  • 循環的複雑度
  • CRAP (Change Risk Anti-Patterns)*1
  • 価値の高い機能
    • サービスのコア機能は何か考える
    • お金が絡む機能を考える
  • よく使われるファイル
    • 直近90日間で最も頻繁に編集された上位10ファイルを抽出するワンライナー
      • git log --since="90 days ago" --pretty=format:"" --name-only | grep "[^\+s]" | sort | uniq -c | sort -nr | head -10

戦略を考える

たとえば、「よく使われるファイル」と「CRAP」を組みわせると、「よく修正が発生しているのに質の低いファイル」を効率的に導きだすことができます。

他にも「価値の高い機能」と「不具合(バグ)/エラー」を組み合わせると最優先で対応していく必要があるものがわかりますね。

こういった戦略をチームで検討し、その戦略でリファクタリングを進めることによって効率的にコードの質を上げていくことができます。また、定期的に変化を追っていくことで「改善が上手くいっている!」というモチベーションにもなり、疲弊を防ぐこともできそうです。

まとめ

リファクタリングを始めるときに、「負の感情」から戦略もなく”えいや”で作業を進めてしまうことがあります。一時的には満たされた改善の欲求も、効果が薄いとどうしてもつらくなってきてしまいます。

そういったときに一度落ち着いて戦略を考え、チームで効率的に改善していくことで楽しく目の前のサービスと向き合えるように思います。

この記事があなたのリファクタリングライフを良いものにすることを願っています!

さて、明日は@tommykwによるオウサムな6日目の記事をお送りします。

*1:CRAPについては Hirakuさんのこのスライドが詳しい。 クソコードの測り方 - https://speakerdeck.com/hirak/kusokodofalsece-rifang

RxSwift.Variableはdeprecatedになりました

こんにちは、ガチエリアS帯のリードエンジニアの田村(@Utmrer)です。他のルールもS帯にいくため、Splatoon2サントラを聴きながら日々コーディングをしております。
この記事はConnehito Advent Calendar 2017の4日目の記事です。

今日はRxSwiftのコードを覗いていたら気づいたことを書きました。
(2017年12月4日現在の情報です)

Variableとは

VariableはRxSwiftで提供されているBehaviorSubjectのwrapperで値の取り出しや代入を直感的に扱うことができるSubjectの1つです。
MVVMでステートフルなViewModelのpropertyとして使っている人が多いのではないでしょうか。

// Example
class VM {
    let name = Variable("")
}
class VC {
    func f() {
        textField.rx.text.orEmpty
            .bind(to: vm.name)
            .disposed(by: disposeBag)
    }
}

RxSwift4でVariableはしれっとdeprecatedに

ある日RxSwift repositoryのコードを読んでいたらDeprecated.swiftという非推奨のAPIをまとめたファイルを見つけ、Variableが記載されているのを見つけました。
Warningが出ていないので気づけなかったのですが、Warningを出していないのは利用者が多いことなどが理由のようです。*1
ではVariableが非推奨になった時代に私たちはどうすればいいのでしょう。

安全なBehaviorSubjectであるBehaviorRelay

Variableのdeprecatedと同時に追加されたBehaviorRelayはBehaviorSubjectのwrapperでerrorの流れることが無い、安全なBehaviorSubjectです。この点においてVariableとほぼ同じ特性を持ちます。
Variableではvalue propertyのsetter/getterで値の操作を行っていたのが、BehaviorRelayでは下記のようなaccept() methodとvalue propertyでアクセスします。

let relay = BehaviorRelay<Int>(value: 0)
relay.asDriver()
    .drive(onNext: { value in
        print(value)
    })
    .disposed(by: disposeBag)
relay.accept(1)
print(relay.value)

Variableが非推奨になったので、同様の性質をもつBehaviorRelayに移行していくのが正道となるでしょう。

BehaviorRelayはRxCocoa

今までVariableはRxSwift moduleの一部でしたが、BehaviorRelayはRxCocoa moduleの一部になっています。BehaviorRelayと同時期に実装された安全なPublishSubjectであるPublishRelayもRxCocoaです。
これは「Relayは特定の環境で求められるものであり、Reactive Extensionsのコンセプト外である」というのが理由のようです。*2
ではRxCocoaに含まれるのが適切なのでしょうか?RelayにはCocoaへの依存はありません。ちなみに、これらRelayの設計元になったと思われるRxJavaのRxRelayはRxJavaのユーティリティという立ち位置でRxJava, RxAndroidには実装されていません。
このままRxCocoaに含まれていくような気がしますが、RxRelayとして分離されることがあるかもしれません。

BehaviorRelayへの移行はやるべき?

今すぐにでもVariableからBehaviorRelayへの移行を行うべきか、というと個人的にはちょっと待とうと思っています。なぜならば、Variableで提供されていたbind(to:)というmethodがまだBehaviorRelayには提供されていないからです。*3 RxSwiftの中の人も「ちゃんと移行方法を決めたら@availability付けて本当にdeprecatedにするよ」と言っているのでそれまで待ってもいいかなと思っています。*4
下記のようにextensionを書くことでbind(to:)を使うこともできるので待てなくなったら移行します。(副作用がちょっとわからないのでまだやってないのですが)

extension BehaviorRelay: ObserverType {
    public func on(_ event: Event<Element>) {
        switch event {
        case .next(let value):
            accept(value)
        default:
            break
        }
    }
}

まとめ

以上、RxSwift4でのVariableとBehaviorRelayについてでした。@availabilityが付くと大量のwarningが出る可能性があるので備えておきたいですね。 明日は@fortkleによるファビュラスマックスな5日目の記事をお送りします。

qiita.com

早速AWS Fargateで、ECSで動かしているタスクを動かしてみた!

こんにちは。インフラエンジニアの永井(shnagai)です。

AWS re:Invent今年は大豊作ですごいですね。 特に待ちに待っていた、フルマネージドのコンテナサービスが発表されて、ECSでEC2の管理したくないなと思ってた勢としてはとても喜びを感じています。 EKSとの棲み分けも気になる所ですね。

AWS Fargateの紹介 – インフラストラクチャの管理不要でコンテナを起動 | Amazon Web Services ブログ

今回は、検証を兼ねてECS上で動かしているバッチ処理をFargateで動かしてみたのでそのレポートをお送りします。

この記事はコネヒト Advent Calendar 2017 3日目の記事です。

qiita.com

ゴール

既にECS環境で動いているDockerイメージとタスク定義をベースに、Fargateで一本バッチ処理を動かしてみて使用感を確かめてみる。

所感

検証メインの記事なので、はじめに所感から

Fargateいいですね!まさにこの願いが叶えられたといったトコロです!! f:id:nagais:20171201190518p:plain

【良かったところ】

  • クラスタマネジメントが不要になるので、運用コストは更に減るというかオートスケールをうまく組めればほぼECSクラスタを意識する必要はなくなりそう
  • コスト面で見ても、ECSだと耐障害性を意識して、multiAZ構成で余分なリソース(EC2)を持っていたのが捨てられるのは大きいし、従量課金なので素晴らしい
  • 既にECSを使っている人なら、既存のECS資産をかなり活かせるので移行コストはほぼかからないと実際に触ってみて思った。

【気になったところ】

  • 起動がECSと比べると遅い  ※バックエンドのEC2側でDokcerイメージのキャッシュが効かないから、起動が遅くなる気がする
  • Fargateにバージョンの概念がありそうなので、そこは詳しく学びたい

検証手順

  • タスク定義とdockerイメージをus-east-1に作る
  • クラスタとタスクのワンタイム実行
  • 感想

タスク定義とdockerイメージをus-east-1に作る

現状だと、Fargateはus-east-1でしか利用できないのでまずはap-northeast-1にあるDockerイメージとタスク定義をus-east-1に移動します。

ECRのリポジトリを作ってDockerイメージ を登録する

ECRで[test]というリポジトリを作ってそこにイメージを手元からpushします。

※aws cliのリージョン(~/.aws/config)をus-east-1に変更

※AWSIDはAWSアカウント毎に割り振られるIDを入れる。(ECRのリポジトリ画面で確認出来ます)

# ECRにログイン
$ $(aws ecr get-login --region us-east-1 --no-include-email)
# リポジトリの作成
$ aws ecr create-repository --repository-name test
# dockerイメージのビルド
$ docker build -t [AWSID].dkr.ecr.us-east-1.amazonaws.com/test:latest .
# dockerイメージのpush
$ docker push [AWSID].dkr.ecr.us-east-1.amazonaws.com/test:latest
# イメージがpushされている事を確認
$ aws ecr list-images --repository-name test
{
    "imageIds": [
        {
            "imageTag": "latest",
            "imageDigest": "sha256:6cda52f3decf045bccce7e1161c6667f24958cc192fae48681014e0c8e9474f8"
        }
    ]
}

タスク定義を登録する

[タスク定義]→[新しいタスク定義の作成]

早速Fargateの文字が!! どうやらタスク定義の時点で、EC2で動かすかFargateで動かすかを選択する必要があるようです。 ※既存のタスク定義を簡単に移行する方法が提供されるとWebinerで言っていたような気がするので東京リージョンに来る時にはそこら辺が整っていることに期待ですね。

f:id:nagais:20171201171417p:plain

続いて設定画面 Task execution IAM ロールという新しい概念がありますね! 「新しいロールの作成」にしておくと最適なロールが作られます。 f:id:nagais:20171201172246p:plain

メモリ,CPUリソースは関連性があり1Gだと0.25〜0.5vCPUしか使えません。

何となくバックエンドにいるEC2が感じられますね。

1コンテナあたりに使えるメモリは、0.5G〜6G f:id:nagais:20171201172311p:plain

1コンテナあたりに使えるvCPUは、0.25vCPU〜4vCPU f:id:nagais:20171201172327p:plain

メモリ、CPUリソースを入れるとこんな形で表記されます。 f:id:nagais:20171201173243p:plain

コンテナ設定の中身はほぼECSと同じですが、ログの部分だけAuto-configureがデフォルトでチェックされています。 おそらくFargateで動くコンテナは自動的にCloudWatch Logsに送られる作りになっているようです。

f:id:nagais:20171201172821p:plain

これまでは、CloudWatch Logsのロググループは手動で作成する必要があったのですが、勝手に作ってくれてちょっと便利になってます。 f:id:nagais:20171201173507p:plain

クラスタとタスクの実行

クラスタの作成

[クラスタ]→[クラスタの作成]

クラスタテンプレートという概念が生まれていますね。 ここでは、[Networking only]を選択します。

f:id:nagais:20171201174123p:plain

次の画面でクラスタ名を入れて、クラスタを作成します。

作成されたクラスタのUIはこれまでとほぼ同じですが、一部気になる所があったので抜粋します。

  • サービスとタスクのrunning数カウントに、FargateとEC2毎の数が出るようになっている

  • Fargateのクラスタを作ってもECSインスタンスのタブは出来るみたいです。(ココらへんは今後改善されていく予感)

f:id:nagais:20171201174526p:plain

タスクの実行

いよいよ本題のタスクの実行です。

[タスク]→[新しいタスクの実行] f:id:nagais:20171201184222p:plain

ここでも新しい設定で気になったものだけピックアップしてみます。

  • Launch typeにFARGATEが選択可能になっている
  • タスク定義が選択方式になっていてこれまでの入力方式に比べるとかなりいいですね。(手動作業する時にリビジョン番号忘れがちだったので)
  • Platform versionという概念が出来ている(Fargateのバージョンの話なのかな)
  • タスク実行ボタンを教えてからの反応がちょっと悪くすこし待ちが必要です。

無事タスクが起動しました!!

f:id:nagais:20171201184802p:plain

CloudWatch Logsからも動いていることが確認出来ますね。 f:id:nagais:20171201184108p:plain

簡単にですが、FargateでECSで動かしていたタスクを実行してみました。 これからもう少しちゃんと検証してみて、あまりコストかからないと思っているので、ECS環境のFargate化に向けて動いていこうかなと思っています。

明日は、 リードエンジニア @yutmr さんによる記事をお送りします。

今更始める Firebase + BigQueryを使った サクサクデータ分析

こんにちは、サーバーサイドやっております金城(@o0h_)です。
最近通読した漫画はフットボールネーションです面白いですね・・・もちろん喧嘩稼業(9)も買いました!!!!
よろしくおねがいします。

あどべんと!

この記事は、Connehito Advent Calendarのday-2です!
やっぱりPHPer的には7.2がホットなネタ!?などとも思ったのですが、
@kiyoeshiの温かいUX改善を読んで、私もfumufumuとなりましたので
データ分析系のテーマで1本ぶっこんでみます。

ここのところ社内でデータ部分析基盤を整えていこうという動きがり、その流れで話題にした内容になります。
「Firebaseで集めた記録を、BigQueryで簡単に「生きたデータ」化しようね」という話です。

続きを読む

CakePHP3.5.6にアップデートしました

こんにちは。5年ぶりくらいにポケモンをやろうかなと思っている結城(@super_manner)です。 もう12月も目前ですっかり冬ですね、体調等くずされてないでしょうか。

さてさて、今日も元気にCakePHPのupdateをお知らせしたいと思います。 cakephp

bakery.cakephp.org

CakePHP3.5.6アップデート超訳

所感など

今回も細かなバグフィックスや、なんとなくスルーされがちな箇所が整っていったようです。 確かにsqlのdumpとかめっちゃ括弧多いなぁって思った事はあったので、実行に移してくださった世界中のエンジニアさんに感謝したいと思います。 もうじき3.6が出そうなのでそれも楽しみです!

ではまた!

個人で開発したOSSを会社のプロダクションコードに投入した話

f:id:itosho525:20171114185252p:plain

こんにちは。先日社内LTで乃木坂46の紹介をした@itoshoです。

いつもアイドルの話ばかりしたり、週末はアイドルのライブに行ったりしている僕ですが、実はちょっと前に忙しいヲタ活の合間を縫いながら、OSSをつくりまして、最終的にそれを弊社のサービスに混ぜ込んだ話を今日はしたいと思います。

会社のプロダクションコードに投入するために

せっかくOSSをつくったので、やっぱり実際に使いたい!使われたい!と思うのが自然な流れだと思いますが、いざ実際に動いている会社のプロダクションコードに実績もない個人のOSSを投入するのはつくった本人も怖いですし、周りも(一定以上の信頼関係があるとは言え)大丈夫かな?と心配してしまうと思います。

というわけで、今回個人で開発したOSSを会社のプロダクションコードに投入する際のガイドラインを作成してみました。

以下は、社内で公開したガイドラインの抜粋です。*1

心構え

  • 臆せずどんどんOSSをつくって公開していこう!
  • でも、会社のプロダクションコードに投入するのは責任を持とう!
    • これは別に不具合があった時に怒られるという意味ではなくプロフェッショナルとして誇りを持って投入していこうという意味です。
  • なので、投入する時はちゃんとチームでコンセンサスをとってから投入しましょう。
    • 相談された人も無下にせず、OSSをつくったことを讃え、リスペクトの気持ちを忘れないようにチェックしましょう。

投入するための最低条件

  • MITライセンスであること
  • コミットメッセージやIssueが英語で書かれていること
  • 各言語のパッケージ管理のスタンダードなエコシステムに乗っていること
    • バージョン管理もちゃんとすること
  • テストがきちんと書かれていること
    • CIをPassをしていること
    • カバレッジが高い水準にあること
      • OSSの特性に依ると思うので必ずしも100%である必要はありません
      • ただし、理由はちゃんとチームメンバーに説明しましょう
  • ドキュメントが整備されていること
    • 最低限使い方がREADME読んで理解出来ること
  • メンテし続けていく気概があること

投入までの流れ

  • 上記の条件を満たしてからチームメンバーに導入の相談をする。*2
  • 相談されたメンバーはコード等を確認して、適宜フィードバックを行う。
  • 必要に応じて修正を繰り返して、チームとしてGoサインが出たら、遂に投入です!

ガイドラインを作成してみて

公開してまだ日が浅いので、今後見直しが発生するかもしれませんが、一定の基準や方針が出来たのはよかったかなと思っています。

今回ガイドラインを作成したのは自分自身、基準がなくて困ったということもありますが、個人でつくったOSSが会社のシステムやサービスをよりよくするものであれば、絶対投入したほうがいいし、まして、それが心理的な障壁だけで投入を躊躇しているんだったらもったいないなと思ったので、このような方針を示してみました。

また、これにより少しでも会社のメンバーがOSSをつくるモチベーションが上がればいいなとも思っています!

ちなみに、どんなOSSをつくったの?

ここからはおまけですが、せっかくなので、どんなOSSをつくったか簡単に紹介させていただきます。

一言で言うと、複雑になりがちなDBへのクエリメソッドを簡単に記述出来るCakePHPのBehaviorプラグインです。

名前はそのままでEasy Queryと名付けました。

どれくらいEasyなの?

CakePHPではレコードの一括登録を行いたい時、 通常saveMany()という関数を利用します。

使い方としてはこんな感じです。

<?php

$data = [
    [
        'title' => 'First Article',
        'body' => 'First Article Body',
        'created' => '2012-02-22 00:00:00',
        'modified' => '2012-02-22 00:00:00'
    ],
    [
        'title' => 'Second Article',
        'body' => 'Second Article Body',
        'created' => '2012-02-22 00:00:00',
        'modified' => '2012-02-22 00:00:00'
    ]
];
$articles = TableRegistry::get('Articles');

$entities = $articles->newEntities($data);
$result = $articles->saveMany($entities);

分かりやすいですね。*3

ただ、このsaveMany()とっても便利なのですが、いわゆるBulk Insertではないので、大量のデータを一括登録したい時はパフォーマンスが問題になる場合があります。

どうしても、Cake的な書き方で、Bulk Insertしたい時はこんな書き方をします。

<?php

$data = [
    [
        'title' => 'First Article',
        'body' => 'First Article Body',
        'created' => '2012-02-22 00:00:00',
        'modified' => '2012-02-22 00:00:00'
    ],
    [
        'title' => 'Second Article',
        'body' => 'Second Article Body',
        'created' => '2012-02-22 00:00:00',
        'modified' => '2012-02-22 00:00:00'
    ]
];
$articles = TableRegistry::get('Articles');

$query = $articles->query()->insert([
    'title', 
    'body',
    'created',
    'modified'
]);
$query->clause('values')->values($data);
$result = $query->execute();

コード量はほとんど変わらないですが、やや直感的じゃなくなっちゃいますね。

というわけでBulk Insertのような複雑になっちゃうクエリを抽象化して、簡単に扱えるようにしたのが、今回開発したEasy Queryです。

Bulk Insertの例で言うと、こういう感じで書けます。

<?php

$data = [
    [
        'title' => 'First Article',
        'body' => 'First Article Body',
        'created' => '2012-02-22 00:00:00',
        'modified' => '2012-02-22 00:00:00'
    ],
    [
        'title' => 'Second Article',
        'body' => 'Second Article Body',
        'created' => '2012-02-22 00:00:00',
        'modified' => '2012-02-22 00:00:00'
    ]
];
$articles = TableRegistry::get('Articles');
$articles->addBehavior('Itosho/EasyQuery.Insert');

$entities = $this->Articles->newEntities($data);
$result = $this->Articles->bulkInsert($entities);

saveMany()と同じようなI/Fで書けるので(自分で言うのも何ですが)直感的ですね!

補足

今回はOSSの紹介がメインではないので、インストール方法や細かい利用方法はGithubやPackagistをご覧いただければと思いますが、Bulk Insert以外にもUpsertやBulk Upsertにも対応しておりますので、よかったら使ってみてください。*4

現状MySQLしかサポートしていなかったり、createdmodifiedが自動で更新されなかったりというIssueがありますが、鋭意対応中です!

最後に

僕自身もこれから乃木坂46のようなビックなOSSをつくれるように頑張るぞ!

脚注

*1:一部内容を加筆・修正しております。

*2:もちろん、つくっている途中で相談してもOKですが最終的にはこの条件を満たすようにする。

*3:timestamp behaviorを利用すれば、createdとmodifiedは省略出来ます。

*4:一生懸命つくっていますが、利用に際しては自己責任でお願いいたします。