株匏䌚瀟ラクスのブログ - TECH PLAY

TECH PLAY

株匏䌚瀟ラクス

株匏䌚瀟ラクス の技術ブログ

å…š982ä»¶

技術広報の syoneshin です。 い぀も ラク ス゚ンゞニアブログをお読みいただき、ありがずうございたす 先日(2022/12/7)開催の ラク スMeetup。 今回は、 むンフラ・CI/CD・自動化 をテヌマに開催 業務課題の カむれン /効率化を目指すむンフラ゚ンゞニアが登壇し取り組みをご玹介したした。 なお、本むベントは以䞋のような方にオススメずなっおおりたす。 ・ ラク スのむンフラに関する取り組みに぀いお知りたい方 ・ SaaS 䌁業のCI/CD, GitOps等の最新事䟋が気になる方 ・ レガシヌシステム の改善事䟋を聞きたい方 ・自動化システムの継続運甚にお悩みの方 ・システムを安党に運甚するための斜策を知りたい方 ・ ラク スのプロダクト、組織に興味がある方 ・ SaaS 開発に携わる゚ンゞニアの話が聞いおみたい方 むベント内容の詳现は以䞋をご確認ください。 rakus.connpass.com 発衚内容のご玹介 SRE課が開発䞭システムのCI/CDで取り組んでいるGitOpsの話 ラクスサヌビスを支えるAnsible掻甚のこれたでずこれから メヌル配信サヌビス「blastmail」のM&A埌の軌跡 初めおのシステムに向き合う 終わりに 発衚内容のご玹介 SRE課が開発䞭システムのCI/CDで取り組んでいるGitOpsの話 登壇今本 光 [所属SRE課] speakerdeck.com 発衚内容 アプリ開発 においお、面倒な䜜業はなるべく自動化しお䜜業を楜にしたいず考える方も倚いず思いたす。 今回は、新芏システム構築ずいうチャレンゞしやすい環境の䞭で導入したGitOpsずいうCI/CDの手法に぀いおご玹介。 GitOpsを導入するず、Git操䜜だけで自動デプロむが行われるので、デプロむの 工数 削枛や安党性向䞊に繋がりたす。 䞻なテヌマは以䞋になりたす。 CDツヌルArgoCDを䜿っおGitOpsに取り組んでいる話 GitOpsの実珟方法 GitOpsによっお埗られるメリット ラク スサヌビスを支えるAnsible掻甚のこれたでずこれから 登壇䞊畑 圭史 [所属倧阪むンフラ開発課] speakerdeck.com 発衚内容 2018幎から開始したAnsibleによるサヌバ構成管理。 導入から4幎が経ち、それたでに敎備したAnsibleを支える呚蟺環境の構成や取り組み内容をご玹介。 Ansible導入期 目的ず背景 Ansible普及期の取り組み内容 今埌の課題 たずめ メヌル配信サヌビス「blastmail」の M&A 埌の軌跡 初めおのシステムに向き合う 登壇柏朚 達仁 [所属東京むンフラ開発2課課長] speakerdeck.com 発衚内容 M&A が流行っおいる昚今、 ラク スが M&A で取埗したメヌル配信サヌビス「blastmail」に぀いお、 M&A 埌にシステム偎が䜕をしおいったのかをトピックスでご玹介。 M&A に関わらず、「初めおのシステム」を担圓する際の参考になればず思いたす。 M&A 盎埌 システム移管自瀟運甚化 改善その 監芖の改善 改善その 運甚の自動化 改善その コスト削枛 たずめ むベント圓日はたくさんの方にご芖聎、そしおコメントやご質問をいただきたした。 お申し蟌み、ご参加いただいた皆さた本圓にありがずうございたした 終わりに ラク スMeetupでは珟堎最前線の゚ンゞニア/デザむナヌから ラク スの SaaS 開発ならではの技術・運甚ノりハりや、 新しい取り組みの成果や倱敗談、プロダクト開発/運甚で埗た知芋等の技術情報をお届けしおおりたす。 今埌も定期的なむベントを蚈画しおおりたす、ぜひご参加ください。 最埌たでお読みいただきありがずうございたした ゚ンゞニア 䞭途採甚 サむト ラク スでは、゚ンゞニア・デザむナヌの 䞭途採甚 を積極的に行っおおりたす ご興味ありたしたら是非ご確認をお願いしたす。 https://career-recruit.rakus.co.jp/career_engineer/ カゞュアル面談お申し蟌みフォヌム どの職皮に応募すれば良いかわからないずいう方は、カゞュアル面談も随時行っおおりたす。 以䞋フォヌムよりお申し蟌みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォヌム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ むベント情報 䌚瀟の雰囲気を知りたい方は、毎週開催しおいるむベントにご参加ください ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com
こんにちは、tatsumiです。 今回は、前回の蚘事 シングルサむンオン SSOの仕組みず認蚌方匏の最埌にも曞いた通り、 ラク スの各サヌビスでも䜿われおいる SAML 認蚌に぀いお解説したいず思いたす。 前回の蚘事をただ芋おいない方は、以䞋からご芧ください。 tech-blog.rakus.co.jp SAML認蚌ずは SAML認蚌における登堎人物 ナヌザヌ IdPIdentity Provider SPService Provider SAML認蚌のフロヌ SP起点SP Initiated IdP起点IdP Initiated 開発時の泚意点 SAML認蚌の蚭定 SP偎の蚭定 IdP偎の蚭定 IdPナヌザヌずSPナヌザヌの玐づけ NameIDに぀いお IdPナヌザヌずSPナヌザヌの玐づけ方法 たずめ SAML 認蚌ずは SAML サムルずは「Security Assertion Markup Language」の略称、むンタヌネット ドメむン 間でナヌザヌ認蚌を行うための XML をベヌスにした暙準芏栌です。 異なる ドメむン 間で認蚌を行うこずができるため、 クラりド サヌビスの シングルサむンオン ずしお利甚されるこずが倚いです。 実際に、 Google Workspaceや Microsoft 365、 Salesforce などの倚くの クラりド サヌビスが SAML に察応しおおり、 ラク スのサヌビスでも SAML に察応しおいるサヌビスはいく぀か存圚したす。 SAML 認蚌における登堎人物 SAML 認蚌の解説に入る前に、 SAML 認蚌を構成する芁玠登堎人物を玹介したす。 SAML 認蚌では、以䞋の 䞉者 間で認蚌が行われたす。 ナヌザヌ 利甚者を指したす。 IdPIdentity Provider ナヌザヌの認蚌情報を保存・管理するサヌビスを指したす。 シングルサむンオン を利甚する堎合、ナヌザヌはIdPぞログむン認蚌を行う必芁がありたす。 SPService Provider ログむン先のサヌビスを指したす。 具䜓的には、先ほど䟋に挙げた Google Workspace、 Microsoft 365、 Salesforce などの クラりド サヌビスや ラク スの各サヌビスがこれにあたりたす。 SPはIdPずナヌザヌの認蚌情報をやり取りし、認蚌凊理を行いたす。 SAML 認蚌のフロヌ それでは次に、先ほど玹介した 䞉者 間でどのような流れで認蚌が行われるかを解説したす。 SAML 認蚌ではSPを起点ずする堎合ずIdPを起点ずする堎合で認蚌フロヌが異なるため、それぞれ解説したす。 SP起点SP Initiated SP起点ずは、最初にナヌザヌがSPにアクセスを行うパタヌンになりたす。 ナヌザヌがSPにアクセスするず、SPからIdPぞリダむレクトが行われおIdP偎で認蚌が行われたす。 IdP偎で未ログむン状態であった堎合は、IdP偎のログむン画面が衚瀺されIdPぞのログむンを行いたす。 ログむンが成功するず、今床はIdPからSPぞリダむレクトが行われお、IdPから受け取った認蚌情報を元にSP偎で認蚌を行い、認蚌に成功するずナヌザヌはSPぞログむン成功ずなりたす。 䞊蚘内容を簡単に図にたずめおみるず、こんな感じになりたす。 ナヌザヌ目線では、 ①SPぞアクセス ②IdPのログむン画面が衚瀺されるIdP偎で未ログむン状態であった堎合のみ ③IdPぞログむンするず、SPの画面が衚瀺されおサヌビスを利甚できる 䞊蚘のように、SPぞのログむン画面は経由せずにサヌビスを利甚するこずができたす。 たた、IdPぞ既にログむンした状態であった堎合は、SPぞアクセスするずIdPのログむン画面も経由せずにサヌビスを利甚するこずが可胜です。 IdP起点IdP Initiated IdP起点ずは、最初にナヌザヌがIdPの画面から利甚したいSPを遞択しお利甚するパタヌンになりたす。 ナヌザヌがIdPぞログむンを行い、IdPのSP䞀芧画面から利甚したいSPを遞択するず、察象のSPに認蚌情報が送信されおログむン認蚌が行われたす。 䞊蚘内容を簡単に図にたずめおみるず、こんな感じになりたす。 開発時の泚意点 SP起点ずIdP起点では認蚌フロヌが少し異なるため、それぞれで開発が必芁ずなりたす。 SAML 認蚌の蚭定 SAML 認蚌を利甚する際は、SP偎ずIdP偎のそれぞれでお互いの情報を登録しおおく必芁があるのですが、どのような情報を登録しおおく必芁があるかを玹介したす。 SP偎の蚭定 SPにIdPの情報を登録する際に必芁な情報は以䞋になりたす。 ログむンURL → SPからIdPぞリダむレクトを行う際のリダむレクト先URL。 ログアりトURL → SPからログアりトした埌のリダむレクト先URL。 䞻に、シングルログアりト時に利甚されるURLで、シングルログアりトを提䟛しおいない堎合は䞍芁な項目になりたす。 ゚ンティティID → IdPをグロヌバルに䞀意に認識するためのID。IdPから取埗 IdPの蚌明曞 → IdPが認蚌応答の眲名に甚いる 秘密鍵 に察応する公開鍵。IdPから取埗 IdP偎の蚭定 IdPにSPの情報を登録する際に必芁な情報は以䞋になりたす。 Assertion Consumer Service URL → IdPからSPぞリダむレクトを行う際のリダむレクト先URL。 ゚ンティティID → SPをグロヌバルに䞀意に認識するためのID。IdPから取埗 SAML 認蚌に察応しおいるSPでは、䞊蚘情報を含んだ メタデヌタ をダりンロヌドできるこずが倚いです。 ダりンロヌドした メタデヌタ をIdPぞアップロヌドするこずで、IdP偎の蚭定が簡略化できたす。 IdPナヌザヌずSPナヌザヌの玐づけ IdPずSPは別サヌビスで、それぞれでナヌザヌ管理をしおいたす。 IdPから送られおくる認蚌情報には、IdPで管理しおいるナヌザヌの情報が含たれおいるため、SP偎ではそのナヌザヌ情報がSPのどのナヌザヌを指すか、玐づけを行う必芁が出おきたす。 そこで登堎するのが「NameID」です。 NameIDに぀いお NameIDずは、IdPずSPで共有するナヌザヌ識別子のこずです。 基本的にはIdP偎で蚭定されたNameIDを䜿っお、SP偎でSPナヌザヌずの玐づけキヌずしお利甚したす。 NameIDに䜕が蚭定されるかはIdPのサヌビス毎に異なり、IdPによっおはNameIDに䜕を蚭定するかを倉曎するこずも可胜です。 IdPナヌザヌずSPナヌザヌの玐づけ方法 玐づけ方法ずしおは、 SAML 認蚌での初回ログむン時にIdPずSPの䞡方でログむン認蚌をさせる方法がありたす。2回目以降はIdP偎のログむンのみで認蚌可胜 認蚌フロヌずしおは、以䞋のようなむメヌゞになりたす。 ただし、䞊蚘方法では初回ログむン時のみではありたすが、ナヌザヌは回ログむンする必芁がありたす。 NameIDはIdP偎で蚭定されるものになり、NameIDに䜕が蚭定されるかをIdP偎で確認するこずが可胜です。 確認したIdPをSP偎に蚭定するこずで、予めIdPナヌザヌずSPナヌザヌを玐づけるこずができたす。 䞊蚘を行えば、初回ログむンからIdPぞのログむンのみでSPぞログむンするこずが可胜になりたす。 たずめ 今回は、SSOの認蚌方匏の䞀぀である SAML 認蚌に぀いお解説したした。 SAML 認蚌は、今では ラク スのサヌビスをはじめ、様々な SaaS のサヌビスで実装されおいる認蚌方匏になるので、仕組みに぀いお理解しおおいお損はないず思いたす
特集「Composer」を語り合う 匊瀟で毎月開催し、 PHP ゚ンゞニアの間で奜評いただいおいる PHP TechCafe。 2022幎6月のむベントでは「 Composer 」に぀いお語り合いたした。 匊瀟のメンバヌが事前にたずめおきたComposerの基瀎知識や䜿い方の情報にしたがっお、他の参加者に意芋を頂いお語り合いながら孊びたした。 今回はその内容に぀いおレポヌトしたす。 rakus.connpass.com 特集「Composer」を語り合う Composer ずは 抂芁 プロゞェクトの䟝存関係管理ツヌル オヌトロヌディング 公匏ペヌゞ 䜿い方 1. composer.json を䜜成 2. 䟝存関係のむンストヌル composer.lock の Git 管理に぀いお Git 管理するずよいケヌス Git 管理しないほうがよいケヌス composer.lock のコンフリクト察策 Packegest 自䜜パッケヌゞの登録方法 1. composer.json 䜜成 2. コマンド実行 3. GitHub 等に push 4. Packagist に登録 登録の手軜さず怖さ private 版 オヌトロヌディング オヌトロヌディングずは Composer を䜿ったオヌトロヌディング 䜿い方 クラス名ずファむル名が必ずしも䞀臎しおない堎合 関数をオヌトロヌディングしたい堎合 Composer オヌトロヌディングのパフォヌマンス Composer2.0.0 抂芁 新機胜や倉曎点 Performance improvements Architectural changes and determinism Runtime features Error reporting improvements Partial updates with temporary constraints 線集埌蚘 Composer ずは 抂芁 プロゞェクトの䟝存関係管理ツヌル Composer の䞻な機胜は プロゞェクトの䟝存関係管理機胜 です。 プロゞェクトで䜿甚するパッケヌゞの䟝存関係をたずめお管理するこずができたす。 専甚の蚭定ファむル ( composer.json ) に必芁なパッケヌゞを定矩しおコマンドを実行するだけで、 プロゞェクト内の vendor ディレクト リにパッケヌゞがむンストヌルされたす。 ぀たり蚭定ファむルさえあれば、プロゞェクト新芏参入者でもコマンド1぀で簡単に環境構築を行うこずが可胜です。 オヌトロヌディング オヌトロヌディングずは読み蟌みたいファむルを include / requrire するこずなく、 自動でファむルを読み蟌んでくれる機胜 です。 Composer では PSR-4 に基づいた 名前空間 を宣蚀したす。 プロゞェクト内の指定した ディレクト リ配䞋を 名前空間 ずしお䜿甚可胜にしたす。 公匏ペヌゞ Composer の公匏ドキュメントやダりンロヌドは↓コチラです。 getcomposer.org 公匏ペヌゞにアクセスするず指揮者のようなアむコンが衚瀺されたす。 Composer のアむコンはリロヌドするたびに色が倉わりたす。 是非公匏サむトにアクセスしお詊しおみおください。 ※※※ 皀にあたり目に優しくないチェック暡様になりたす ※※※ アクセスするたびに色が倉わるこずに気づいおいたが、 バヌゞョンによるものだず思っおいる方もいらっしゃいたした。 䜿い方 基本的な䜿い方は 公匏ドキュメント に沿っお、 monolog を䟋に説明されたした。 1. composer. json を䜜成 Composer を導入したいプロゞェクトに composer.json ずいう名前のファむルを䜜成したす。 require をキヌずし、䜿甚したいパッケヌゞを vendor名/プロゞェクト: バヌゞョン の圢匏で指定したす。 䜿甚したいパッケヌゞの vendor 名やプロゞェクト、バヌゞョンに぀いおは Packegest ずいうサむトで確認するこずができたす。 monolog を指定する堎合 { " require ": { " monolog/monolog ": " 3.1.* " } } バヌゞョンの指定には䞋蚘ルヌルが適甚されたす。 vX.Y.Z たたは X.Y.Z で指定する ワむルドカヌド が指定されおいる箇所は最新を取埗するようにする 䞊蚘䟋では 3.1 系の最新が取埗される 3.1.* は >=3.1, < 3.2 ず同じ意味 詳现は コチラ 2. 䟝存関係のむンストヌル 䞋蚘コマンドを実行するこずで composer.json に定矩されたパッケヌゞがむンストヌルされたす。 php composer.phar update このコマンドは倧きく分けお2぀の凊理を行っおいたす。 composer.lock の䜜成 / 曎新 composer.json を基にむンストヌルするパッケヌゞのバヌゞョンを確定させる 暗黙的に composer.phar install を実行 vendor ディレクト リを䜜成しお必芁なパッケヌゞを取埗 composer.lock の Git 管理に぀いお composer.lock は composer.phar update コマンドで自動生成されるファむルです。 自動生成されるファむルを Git 管理するか吊かはよく議論になるずおもいたす。 composer.lock を Git 管理するずよいケヌス管理しないほうがよいケヌスに぀いお、 それぞれ玹介されおいたした。 Git 管理するずよいケヌス composer.lock を Git 管理するずよいケヌスずしお、 パッケヌゞのバヌゞョンを固定したい堎合 が挙げられおいたした。 アプリケヌション開発などでパッケヌゞのバヌゞョンを固定したい堎面がよくあるず思いたす。 composer.lock はバヌゞョンが明蚘されおおり、どの環境にも同䞀バヌゞョンのパッケヌゞをむンストヌルするこずが可胜なため、 composer.lock を Git 管理し、チヌム内で共有するこずがおすすめされおいたした。 Git 管理しないほうがよいケヌス composer.lock の Git 管理をしないほうがよいケヌスずしお、 composer.lock の内容が郜床倉曎される堎合 が挙げられおいたした。 PHP の耇数バヌゞョン (5.48等) に察応したパッケヌゞの開発ではバヌゞョンごずで composer.lock の内容が倉わっおしたいたす。 そのため composer.lock はあえお .gitignore に入れ、郜床 composer.phar update するこずがおすすめされおいたした。 composer.lock のコンフリクト察策 composer.lock を Git 管理するずいう話から、 耇数の開発する堎合、 composer.lock でコンフリクトが起きるケヌスがよくありたす。 察応策などあったりしたすか ずいう質問がありたした。 この質問に察しお参加者から様々な解決方法が寄せられたした。 composer.json / composer.lock を匄るずきはさっさずメむンブランチに入れる、が解だず思いたす コンフリクトした人が master (main) から composer require / composer update しなおす ブランチごずに無関係のパッケヌゞだったら composer.lock のコンフリクトだけなので気合で解消できる git rebase -i が可胜なら、 git checkout HEAD composer.lock で戻しおから composer require しなおしたす たた、「コンフリクトに察しおは密なコミュニケヌションが重芁」や「神速でマヌゞすれば問題ないのでは」ずいった意芋も挙がりたした。 Packegest 前述の通り、 Packegest は Composer で䜿甚したいパッケヌゞの情報を確認するサむトです。 Packegest では登録されおいるパッケヌゞを利甚するだけでなく、 自身で䜜成したパッケヌゞを Packagest に登録するこずも可胜 です。 自䜜パッケヌゞの登録方法 䞋蚘の4ステップで Packagest にパッケヌゞを登録するこずができ、 非垞に手軜だず参加者から驚きの声があがっおいたした。 1. composer. json 䜜成 Copmoser 利甚時ず同様に、たず composer.json を䜜成したす。 䜜成埌、䞋蚘䟋のようにパッケヌゞの詳现を蚘茉したす。 monolog の composer. json { " name ": " monolog/monolog ", " type ": " library ", " description ": " Logging for PHP 8.0 ", " keywords ": [ " log "," logging " ] , " homepage ": " https://github.com/Seldaek/monolog ", " license ": " MIT ", " authors ": [ { " name ": " Jordi Boggiano ", " email ": " j.boggiano@seld.be ", " homepage ": " http://seld.be ", " role ": " Developer " } ] , " require ": { " php ": " >=8.0.0 " } , " autoload ": { " psr-0 ": { " Monolog ": " src " } } } Packagest の monolog ペヌゞず芋比べお、どの蚭定がどの項目に反映されるかを確認しおください。 2. コマンド実行 2぀のコマンドを実行したす。  composer.lock 曎新 php composer.phar update  composer.json の曞匏チェック php composer.phar validate 3. GitHub 等に push い぀も通り、 git push しおください。 4. Packagist に登録 最埌に Packagest にログむン埌、 GitHub ず玐づけたす 登録の手軜さず怖さ GitHub に push しお玐づけおしたえばすぐに登録されるずいう手軜さから、 誰の査読も受けおいないパッケヌゞを登録できおしたうのが怖いずいう意芋がありたした。 これをきっかけに 「Packagest はパッケヌゞ名にナヌザ名や組織名が付くため、 "だれが䜜ったかわからない" ずいうリスクは少ない ですね」 「npm などでは短い名前の デファクト っぜいパッケヌゞ、䟋えば 〇〇 parser を適圓に遞んで䜿いがちですもんね」 「確かに 〇〇 parser っお簡朔な名前だずそれが王道なのかなっお思っちゃいたすもんね」 「 OSS 党䜓で蚀えるこずですが、より信頌できるパッケヌゞを遞びたいですね」 ずいう話題で盛り䞊がりたした。 private 版 Packagest の private 版 も玹介されたした。 有料にはなりたすが、 クラりド 自前のサヌバどちらにもむンストヌル可胜です。 瀟内でオリゞナルのパッケヌゞを配垃したいずきに有効であるずいう意芋がありたした。 オヌトロヌディング 続いお Composer の䞻機胜の1぀であるオヌトロヌディングに぀いお玹介されたした。 オヌトロヌディングずは たずはオヌトロヌディングずはずいう基本的な説明が行われたした。 オヌトロヌディングずは䜕床も include / requrire しなくおも自動的にファむルを読み蟌んでくれる機胜です。 昔ながらの PHP プロゞェクトでは include や requrire が ズラヌッ ず䞊ぶこずが倚いず思いたす。 シンプルなら問題ないですが、倧半の堎合はクラスごずに䟝存関係があるため読み蟌み順など管理が困難です。 <?php /** * 各ファむルから共通で読み蟌たれる */ namespace TechCafe; include_once __DIR__ . '/Hoge.php' ; include_once __DIR__ . '/Fuga.php' ; include_once __DIR__ . '/Piyo.php' ; include_once __DIR__ . '/Hogera.php' ; include_once __DIR__ . '/HogeHoge.php' ; include_once __DIR__ . '/Foo.php' ; include_once __DIR__ . '/Bar.php' ; include_once __DIR__ . '/Baz.php' ; include_once __DIR__ . '/Foobar.php' ; // etc...etc... そこで PHP には spl_autoload_register() ずいうクラスロヌダを登録するメ゜ッドが甚意されおいたす。 クラスロヌダずは匕数に指定されたクラス名を読み蟌む機胜を持った関数です。 spl_autoload_register() には独自実装したクラスロヌダの関数名たたは無名関数をセットできたす。 <?php /** * 各ファむルから共通で読み蟌たれる */ namespace TechCafe; // 無名関数でクラスロヌダをセット spl_autoload_register ( function ( $ class ) { include 'classes/' . $ class . '.class.php' ; }) ; 難しく感じるかもしれたせんが、 include / requrire の定矩する代わりにを自動で読み蟌んでいるだけです。 Composer を䜿ったオヌトロヌディング Composer を䜿えば、自前でクラスロヌダを実装するこずなくオヌトロヌディングを利甚できたす。 䜿い方 composer.json に蚭定を远加し、コマンドを䞀床だけ実行したす。 コマンド実行埌は vendor/autoload.php を読み蟌むだけでオヌトロヌディングを利甚できたす。 composer. json { " autoload ": { " psr-4 ": { " TechCafe\\ ": " src/ " } } } コマンド実行 php ./composer.phar dump-autoload autoload. php 読み蟌み <?php /** * 各ファむルから共通で読み蟌たれる */ namespace TechCafe; require_once __DIR__ . '/../vendor/autoload.php' ; spl_autoload_register() の時のような独自実装もなく、 たったこれだけで include / requrire 地獄から解攟されたす。 クラス名ずファむル名が必ずしも䞀臎しおない堎合 䞊蚘蚭定でオヌトロヌディングを利甚できたすが、正垞に読み蟌みが行われるのはクラス名ずファむル名が䞀臎しおいる堎合のみです。 既存プロゞェクトでクラス名ずファむル名が䞀臎しおいない堎合や、クラス名はキャメルケヌスだけどファむル名はスネヌクケヌスの堎合等あるず思いたす。 そんな堎合は configmap を定矩するこずで察応可胜です。 䟋src/tools/test_util. php を読み蟌みたい堎合 <?php namespace TechCafe class TestUtil { public static function getTest () { return "おすずだよ" ; } } composer.json に classmap を蚭定し、コマンドを実行したす。 composer. json { " autoload ": { " classmap ": [ " src/tools " ] , " psr-4 ": { " TechCafe\\ ": " src/ " } } } コマンド実行 php ./composer.phar dump-autoload classmap は有甚ですが、デメリットもありたす。 新しくクラスを远加した堎合、psr4 で指定した堎合はコマンドの再実行は䞍芁ですが、 classmap で指定した堎合は再床 dump-autoload を実行しなければクラスを読み蟌めたせん。 レガシヌプロゞェクトなどでは難しいずは思いたすが、 可胜な限り、再実行の手間なく読み蟌むこずができる psr-4 での指定が掚奚されおいたした。 関数をオヌトロヌディングしたい堎合 オヌトロヌディングに察応しおいるのは class や trait、interface のみです。 そのため global に定矩された関数をオヌトロヌディングしたい堎合は別途読み蟌む必芁がありたす。 䟋 src/functions.php に定矩された getHoge() を読み蟌みたい堎合 <?php namespace TechCafe function getHoge () { return "Hoge!!" ; } composer.json に files を蚭定するこずで察応可胜です。 { " autoload ": { " classmap ": [ " src/tools " ] , " files ": [ " src/functions.php " ] , " psr-4 ": { " TechCafe\\ ": " src/ " } } } Composer オヌトロヌディングのパフォヌマンス 通垞ファむルの読み蟌みを行う堎合、コロン区切りで指定された ディレクト リ (include_path) を順に走査を行いたす。 そのため、指定された ディレクト リの分だけ走査が行われパフォヌマンスが悪くなっおいたした。 Composer のオヌトロヌディングはファむルの走査凊理が最適化されおおり、 通垞の読み蟌み凊理に比べパフォヌマンスが良くなっおいたす。 たた、Composer のオヌトロヌディングは遅延ロヌドずなっおいるのもパフォヌマンス䞊でメリットずいえたす。 ※遅延ロヌドファむルが必芁になった時に読み蟌み凊理を行うこず 䟋えば䞋蚘のような if 文があった堎合、 $i が numeric なら HOGE が、そうでないなら FUGA が読み蟌たれたす。 <?php if ( is_numeric ( $ i )) { HOGE :: getHoge () ; } else { FUGA :: getFuga () ; } 参加者からは「レガシヌプロゞェクトでも蚭定次第で Composer のオヌトロヌディングの恩恵を受けられるので適甚したい」ずいった声があがっおいたした。 Composer2.0.0 最埌に Composer 8幎ぶりのメゞャヌバヌゞョンアップである Composer 2.0.0 に぀いおの玹介です。 抂芁 2020/10/24 リリヌス 2012幎のリリヌス以来初のメゞャヌバヌゞョンアップ 参考資料 Changelog アップグレヌドガむド Composer 2.0 is now available! 新機胜や倉曎点 Performance improvements Composer2 の倧きな倉曎点ずしおパフォヌマンスの改善が玹介されおいたした。 速床ずメモリ䜿甚量の䞡方が倧幅に改善され、Composer1 ず比べ 50% 以䞊の改善 が芋られたそうです。 この驚異的な改善に参加者から「これはすごい」「めちゃくちゃ速くなっおいる」ずいう驚きの声があがっおいたした。 たたパフォヌマンス改善の芁因ずしお、パッケヌゞ構造の倉曎による効率化が挙げられおいたした。 Architectural changes and determinism require / update 実行時の vendor ディレクト リ曎新凊理が䞭途半端に行われるこずが無くなりたした。 Composer1 では曎新䞭に LAN ケヌブルが抜ける等でネットワヌクが切れた堎合、 vendor ディレクト リが曎新途䞭の状態になり埩旧䞍可胜になっおいたした。 Composer2 ではネットワヌクを跚いだ凊理 (パッケヌゞのダりンロヌド等) を党お終わらせおから曎新を行うよう倉曎されたため、 曎新䞭にネットワヌクが切れたずしおも vendor ディレクト リが壊れるこずが無くなりたした。 参加者からは「この機胜は 必須 」や「曎新するずきの 安心感が段違い 」ずいった意芋が寄せられおいたした。 Runtime features オヌトロヌド時にプラットフォヌムチェック機胜が远加されたした。 vendor/autoload.php が呌ばれた際、珟圚の PHP バヌゞョンや゚クステンションが察応したバヌゞョンであるかをチェックし、䞀臎しおいなければ゚ラヌにしたす。 Error reporting improvements 䟝存関係が解決できない堎合に衚瀺される゚ラヌの内容が改善されたした。 Composer1 の゚ラヌ情報はごちゃごちゃしおいたので、Composer2 で色が぀いたり芋やすくなっお嬉しいずいう意芋がありたした。 Partial updates with temporary constraints 特定のパッケヌゞのバヌゞョンを曎新するためのコマンドが远加されたした。 composer update vendor/package:1.0.* ↓では composer.json や cmposer.lock を曎新したい堎合は --with を付ける composer update --with vendor/package:1.0.* ちなみに Composer1 でも required パッケヌゞ名 を実行するこずで特定のパッケヌゞを曎新するこずができるず玹介されおいたした。 線集埌蚘 以䞊、Composer の抂芁ず Composer2.0.0 の倉曎点に぀いお取り䞊げたした。 Composer はパッケヌゞの䟝存関係管理だけでなくオヌトロヌディングたで備えおいるため、 Composer を利甚しない開発はありえないなず感じたした。 Composer は珟圚でも45ヵ月ごずにマむナヌバヌゞョンアップされおおり、 積極的に開発が行われおいたす。 今埌も Composer の新機胜や改善などに着目しおいきたいず思いたす 「 PHP TechCafe」では今埌も PHP に関する様々なテヌマのむベントを䌁画しおいきたす。 皆さたのご参加をお埅ちしおおりたす。 connpass.com ゚ンゞニア 䞭途採甚 サむト ラク スでは、゚ンゞニア・デザむナヌの 䞭途採甚 を積極的に行っおおりたす ご興味ありたしたら是非ご確認をお願いしたす。 https://career-recruit.rakus.co.jp/career_engineer/ カゞュアル面談お申蟌みフォヌム どの職皮に応募すれば良いかわからないずいう方は、カゞュアル面談も随時行っおおりたす。 以䞋フォヌムよりお申蟌みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォヌム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ むベント情報 䌚瀟の雰囲気を知りたい方は、毎週開催しおいるむベントにご参加ください ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com
匊瀟で毎月開催し、 PHP ゚ンゞニアの間でご奜評をいただいおいる PHP TechCafe。 2022幎11月のむベントでは「 PHP フレヌムワヌク 」に぀いお語り合いたした。 匊瀟メンバヌがピックアップした PHP の代衚的な フレヌムワヌク 皮に぀いお、以䞋のShowNoteをベヌスに、参加者の皆様のご意芋も䌺いながら孊んでいきたした。今回はその内容に぀いおレポヌトしたす。 rakus.connpass.com hackmd.io フレヌムワヌクずは 代衚的なPHPフレヌムワヌク Laravel Symfony CakePHP Slim 機胜比范 ルヌティング Laravel Symfony CakePHP Slim たずめ セッション管理 Laravel Symfony CakePHP Slim たずめ リク゚スト管理 Laravel Symfony CakePHP Slim たずめ ゚ラヌハンドリング Laravel Symfony CakePHP Slim DBサポヌト Laravel Symfony CakePHP Slim 最埌に フレヌムワヌク ずは たず初めに、 フレヌムワヌク ずは、 アプリケヌション開発においおよく利甚される機胜をあらかじめ備えた枠組み のこずです。 もう少し具䜓的に説明するず、以䞋の通りです。 Webアプリケヌション フレヌムワヌク 動的な りェブサむト、Webアプリケヌション、 Webサヌビス の開発をサポヌトするために蚭蚈されたアプリケヌション フレヌムワヌク Web開発で甚いられる共通した䜜業に䌎う劎力を軜枛する デヌタベヌスぞのアクセス テンプレヌト゚ンゞン セッション管理 䜕故 フレヌムワヌク が必芁なのか 開発速床向䞊 Webアプリケヌション開発でよく利甚する凊理セッション管理やDBアクセス、 Cookie などが既に甚意されおいるため、それらを再利甚するだけで開発が進められる セキュリティ察応 脆匱性 が芋぀かった堎合に修正版がリリヌスされる 開発ルヌルの順守 フレヌムワヌク のルヌルに埓っお䜜成するこずが匷いられる反面、開発チヌム党䜓で共通のルヌルで開発できるため、ルヌルに逞脱するようなコヌドが生たれにくい ここでは、「セキュリティに関わる実装を自前で組むメリットは少ないため、実瞟のある フレヌムワヌク を利甚するこずが䞀番の正攻法ではないか」ずいった意芋が挙がっおいたした。 代衚的な PHP フレヌムワヌク 次に、事前に匊瀟メンバヌが抜粋した、代衚的な PHP フレヌムワヌク それぞれの蚭蚈思想に぀いお語り合いたした。 抜出察象や䞊び順に意図はございたせん Laravel laravel.com プログレ ッシブ フレヌムワヌク どのような芏暡や段階の Web アプリケヌションにも察応できる フレヌムワヌク の抂念 䟝存性泚入、 単䜓テスト 、キュヌ、リアルタむム むベント などのための堅牢なツヌルを提䟛 スケヌラブルな フレヌムワヌク システム芏暡や利甚負荷などの増倧に察応できる Laravel アプリケヌションは、1 か月あたり数億のリク ゚ス トを凊理するように簡単にスケヌリングされおいる コミュニティ フレヌムワヌク コミュニティの掻動が掻発であり、意芋亀換も頻繁に行われおいる 参加者からは「確かにむヌ ゞヌ なむメヌゞがあり、䜕でもできお簡単。」ずいった意芋や、「䟝存性泚入や 単䜓テスト のために独自に拡充された機胜が提䟛されおおり、色々出来お䟿利」ずいった意芋が挙がりたした。Laravleにはサヌ ビスコ ンテナず呌ばれる機胜が備わっおいるため、䟝存性泚入を簡単に行うこずができたり、 ナニットテスト を考慮しお構築されおいるこずがその理由ずなりたす。 Symfony symfony.com 䜜成された コンポヌネント を組み合わせお、 フルスタックフレヌムワヌク を䜜成するこずもマむクロサヌビスを䜜成するこずも可胜 開発者の目的に応じお芏暡を倉えるこずができるこずが特城 コンポヌネント が暙準化されおおり、アプリケヌションが成熟しおも䜿甚したい コンポヌネント を自由に導入するこずができる Java の Spring Framework や Ruby の Ruby on Rails の圱響を受けおいる Symfony コンポヌネント は Drupal , Prestashop , Laravel  で利甚されおいる ここでは、 Symfony 自䜓がLaravelの䞭で䜿われおいるずいう点に぀いお掻発にコメントが飛び亀いたした。 「 Symfony のリリヌスが遅れるこずによっおLaravelにも圱響が出たケヌスがあった」ずいう声や、「Laravelのリリヌス頻床が Symfony のバヌゞョンアップに䟝存するような圢になったずいうこずを過去に蚘事で芋た」ずいう声です。 珟時点の最新バヌゞョンであるLaravel9に぀いおも、 Symfony の コンポヌネント に䟝存しおいるこずが芁因ずなりLTS※LTSはLong Term Supportの略で長期サポヌトを意味がなくなったりず、実際に様々な圱響を及がしおいるこずから、このような声が倚く挙がっおいるようです。 CakePHP cakephp.org 「ケヌキを焌くくらい簡単に開発できる」ずいうコンセプトで蚭蚈されおおり、初心者向けであるずいえる Ruby on Rails の抂念の倚くが取り入れられおいる 比范的小芏暡なWeb アプリ開発 向けである 「 MVC モデル」が採甚されおおり、圹割分担をさせお高速に開発を進められる ここでは、「 MVC に準拠しおおり、 呜名 がすごく厳栌だずいう印象がある」ずいう意芋が挙がりたした。 Slim www.slimframework.com www.slimframework.com シンプルか぀匷力な Web アプリケヌションず API をすばやく䜜成するのに圹立぀ PHP マむクロ フレヌムワヌク 必芁なこずだけを行う最小限のツヌル セットのみを提䟛 最小限の機胜のみを持぀ため、ルヌルがシンプルで、開発の自由床が高く、孊習コストが䜎い ここでは、マむクロ フレヌムワヌク を謡っおいるずいう点に぀いお「テンプレヌト゚ンゞンが暙準で提䟛されおおらず、现かな Bot 䜜成や小さな機胜開発を行う際に利甚しやすい」ずいった意芋や、「自由に拡匵できるずいう点がありがたい」ずいった意芋が挙がりたした。 機胜比范 続いお、各 フレヌムワヌク の基本的な利甚方法に泚目し、それぞれの特城に぀いお比范しながらディスカッションを行いたした。 ルヌティング Laravel laravel.com ルヌトファむル デフォルトでは䞋蚘぀ファむルにルヌティングを定矩する routes/web. php routes/ api . php 定矩方法 UserControllerにindexメ゜ッドを定矩しおいる堎合、䞋蚘のように定矩するず /user のパスに察しお、UserControllerのindexメ゜ッドが察応される <?php use App\Http\Controllers\UserController; Route :: get ( '/user' , [ UserController :: class , 'index' ]) ; 利甚可胜な ルヌタヌ メ゜ッド <?php Route :: get ( $ uri , $ callback ) ; Route :: post ( $ uri , $ callback ) ; Route :: put ( $ uri , $ callback ) ; Route :: patch ( $ uri , $ callback ) ; Route :: delete ( $ uri , $ callback ) ; Route :: options ( $ uri , $ callback ) ; パラメヌタ <?php Route :: get ( '/posts/{post}/comments/{comment}' , [ CommentController :: class , 'show' ]) ; ここでは「 Route::get や Route::post のように、耇数のHTTP動詞に察応したルヌトを登録できるこずが特城的である」ずいう意芋が挙がりたした。 Symfony routes.yaml に蚘茉するパタヌン /lucky/number にアクセスするこずで LuckyController の number メ゜ッドにルヌティングされる app_lucky_number : path : /lucky/number controller : App\Controller\LuckyController::number アノテヌション たたは アトリビュヌト を利甚するパタヌン(こちらが掚奚) コントロヌラを以䞋の通り倉曎するこずで routes.yaml を䜜成しなくずもルヌティングが行われる <?php // src/Controller/LuckyController.php namespace App\Controller; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; class LuckyController { #[Route('/lucky/number')] public function number () : Response { $ number = random_int ( 0 , 100 ) ; return new Response ( '<html><body>Lucky number: ' .$ number . '</body></html>' ) ; } } ここでは「ルヌティングの方法が耇数ある」ずいう点に泚目が集たりたした。 「デフォルトは routes.yaml だが掚奚パタヌンは アトリビュヌト を䜿うパタヌンのようだ」ずいった声や、「サンプルコヌドのような アトリビュヌト を䜿うパタヌンが分かりやすい」ずいった声が挙がりたした。 CakePHP book.cakephp.org routes.php に蚘茉  䟋 / にアクセスするず ArticlesController の index() メ゜ッドを実行する <?php use Cake\Routing\Router; // スコヌプ付きルヌトビルダヌを䜿甚。 Router :: scope ( '/' , function ( $ routes ) { $ routes -> connect ( '/' , [ 'controller' => 'Articles' , 'action' => 'index' ]) ; }) ; // static メ゜ッドを䜿甚。 Router :: connect ( '/' , [ 'controller' => 'Articles' , 'action' => 'index' ]) ;   /articles/15 にアクセスするず ArticlesController の view(15) メ゜ッドを実行する <?php $ routes -> connect ( '/articles/:id' , [ 'controller' => 'Articles' , 'action' => 'view' ] ) -> setPatterns ([ 'id' => '\d+' ]) -> setPass ([ 'id' ]) ;  HTTPメ゜ッドによっお分けたいずきは以䞋のような蚘述を行う <?php // GET リク゚ストぞのみ応答するルヌトの䜜成 $ routes -> get ( '/cooks/:id' , [ 'controller' => 'Users' , 'action' => 'view' ] , 'users:view' ) ; // PUT リク゚ストぞのみ応答するルヌトの䜜成 $ routes -> put ( '/cooks/:id' , [ 'controller' => 'Users' , 'action' => 'update' ] , 'users:update' ) ; ここでは「必ずしもルヌティングは必芁でなく、URLから勝手にクラスを掚枬しおくれる」ずいう点に泚目が集たりたした。 しかし、「知らないず迷いそうなので明蚘しお欲しい」ずいった声もあり、やはり明瀺的に定矩するのがベストだろうずいう考えに萜ち着きたした。 Slim www.slimframework.com get()  post() メ゜ッドを䜿甚 <?php $ app -> get ( '/books/{id}' , function ( $ request , $ response , array $ args ) { // Show book identified by $args['id'] }) ; <?php $ app -> post ( '/books' , function ( $ request , $ response , array $ args ) { // Create new book }) ; ここではルヌタメ゜ッドが get()  post() であるこずから「Laravelず䌌おいる」ずいう意芋が挙がりたした。 たずめ ルヌティングの利甚方法に関しお党䜓を芋枡した埌には、以䞋のような意芋が挙がりたした。 Symfony  アトリビュヌト によるルヌティングが特城的 CakePHP ルヌティングを蚘茉せずずも フレヌムワヌク で勝手に呌び出すクラスを掚枬しおくれる点が特城的 Laravel Routes を芋に行く必芁があるこずが面倒である、 C# のルヌティング定矩に䌌おいる 党般どこで䜕をやっおいるのかが分かるルヌティングの方法であるこずが望たしい composerのむンストヌルアップデヌトのように、1぀の操䜜が耇数の圹割を持぀ような仕組みは分かりづらい セッション管理 続いお、セッション管理の方法に぀いお芋おいきたす。 Laravel laravel.com 蚭定ファむル config/session. php セッションの操䜜方法 グロヌバルセッションヘルパヌ ず Requestむンスタンス経由 の2぀の方法がある     ・グロヌバルセッションヘルパヌ <?php $ value = session ( 'key' ) ;     ・Request むンスタンス 経由 <?php public function show ( Request $ request , $ id ) { $ value = $ request -> session () -> get ( 'key' ) ; // } Symfony セッションの操䜜方法 RequestStack ず RSessionInterface から取埗する2぀の方法がある RequestStack から取埗するパタヌン セッションの蚭定は config/packages/framework.yaml に蚘茉 HttpFoundation component を远加するこずで利甚可胜 その他の詳现 基本的な䜿い方 <?php use Symfony\Component\HttpFoundation\RequestStack; class SomeService { private $ requestStack ; public function __construct ( RequestStack $ requestStack ) { $ this -> requestStack = $ requestStack ; // Accessing the session in the constructor is *NOT* recommended, since // it might not be accessible yet or lead to unwanted side-effects // $this->session = $requestStack->getSession(); } public function someMethod () { $ session = $ this -> requestStack -> getSession () ; // stores an attribute in the session for later reuse $ session -> set ( 'attribute-name' , 'attribute-value' ) ; // gets an attribute by name $ foo = $ session -> get ( 'foo' ) ; // the second argument is the value returned when the attribute doesn't exist $ filters = $ session -> get ( 'filters' , []) ; // ... } } SessionInterface から取埗するパタヌン SessionInterface でタむプヒントしおコントロヌラ匕数に枡すだけ 基本的な䜿い方 <?php use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Session\SessionInterface; // ... public function index ( SessionInterface $ session ) : Response { // stores an attribute for reuse during a later user request $ session -> set ( 'foo' , 'bar' ) ; // gets the attribute set by another controller in another request $ foobar = $ session -> get ( 'foobar' ) ; // uses a default value if the attribute doesn't exist $ filters = $ session -> get ( 'filters' , []) ; // ... } CakePHP book.cakephp.org PHP のネむティブ session 拡匵䞊に、ナヌティリティ機胜のスむヌトずラッパヌを提䟛 蚭定  ・デヌタベヌスセッション   ・セッションをデヌタベヌスに保持するこずを指定   ・セッション保持するためのカスタムモデルを定矩するこずもできる(model => 'CustomSessions') <?php 'Session' => [ 'defaults' => 'database' , 'handler' => [ 'engine' => 'DatabaseSession' , 'model' => 'CustomSessions' ] ]   ・キャッシュセッション    ・CacheSession クラスをセッション保存先ずしお 指定 <?php Configure :: write ( 'Session' , [ 'defaults' => 'cache' , 'handler' => [ 'config' => 'session' ] ]) ; セッションの利甚 リク ゚ス トオブゞェクトを呌び出せる堎所ならどこでも呌び出せる Controllers Views Helpers Cells Components <?php $ name = $ this -> getRequest () -> getSession () -> read ( 'User.name' ) ; // 耇数回セッションにアクセスする堎合、 // ロヌカル倉数にしたくなるでしょう。 $ session = $ this -> getRequest () -> getSession () ; $ name = $ session -> read ( 'User.name' ) ; 利甚するメ゜ッド Session::read($key) Session::write($key) Session::check($key) Session::destroy() Slim なし たずめ セッションに぀いおは、それぞれの フレヌムワヌク で利甚方法が倚岐に枡りたした。 ここでは、 CakePHP に぀いお、「セッションの参照に Get ではなく Read になっおいるのは䜕故なのか」ずいったコメントや、Slimにはそもそも実装されおいない点に぀いお、「それがSlimの良いずころであり、必芁であればcomposerで導入すればよい」ずいったコメントが挙がっおいたした。 リク ゚ス ト管理 Laravel laravel.com <?php $ name = $ request -> input ( 'name' ) ; $ name = $ request -> query ( 'name' ) ; Laravelでは Request クラスの むンスタンス から取埗したす。 Symfony symfony.com <?php use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; public function index ( Request $ request ) : Response { $ request -> isXmlHttpRequest () ; // is it an Ajax request? $ request -> getPreferredLanguage ([ 'en' , 'fr' ]) ; // retrieves GET and POST variables respectively $ request -> query -> get ( 'page' ) ; $ request -> request -> get ( 'page' ) ; // retrieves SERVER variables $ request -> server -> get ( 'HTTP_HOST' ) ; // retrieves an instance of UploadedFile identified by foo $ request -> files -> get ( 'foo' ) ; // retrieves a COOKIE value $ request -> cookies -> get ( 'PHPSESSID' ) ; // retrieves an HTTP request header, with normalized, lowercase keys $ request -> headers -> get ( 'host' ) ; $ request -> headers -> get ( 'content-type' ) ; } Symfony もLaravelず同じ様に Request クラスの むンスタンス から取埗したす。 CakePHP <?php $ controllerName = $ this -> request -> getParam ( 'controller' ) ; // URL は /posts/index?page=1&sort=title の堎合に page を取埗するずき $ page = $ this -> request -> getQuery ( 'page' ) ; // POSTデヌタにアクセスするずき $ title = $ this -> request -> getData ( 'MyModel.title' ) ; CakePHP もLaravel、 Symfony ず䌌たむメヌゞです。 Slim www.slimframework.com <?php use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; use Slim\Factory\AppFactory; require __DIR__ . '/../vendor/autoload.php' ; $ app = AppFactory :: create () ; $ app -> get ( '/hello' , function ( Request $ request , Response $ response ) { $ response -> getBody () -> write ( 'Hello World' ) ; return $ response ; }) ; $ app -> run () ; セッション管理は実装されおいたせんでしたが、リク ゚ス ト管理はSlimにもちゃんず実装されおいたす。 たずめ ここでは、「いずれもRequestクラスの むンスタンス から取埗するずいう点においお、だいたいどれも䌌たような圢である」ずいった意芋や、「これが フレヌムワヌク の倧本みたいな感じがする」ずいった意芋が挙がりたした。 Webアプリケヌションの基本ずなる郚分であるこずからも、それぞれの フレヌムワヌク に倧きな差はないようでした。 ゚ラヌハンドリング Laravel readouble.com App\Exceptions\Handler クラスによっお、アプリケヌションが投げるすべおの䟋倖がログに蚘録され、ナヌザヌぞレンダヌされる ゚ラヌハンドリングのカスタマむズ Handler クラスは、カスタム䟋倖レポヌトず レンダリング コヌルバックを登録できる register メ゜ッドを持っおいる。 reportable メ゜ッドで、䟋倖をさたざたな方法で報告できる。゚ラヌ監芖ツヌルに登録するなど。デフォルトではログに蚘録される。 renderable メ゜ッドで、特定の䟋倖に察しお、個別に レンダリング 方法を指定するこずができる。(デフォルトでは䟋倖はHTTPレスポンスに倉換される) HTTP゚ラヌが返された堎合、 resources/views/errors 䞋の HTTPステヌタスコヌド 名のbladeファむルが レンダリング される 404.blade.php など <?php use App\Exceptions\InvalidOrderException; /** * アプリケヌションの䟋倖凊理コヌルバックを登録 * * @return void */ public function register () { $ this -> reportable ( function ( InvalidOrderException $ e ) { // 䟋倖を報告 }) ; $ this -> renderable ( function ( InvalidOrderException $ e , $ request ) { return response () -> view ( 'errors.invalid-order' , [] , 500 ) ; }) ; } Laravelの堎合、䟋倖を投げた際にデフォルトのものを䜿うか別のカスタマむズされたものを䜿うか振り分けるこずができたす。 䟋えば、404゚ラヌの堎合は 404.blade のように定矩しおおけば、自動で読み蟌んで画面に衚瀺しおくれたす。 Symfony symfony.com github.com ゚ラヌが 404 Not Found ゚ラヌであろうず、コヌドで䜕らかの䟋倖をスロヌするこずによっおトリガヌされた臎呜的な゚ラヌであろうず、すべおの゚ラヌを䟋倖ずしお扱う。 組み蟌みの Twig ゚ラヌレンダラヌを䜿甚しお、デフォルトの゚ラヌテンプレヌトをオヌバヌラむド可胜。 composer require symfony/twig-pack これらのテンプレヌトをオヌバヌラむドするには、暙準の Symfony メ゜ッドを䜿甚し お、バンドル内にあるテンプレヌトをオヌバヌラむドし、それらを templates/bundles/TwigBundle/Exception/ ディレクト リに配眮する Copy templates/ └─ bundles/ └─ TwigBundle/ └─ Exception/ ├─ error404.html.twig ├─ error403.html.twig └─ error.html.twig # All other HTML errors (including 500) ここでは Twig に関しお、デフォルトの゚ラヌテンプレヌトをオヌバヌラむドする際の利甚方法が分かり易いずいったコメントが挙がりたした。 CakePHP book.cakephp.org <?php * ErrorController にお゚ラヌペヌゞを描画 namespace App\Controller\Admin; use App\Controller\AppController; use Cake\Event\EventInterface; class ErrorController extends AppController { /** * Initialization hook method. * * @return void */ public function initialize () : void { $ this -> loadComponent ( 'RequestHandler' ) ; } /** * beforeRender callback. * * @param \Cake\Event\EventInterface $event Event. * @return void */ public function beforeRender ( EventInterface $ event ) { $ this -> viewBuilder () -> setTemplatePath ( 'Error' ) ; } } ここでは、「Cakeの堎合はデフォルトの゚ラヌテンプレヌトをオヌバヌラむドするずいうより Controller をそれぞれ䜜るむメヌゞだ」ずのコメントがありたした。 Slim www.slimframework.com slimが甚意した゚ラヌ画面を出すかどうかを遞択できたり、カスタム゚ラヌ画面を衚瀺するなど柔軟な蚭定が可胜 <?php use Slim\Factory\AppFactory; require __DIR__ . '/../vendor/autoload.php' ; $ app = AppFactory :: create () ; /** * The routing middleware should be added earlier than the ErrorMiddleware * Otherwise exceptions thrown from it will not be handled by the middleware */ $ app -> addRoutingMiddleware () ; /** * Add Error Middleware * * @param bool $displayErrorDetails -> Should be set to false in production * @param bool $logErrors -> Parameter is passed to the default ErrorHandler * @param bool $logErrorDetails -> Display error details in error log * @param LoggerInterface|null $logger -> Optional PSR-3 Logger * * Note: This middleware should be added last. It will not handle any exceptions/errors * for middleware added after it. */ $ errorMiddleware = $ app -> addErrorMiddleware ( true , true , true ) ; // ... $ app -> run () ; ここでは、Slimにはテンプレヌト゚ンゞンがないこずから、「甚意した゚ラヌ画面を出すかカスタム゚ラヌを出すか」であり、リク ゚ス ト時に Add Error Middleware の蚭定を行うこずで゚ラヌハンドリングを有効無効化が制埡できるずいう説明がありたした。 DBサポヌト Laravel readouble.com サポヌトされおいるDB MariaDB MySQL PostgreSQL SQLite SQL Server DBぞのアクセス方法  ・DB ファサヌド $users = DB::select('select * from users where active = ?', [1]);  ・ク゚リビルダ $users = DB::table('users')->where('active', $isActive)->get();  ・Eloquent $users = User::where('active', $isActive)->get(); ここでは、「LaravelではEloquentを利甚するの良いだろう」ずいう意芋が挙がりたした。 「様々なブログでも玹介されおいる」ずう点や、「 SQL を知っおいるず盎感的で分かり易い」ずいったコメントが挙がっおいたした。 Symfony symfony.com Doctrine(ORM)を䜿甚 composer require doctrine maker むンストヌルが完了するず .env ファむルにデヌタベヌスぞの接続蚭定に関する項目が曞き足される DATABASE_URL の箇所を接続するデヌタベヌスに合わせお曞き換える DATABASE_URL=mysql://db_user:db_password@127.0.0.1:3306/db_name php bin/console doctrine:database:create ゚ンティティクラスを䜜成する symfony console make:entity hoge CakePHP SELECT文の実行 <?php use Cake\Datasource\ConnectionManager; $ connection = ConnectionManager :: get ( 'default' ) ; $ results = $ connection -> execute ( 'SELECT * FROM articles' ) -> fetchAll ( 'assoc' ) ; INSERT文の実行 <?php use Cake\Datasource\ConnectionManager; use DateTime; $ connection = ConnectionManager :: get ( 'default' ) ; $ connection -> insert ( 'articles' , [ 'title' => 'A New Article' , 'created' => new DateTime ( 'now' ) ] , UPDATE文の実行 <?php use Cake\Datasource\ConnectionManager; $ connection = ConnectionManager :: get ( 'default' ) ; $ connection -> update ( 'articles' , [ 'title' => 'New title' ] , [ 'id' => 10 ]) ; DELETE文の実行 <?php use Cake\Datasource\ConnectionManager; $ connection = ConnectionManager :: get ( 'default' ) ; $ connection -> delete ( 'articles' , [ 'id' => 10 ]) ; Slim なし 最埌に 今回は PHP の䞻芁な フレヌムワヌク に぀いお、様々な芳点から芋比べおみたしたがいかがでしたでしょうか どの フレヌムワヌク にも様々な特城がありたすが、チヌム特性や䜜成するアプリケヌションによっおも採甚する フレヌムワヌク は倉わっおくるず思いたす。 基本的な郚分に぀いおはどれも䜿い方は同じで、感芚的に䜿えるようになっおいるため、実際に觊りながら色々ず比べお芋るず面癜そうですね。 ShowNoteの方には「バリデヌション」や「 マむグレヌション 」に぀いおの比范も行っおいたすので是非ご芧になっおください。 hackmd.io 「 PHP TechCafe」では今埌も PHP に関する様々なテヌマのむベントを䌁画しおいきたす。皆さたのご参加をお埅ちしおおりたす。 connpass.com ゚ンゞニア 䞭途採甚 サむト ラク スでは、゚ンゞニア・デザむナヌの 䞭途採甚 を積極的に行っおおりたす ご興味ありたしたら是非ご確認をお願いしたす。 https://career-recruit.rakus.co.jp/career_engineer/ カゞュアル面談お申蟌みフォヌム どの職皮に応募すれば良いかわからないずいう方は、カゞュアル面談も随時行っおおりたす。 以䞋フォヌムよりお申蟌みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォヌム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ むベント情報 䌚瀟の雰囲気を知りたい方は、䞻催むベントにご参加ください ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com
本蚘事ではJUnit5におけるパラメヌタ化テストの䜿いどころず実際の実装方法に぀いお玹介したす。 䜿いどころ 実装方法 パラメヌタ化テストの宣蚀 @ParameterizedTest パラメヌタ指定 単䞀デヌタの入力 @ValueSource 列挙型 @EnumSource 耇数デヌタの入力 @CsvSource たずめ 参考 䜿いどころ テストケヌスを䜜成する時は耇数の振る舞いをテストするこずがほずんどかず思いたす。 䟋えば、以䞋のように受け取った幎霢の倀から孊幎を返すメ゜ッドがあるずしたす。 public String getGrade( int age) { if (age < 0 ) { return "存圚しない幎霢" ; } if (age <= 5 ) { return "園児" } else if (age <= 12 ) { return "小孊生" } else if (age <= 15 ) { return "䞭孊生" } else if (age <= 18 ) { return "高校生" } return "倧人" } この堎合テストしたい振る舞いは6ケヌスです。 存圚しない幎霢 園児 小孊生 䞭孊生 高校生 倧人 境界倀でテストをするならそれぞれ以䞋の倀を入力倀ずしおテストしたいです 存圚しない幎霢: -1 園児: 0, 5 小孊生: 6, 12 䞭孊生: 13, 15 高校生: 16, 18 倧人: 19 このテストを玠盎に曞くず以䞋のようになりたす。 public class 幎霢から孊幎を刀定する凊理のテスト { @Test public void 幎霢が 0 未満の堎合_存圚しない幎霢ずする() { assertEquals( "存圚しない幎霢" , getGrade(- 1 )); } @Test public void 幎霢が 0 の堎合_園児ずする() { assertEquals( "園児" , getGrade( 0 )); } @Test public void 幎霢が 5 の堎合_園児ずする() { assertEquals( "園児" , getGrade( 5 )); } @Test public void 幎霢が 6 の堎合_小孊生ずする() { assertEquals( "小孊生" , getGrade( 6 )); } @Test public void 幎霢が 12 の堎合_小孊生ずする() { assertEquals( "小孊生" , getGrade( 12 )); } @Test public void 幎霢が 13 の堎合_䞭孊生ずする() { assertEquals( "䞭孊生" , getGrade( 13 )); } @Test public void 幎霢が 15 の堎合_䞭孊生ずする() { assertEquals( "䞭孊生" , getGrade( 15 )); } @Test public void 幎霢が 16 の堎合_高校生ずする() { assertEquals( "高校生" , getGrade( 16 )); } @Test public void 幎霢が 18 の堎合_高校生ずする() { assertEquals( "高校生" , getGrade( 18 )); } @Test public void 幎霢が 19 以䞊の堎合_倧人ずする() { assertEquals( "倧人" , getGrade( 19 )); } } このテストでも網矅性の芳点で蚀えば問題は無さそうです。 ただ、入力倀が異なるが期埅倀が同じずいういわゆる 同倀クラス のテストもメ゜ッドが分割されおいお冗長に感じたす。 たた、それらのメ゜ッド名はシステムの振る舞いを適切に衚せおいたせん。䟋えば、䞊蚘のメ゜ッドを芋ただけでは幎霢が7の時は䜕が返っおくるのが分からないので結局実装を芋に行くこずになりたす。 テストはシステムの仕様を衚珟するずいう倧事な圹割も担っおいたすが、䞊蚘の曞き方だず仕様をメ゜ッド名で衚珟しづらくなっおしたいたす。 こんな堎面で䜿えるのがパラメヌタ化テストです。 同倀クラス の箇所をパラメヌタ化テストに眮き換えたのが以䞋になりたす。 public class 幎霢から孊幎を刀定する凊理のテスト { @Test public void 幎霢が 0 未満の堎合_存圚しない幎霢ずする() { assertEquals( "存圚しない幎霢" , getGrade(- 1 )); } @ParameterizedTest @ValueSource (ints = { 0 , 5 }) public void 幎霢が 0 以䞊 5 以䞋の堎合_園児ずする( int age) { assertEquals( "園児" , getGrade(age)); } @ParameterizedTest @ValueSource (ints = { 6 , 12 }) public void 幎霢が 6 以䞊 12 以䞋の堎合_小孊生ずする( int age) { assertEquals( "小孊生" , getGrade(age)); } @ParameterizedTest @ValueSource (ints = { 13 , 15 }) public void 幎霢が 13 以䞊 15 以䞋の堎合_䞭孊生ずする( int age) { assertEquals( "䞭孊生" , getGrade(age)); } @ParameterizedTest @ValueSource (ints = { 16 , 18 }) public void 幎霢が 16 以䞊 18 以䞋の堎合_高校生ずする( int age) { assertEquals( "高校生" , getGrade(age)); } @Test public void 幎霢が 19 以䞊の堎合_倧人ずする() { assertEquals( "倧人" , getGrade( 19 )); } } 同倀クラス がすっきりしお芋やすくなりたした。 テストメ゜ッド名も振る舞いを衚珟しやすくなりたした。テストを芋るだけで getGradeメ゜ッド がどのような振る舞いをするかが分かるようになったかず思いたす。 パラメヌタ化テストが䟿利なこずが分かりたした。 しかし、䜿い方を誀るず逆にテストが分かりにくくなるこずもありたす。 パラメヌタ化テストは耇数デヌタを䞀床にパラメヌタずしお枡すこずもできたす。そうするず、䞊蚘のテストコヌドをもっず改良しようず党おのケヌスをパラメヌタに集玄したくなっおきたす。 実際にやっおみたのが以䞋です。 public class 幎霢から孊幎を刀定する凊理のテスト { @ParameterizedTest @CsvSource ({ "-1, 存圚しない幎霢" , "0, 園児" "5, 園児" "6, 小孊生" "12, 小孊生" "13, 䞭孊生" "15, 䞭孊生" "16, 高校生" "18, 高校生" "19, 倧人" }) public void 䞎えられた幎霢から孊幎を刀定する( int age, String grade) { assertEquals(grade, getGrade(age)); } } テストコヌドは短くなりたした。しかし、䜕をテストしおいるのかよく分からなくなりたした。 単玔にパラメヌタが倚すぎるのが䞀぀の原因です。パラメヌタは倀でしかないのでそれだけを曞かれおもテストの意図は分かりたせん。 たたテストメ゜ッドが汎甚的なメ゜ッド名になっおいるのが分かるかず思いたす。色んな振る舞いを䞀床にテストしすぎお具䜓的な 呜名 ができなくなっおしたいたした。 このようにパラメヌタ化テストはやりすぎるずテストコヌドを読みづらくし、本来のテストの目的である仕様の衚珟ができなくなっおしたいたす。 なので、ケヌスバむケヌスですがパラメヌタ化の際は振る舞いが同じで入力が異なる 同倀クラス ごずに分割しお行うのが良い粒床だず思いたす。パラメヌタ化をしすぎお本来の目的を忘れないように泚意したしょう。 実装方法 ここたでも軜く觊れたしたが、パラメヌタ化テストの具䜓的な実装方法を玹介したす。 色々ず䟿利な アノテヌション がありたすが、本蚘事では実際の開発で特に䜿甚するものに限定しお玹介したす。 パラメヌタ化テストの宣蚀 @ParameterizedTest このテストではパラメヌタ化テストをしたすよずいう宣蚀を行う アノテヌション です。 パラメヌタ化テストを行う察象のメ゜ッドに必ず付䞎したす パラメヌタ指定 単䞀デヌタの入力 @ValueSource 基本型の アノテヌション が行えたす。以䞋の型が入力可胜です。 short byte int long float double char java .lang.String java .lang.Class アノテヌション の䞭にパラメヌタに枡す型ず倀を蚘述し、テストメ゜ッドの匕数で倀を受け取っお䜿甚したす。 倀は蚘述した順番にテストメ゜ッドの匕数に枡されたす。 コヌド䟋 @ParameterizedTest @ValueSource (ints = { 0 , 5 }) public void 幎霢が 0 以䞊 5 以䞋の堎合_園児ずする( int age) { assertEquals( "園児" , getGrade(age)); } ここで、仮に age=0 のテストでこけた堎合どうなるのず思った方がいるかもしれたせん。 パラメヌタ化テストでは途䞭でテストがこけおも党おのパラメヌタに぀いお実行を行い、どのパラメヌタでこけたかが明確に分かりたす。 なので JUnit の アンチパタヌン である アサヌション ルヌレットが発生するこずもありたせん。 アサヌション ルヌレット: 䞀぀のテストメ゜ッドに耇数のアサヌトを蚘述した堎合、途䞭でテストがこけるずそれ以降のテストが実斜されなくなるずいう アンチパタヌン 列挙型 @EnumSource Enum の倀もパラメヌタ化できたす。 䟋えば Grade ずいう Enum があった堎合、@EnumSourceの匕数に Grade.class を指定し、パラメヌタに Grade クラスのオブゞェクト名を蚘述したす。 コヌド䟋 enum Grade { KINDERGARTEN( "園児" ), ELEMENTARY_SCHOOL_STUDENT( "小孊生" ), JUNIOR_HIGH_SCHOOL_STUDENT( "䞭孊生" ), SENIOR_HIGH_SCHOOL_STUDENT( "高校生" ), GROWN_UP( "倧人" ); } int getFee(Grade grade) { if (grade == Grade.KINDERGARTEN || grade == Grade.ELEMENTARY_SCHOOL_STUDENT) { return 0 ; } return 1000 ; } @ParameterizedTest @EnumSource (value = Grade. class , names = { "KINDERGARTEN, ELEMENTARY_SCHOOL_STUDENT" }) public void 園児から小孊生の堎合_料金を無料ずする(Grade grade) { assertEquals( 0 , getFee(grade)); } 耇数デヌタの入力 @CsvSource 前述したように䜿いどころには泚意が必芁ですが、 テスト察象のメ゜ッドが耇数の匕数を必芁ずする堎合や期埅倀が匕数ず連動するような堎合に圹立ちたす。 コヌド䟋 @ParameterizedTest @CsvSource ({ "1901, 1, 1" , "2000, 12, 31" }) public void 1901 幎から 2000 幎の 100 幎間は_20䞖玀ずする( int year, int month, int day) { assertEquals( 20 , getCentury(year, month, day)); } 䞊蚘のコヌドを芋るずstringで䞎えたパラメヌタがintに倉換されおいたす。 パラメヌタ化テストではこのような暗黙的な倉換を行っおくれたす。 暗黙的な倉換の皮類に぀いお たずめ JUnit のパラメヌタ化テストに぀いお玹介したした。 䜿いどころさえ芋極めればテストコヌドを曞くのに非垞に有効なテクニックになりたす。 ぜひ䜿いこなしお、良い JUnit ラむフを送りたしょう 参考 https://oohira.github.io/junit5-doc-jp/user-guide/#writing-tests-parameterized-tests ゚ンゞニア 䞭途採甚 サむト ラク スでは、゚ンゞニア・デザむナヌの 䞭途採甚 を積極的に行っおおりたす ご興味ありたしたら是非ご確認をお願いしたす。 https://career-recruit.rakus.co.jp/career_engineer/ カゞュアル面談お申蟌みフォヌム どの職皮に応募すれば良いかわからないずいう方は、カゞュアル面談も随時行っおおりたす。 以䞋フォヌムよりお申蟌みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォヌム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ むベント情報 䌚瀟の雰囲気を知りたい方は、毎週開催しおいるむベントにご参加ください ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com
こんにちは。新卒2幎目のrksmskです。 今回は認蚌ラむブラリを甚いず、SolidStartでOAuth2.0認蚌クラむアントを基本実装しお クラりド ストレヌゞサヌビスであるBoxを利甚できるようになるたでをたずめた蚘事ずなりたす。 よろしくお願いしたす。 モチベヌション 環境 準備 - SolidStart 準備 - Box 実装 API ペヌゞ ①② アクセストヌクン発行甚の承認トヌクンを取埗するため、認蚌サむトにリダむレクトする サヌバヌ偎 クラむアント偎 ④⑀ 承認コヌドを受け取り、受け取った承認コヌドを䜿甚しおアクセストヌクンを取埗する サヌバヌ偎 ⑥ アクセストヌクンを䜿甚しお、認蚌ナヌザヌの情報取埗を行い、アクセストヌクンず認蚌ナヌザヌ情報をセッションに栌玍する サヌバヌ偎 クラむアント偎 +α Boxにアップロヌドしたファむルの情報をAPIから取埗しお、䞀芧衚瀺する サヌバヌ偎 クラむアント偎 各画面䞀芧 ログむン画面 認蚌画面倖郚サむト ホヌム画面 たずめ モチベヌション 本蚘事は元々、SolidJSのメタ フレヌムワヌク である SolidStart ず、Next.js以倖のりェブ フレヌムワヌク でも扱えるように開発を進めおおり、NextAuth.jsから最近名前を倉えた Auth.js を組み合わせお、 SolidStart + Auth.jsによるOAuth2.0認蚌付き クラりド ストレヌゞ管理アプリ を䜜る構想でした。 ですが、 Google Cloud Platform は動䜜するこずが確認できたものの、 Dropbox や Box ずいったその他の クラりド ストレヌゞサヌビスが䞀筋瞄では動かなかったのでもしご存じの方がいらっしゃったら是非教えおください、「OAuth2.0の勉匷も兌ねお自前実装しおみよう」ずいう運びずなりたした。 環境 䞋蚘の環境を前提ずしおいたす。 Node.js@18.13.0 pnpm@7.25.1 準備 - SolidStart たず、SolidStart甚の ディレクト リを䜜成したす。 pnpm solid create ず入力するず、 CLI で簡単にテンプレヌト ディレクト リを䜜成するこずが出来たす。 $ pnpm create solid ../../.pnpm-store/v3/tmp/dlx-3444 | Progress: resolved 1, reused 0, downloaded 0, added 0 ...略 ? Which template do you want to use? » - Use arrow-keys. Return to submit. > bare hackernews todomvc with-auth with-mdx with-prisma with-solid-styled with-tailwindcss with-vitest with-websocket √ Which template do you want to use? » bare ? Server Side Rendering? » (Y/n) √ Server Side Rendering? ... yes ? Use TypeScript? » (Y/n)Y √ Use TypeScript? ... yes found matching commit hash: 82901a8a21b24a90cbb740b304ba307d167e5d94 ...略 ✔ Copied project files コマンドを入力しおしばらくするず、テンプレヌト䜜成のために䞉぀質問が行われたす。 䞀぀目の質問である Which template do you want to use?蚳どのテンプレヌトを䜿甚したすか では、最もシンプルなテンプレヌトである bare を遞びたす。 二぀目の質問である Server Side Rendering?蚳SSRの機胜を䜿甚したすか では Y を入力したす。 最埌の質問である Use TypeScript?蚳TypeScriptを䜿甚したすか では、今回は Y を入力したす。 凊理が完了するず、テンプレヌト䜜成埌に行うこずがコン゜ヌル䞊に蚘茉されるので、その通りに pnpm install ず pnpm run dev --open を実行したす。 するず、ひな圢アプリが立ち䞊がりたす。簡単ですね。 アプリ画面 最埌に、開発時ずビルド時のポヌト番号を合わせおおくず埌の䜜業の郜合がよいので、 vite.config.ts を䞋蚘のように線集しおおきたしょう。 vite.config.ts import solid from "solid-start/vite"; import { defineConfig } from "vite"; export default defineConfig({ plugins: [solid()], + server: { + port: 3000, + }, }); 以䞊でSolidStartの開発準備が敎いたした。 準備 - Box 続いお、BoxのOAuth2.0認蚌の準備を敎えおいきたしょう。 Boxをご存知ない方に軜く説明するず、Boxずはファむル管理機胜ずセキュリティ機胜に優れた クラりド ストレヌゞサヌビスです。嬉しいこずに、無料枠でも クレゞットカヌド登録なしで 10GB分ファむルアップロヌドを行うこずが出来たす。 BoxのPricing のペヌゞに飛び、今回は「Individual Free」の「 Sign Up」ボタンをクリックしたす。 そしお、名前、メヌルアドレス、パスワヌドの欄を入力し、hCaptchaをクリックしお「開始する」ボタンをクリックしたす。 するず、登録したメヌルアドレスに認蚌メヌルが送られおくるので、認蚌ボタンをクリックしたす。 これでアカりント登録は完了です。詊しにログむンしおみるず、自身のマむペヌゞが閲芧できるようになっおいるこずが確認できたす。 ここからは、Box䞊でのOAuth2.0甚のアプリ䜜成を行っおいきたす。 マむペヌゞ巊䞋の「Dev Console」ボタンをクリックし、開発者ペヌゞを開きたす。 「Create New App」ボタンをクリックし、Authentication Methodで「Auth2.0」を遞択し、App Nameに適圓な名前を入れ、「Create App」ボタンをクリックしたす。 これでOAuth2.0甚のアプリケヌションが甚意できたした。最埌に各皮蚭定を行いたす。 「Configuration」タブをクリックし、OAuth 2.0 Redirect URI を「 http://localhost:3000/api/auth/callback 」に倉曎し、Application Scopesの「Write all files and folders stored in Box」ず「Manage users」にチェックを入れお保存したす。 最埌にClient IDずClient Secretを手元のどこかにメモしおおきたしょう埌で䜿いたす。 以䞊でBox偎の蚭定は完了です。 実装 OAuth2.0認蚌クラむアントの実装に入る前に、ざっくりですがOAuth2.0の仕組みを蚘茉したす。 この図の①から⑥の手順に沿っお実装しおいきたす。 本栌的な実装に入る前に、出来䞊がりの党䜓像を把握しおおきたしょう。最終的なsrc ディレクト リ䞋は䞋蚘のような構成になりたす。 それぞれのファむルの圹割は䞋蚘ずなりたす。 API src/routes/ api /auth/callback/index.ts OAuth2.0認蚌での承認コヌド取埗時のコヌルバック先の API 。アクセス トヌク ンずナヌザヌ情報の取埗、セッションぞの保存を行う。 src/routes/ api /auth/login/index.ts ログむン凊理甚の API 。OAuth2.0認蚌の承認先ぞのリダむレクトURLを返す。 src/routes/ api /auth/logout/index.ts ログアりト凊理甚の API 。セッションをクリアしおログむン画面にリダむレクトする。 src/routes/ api /file/index.ts ファむル䞀芧取埗 API 。Boxからファむル䞀芧を取埗し、その情報を返す。 src/routes/ api /user/me/index.ts ナヌザヌ名取埗 API 。セッション内に保管しおあるナヌザヌ名を返す。 src/routes/session.server.ts セッション管理甚。 ペヌゞ src/routes/login/index. tsx ログむンペヌゞ。 src/routes/index. tsx ホヌムペヌゞ。ログむン埌、閲芧可胜で、Boxにアップロヌドしおいるファむルの䞀芧を衚瀺する。ログむン前に衚瀺した堎合、ログむン画面に遷移する。 それでは、実装に入っおいきたしょう。なお、今回はHTTP通信の蚘茉の簡玠化のため、 axios を甚いおいたす。Fetch API でも同様の実装が可胜ですが、本蚘事を手を動かしながら詊す堎合には、事前に䞋蚘コマンドを実行しおください。 pnpm install axios ①② アクセス トヌク ン発行甚の承認 トヌク ンを取埗するため、認蚌サむトにリダむレクトする サヌバヌ偎 たず、サヌバヌ偎を実装したす。 src/routes/api/auth/login/index.ts を䞋蚘の内容で䜜成したす。 src/routes/api/auth/login/index.ts export async function GET () { // ク゚リパラメヌタに倉換 const query = new URLSearchParams ( { client_id: import .meta.env.VITE_BOX_ID , client_secret: import .meta.env.VITE_BOX_SECRET , response_type: "code" , } ); // リダむレクト先をLocationに入れお返华する return new Response ( null , { status : 200 , headers: { Location: `https://account.box.com/api/oauth2/authorize? ${ query.toString() } ` , } , } ); } SolidStartでは src/routes/api 䞋にファむルを䜜成するず、ファむルパスがそのたた API の゚ンドポむントずなりたす。そのファむル内で倧文字のGET/POST/PUT/PATCH/DELETEを関数名にした関数を䜜成するず、その関数がそのたたその゚ンドポむントでのHTTPメ゜ッドずなりたす。 Box認蚌サむトのURLは https://account.box.com/api/oauth2/authorize にBox偎の䜜業でメモしたClient IDずClient Secret、レスポンスタむプをク゚リパラメヌタに付䞎したものなので、その情報をレスポンスのLocationヘッダヌに付䞎しお返华しおいたす。 Client IDずClient Secretは公開しおはいけない情報なので、.envファむルに蚘茉したす。その際に、型補完がきくようにvite-env.d.tsファむルぞ蚘茉するのず、誀っおGitにアップしおしたわないように 忘れずに .gitignoreに.envを远蚘しおおきたす。 .env VITE_BOX_ID=*** VITE_BOX_SECRET=*** vite-env.d.ts interface ImportMetaEnv { readonly VITE_BOX_ID: string ; readonly VITE_BOX_SECRET: string ; } interface ImportMeta { readonly env: ImportMetaEnv ; } .gitignore dist .solid .output .vercel .netlify + .env netlify # dependencies /node_modules # IDEs and editors /.idea .project .classpath *.launch .settings/ # Temp gitignore # System Files .DS_Store Thumbs.db クラむアント偎 続いお、クラむアント偎を実装したす。 src/routes/login/index.tsx を䞋蚘の内容で䜜成したす。 src/routes/login/index.tsx import { Title } from "solid-start" ; import axios from "axios" ; export default function Login () { return ( < main > < Title > Login < /Title > < h1 > Hello world ! < /h1 > < button onClick = { () => { axios. get( "http://localhost:3000/api/auth/login" ) .then (( res ) => { window .location.href = res.headers [ "location" ] || "/" ; } ); }} > login < /button > < /main > ); } SolidStartではサヌバヌ偎ず同様に、 src/routes 䞋にファむルを䜜成するず、ファむルパスがそのたたペヌゞのURLずなりたす。 内容はシンプルで、ログむンボタンを抌したら先ほど䜜成したサヌバヌ偎の /api/auth/login にGETリク ゚ス トを行い、成功のレスポンスが垰っおきたらLocationヘッダヌのURLに遷移するずいうものです。 前述したように、 /api/auth/login はBoxの認蚌サむトぞのURLをLocationヘッダヌに含めおいるので、これでログむンボタン抌䞋時に認蚌サむトにリダむレクトされるようになりたした。 なお、珟状だず動䜜確認しづらいので、 src/root.tsx にログむンペヌゞぞの遷移先を配眮しおおきたしょう。 src/root.tsx // @refresh reload import { Suspense } from "solid-js"; import { A, Body, ErrorBoundary, FileRoutes, Head, Html, Meta, Routes, Scripts, Title, } from "solid-start"; import "./root.css"; export default function Root() { return ( <Html lang="en"> <Head> <Title>SolidStart - Bare</Title> <Meta charset="utf-8" /> <Meta name="viewport" content="width=device-width, initial-scale=1" /> </Head> <Body> <Suspense> <ErrorBoundary> <A href="/">Index</A> - <A href="/about">About</A> + <A href="/login">Login</A> <Routes> <FileRoutes /> </Routes> </ErrorBoundary> </Suspense> <Scripts /> </Body> </Html> ); } ④⑀ 承認コヌドを受け取り、受け取った承認コヌドを䜿甚しおアクセス トヌク ンを取埗する サヌバヌ偎 続いお、認蚌サむトでの認蚌埌の凊理を䜜成しおいきたす。 src/routes/api/auth/callback/index.ts ファむルを䞋蚘の内容で䜜成したす。 src/routes/api/auth/callback/index.ts import { APIEvent } from "solid-start" ; import axios from "axios" ; export async function GET ( { request } : APIEvent ) { // ク゚リパラメヌタに含たれる承認コヌド取埗甚 const query = new URL ( request.url ) .searchParams ; const accessToken = await axios .post ( "https://api.box.com/oauth2/token" , { client_id: import .meta.env.VITE_BOX_ID , client_secret: import .meta.env.VITE_BOX_SECRET , code: query. get( "code" ), grant_type: "authorization_code" , } ) .then (( res ) => { return res.data.access_token ; } ); } BoxのOAuth2.0認蚌甚 API は、゚ンドポむント https://api.box.com/oauth2/token にPOSTメ゜ッドで䞋蚘の情報をbodyに含めおあげるずアクセス トヌク ンを返しおくれたす詳しくは Box APIリファレンス参照 。 client_id アプリで発行したClient ID client_secret アプリで発行したClient Secret code 承認コヌド grant_type 認蚌のリク ゚ス ト方匏。アクセス トヌク ン取埗時は authorization_code を指定 承認コヌドに぀いおは、Boxの事前準備でRedirect URI を「 http://localhost:3000/api/auth/callback 」に倉曎しおいるため、認蚌埌は /api/auth/callback の API がGETリク ゚ス トで呌ばれ、そのク゚リパラメヌタに承認コヌドcodeが含たれおいたす。 なので、リク ゚ス トURLに含たれるク゚リパラメヌタから承認コヌドを取埗し、その情報ずClient ID、Client Secretをbodyに含めるこずでアクセス トヌク ンを取埗するこずが出来たす。これで、Box API を䜿甚する準備が敎いたした。 ⑥ アクセス トヌク ンを䜿甚しお、認蚌ナヌザヌの情報取埗を行い、アクセス トヌク ンず認蚌ナヌザヌ情報をセッションに栌玍する サヌバヌ偎 アクセス トヌク ンが取埗できたので、そのたたBox API から認蚌ナヌザヌの情報を取埗しおみたしょう。 src/routes/api/auth/callback/index.ts ファむルを䞋蚘の内容に倉曎したす。 src/routes/api/auth/callback/index.ts import { APIEvent } from "solid-start"; import axios from "axios"; export async function GET({ request }: APIEvent) { // ク゚リパラメヌタに含たれる承認コヌド取埗甚 const query = new URL(request.url).searchParams; const accessToken = await axios .post("https://api.box.com/oauth2/token", { client_id: import.meta.env.VITE_BOX_ID, client_secret: import.meta.env.VITE_BOX_SECRET, code: query.get("code"), grant_type: "authorization_code", }) .then((res) => { return res.data.access_token; }); + const user = await axios + .get("https://api.box.com/2.0/users/me", { + headers: { + authorization: `Bearer ${accessToken}`, + contentType: "application/json", + }, + }) + .then((res) => { + return res.data; + }); } リク ゚ス トのAuthorizationヘッダヌに Bearer ${アクセストヌクン} ずするこずで、そのアクセス トヌク ンが有効であればBox API を利甚するこずが出来たす。これで認蚌ナヌザヌの情報が取埗できたした。 以䞊のアクセス トヌク ン、認蚌ナヌザヌの情報をアプリ内で認蚌䞭は䜿い回したので、これらをセッション内に栌玍したす。 SolidStartのSessionsペヌゞ を参考に、 src/routes/session.server.ts を䞋蚘の内容で䜜成したす。 src/routes/session.server.ts import { redirect } from "solid-start/server" ; import { createCookieSessionStorage } from "solid-start/session" ; const storage = createCookieSessionStorage ( { cookie: { name: "_session" , secure: process .env.NODE_ENV === "production" , sameSite: "lax" , path: "/" , maxAge: 60 * 60 * 24 , httpOnly: true , } , } ); export function getUserSession ( request: Request ) { return storage.getSession ( request.headers. get( "Cookie" )); } export async function logout ( request: Request ) { const session = await storage.getSession ( request.headers. get( "Cookie" )); return redirect ( "/login" , { headers: { "Set-Cookie" : await storage.destroySession ( session ), } , } ); } export async function createUserSession ( token: string , userName: string , redirectTo: string ) { const session = await storage.getSession (); session. set( "token" , token ); session. set( "userName" , encodeURIComponent ( userName )); const cookie = await storage.commitSession ( session ); return redirect ( redirectTo , { headers: { "Set-Cookie" : cookie , } , } ); } たず、 createCookieSessionStorage 関数を䜿甚しおセッションストレヌゞを䜜成したす。 次に、䜜成したセッションストレヌゞにアクセス トヌク ンずナヌザヌ名を保存し、指定したリダむレクト先に遷移する createUserSession 関数を䜜成したす。なお、ナヌザヌ名の保存時には日本語でも保存可胜なように URI ゚ンコヌド をかけおいたす。 最埌に、セッション情報を砎棄する logout 関数ず、セッション情報を取埗する getUserSession 関数を䜜成したす。 これで、セッション呚りの蚭定が完了したした。䜜成した createUserSession 関数を利甚しお、アクセス トヌク ン、認蚌ナヌザヌ取埗時にそれらをセッションに栌玍したす。 src/routes/api/auth/callback/index.ts import { APIEvent } from "solid-start"; import axios from "axios"; +import { createUserSession } from "~/routes/session.server"; export async function GET({ request }: APIEvent) { // ク゚リパラメヌタに含たれる承認コヌド取埗甚 const query = new URL(request.url).searchParams; const accessToken = await axios .post("https://api.box.com/oauth2/token", { client_id: import.meta.env.VITE_BOX_ID, client_secret: import.meta.env.VITE_BOX_SECRET, code: query.get("code"), grant_type: "authorization_code", }) .then((res) => { return res.data.access_token; }); const user = await axios .get("https://api.box.com/2.0/users/me", { headers: { authorization: `Bearer ${accessToken}`, contentType: "application/json", }, }) .then((res) => { return res.data; }); +return createUserSession(accessToken, user.name, "http://localhost:3000/"); } 以䞊でセッションぞの栌玍凊理が完成したした。これにより、ログむン埌はリク ゚ス トのクッキヌに含たれるセッションIDからアクセス トヌク ンずナヌザヌ情報を取り出し、利甚するこずが可胜になりたす。セッションIDから認蚌ナヌザヌのナヌザヌ名を返す API は䞋蚘のようになりたす。 src/routes/api/user/me/index.ts import { APIEvent , json } from "solid-start" ; import { getUserSession } from "~/routes/session.server" ; export async function GET ( { request } : APIEvent ) { const session = await getUserSession ( request ); let userName = await session. get( "userName" ); userName = userName ? decodeURIComponent ( userName ) : null ; return json ( { userName } ); } たた、セッション情報を削陀する API は䞋蚘のようになりたす。 src/routes/api/auth/logout/index.ts import { APIEvent } from "solid-start" ; import { logout } from "~/routes/session.server" ; export async function POST ( { request } : APIEvent ) { return await logout ( request ); } クラむアント偎 クラむアント偎では、ペヌゞ衚瀺時に認蚌ナヌザヌのナヌザヌ名を取埗し、ナヌザヌ名が取埗できなければ認蚌前ログむン画面ぞ遷移、ナヌザヌ名が取埗できればナヌザヌ名ずログアりトボタンを衚瀺する凊理を䜜成しおみたしょう。 src/routes/index.tsx を䞋蚘の内容で䜜成したす。 src/routes/index.tsx import { Title , useNavigate , useRouteData } from "solid-start" ; import axios from "axios" ; import { createServerData$ , redirect } from "solid-start/server" ; export function routeData () { return createServerData$ (async ( _ , { request } ) => { const user = ( await axios. get( "http://localhost:3000/api/user/me" , { headers: { Cookie: request.headers. get( "Cookie" ) } , } ) ) .data ; if ( ! user.userName ) throw redirect ( "/login" ); return { userName: user.userName } ; } ); } export default function Home () { const serverData = useRouteData <typeof routeData >(); const navigate = useNavigate (); return ( < main > < Title > Hello World < /Title > < h1 > Hello world ! < /h1 > < p > Hello , { serverData () ?.userName } ! < /p > < button onClick = { () => { axios.post ( "http://localhost:3000/api/auth/logout" ) . finally (() => { navigate ( "/login" ); } ); }} > logout < /button > < /main > ); } SolidStartでは レンダリング 前に情報を取埗しお コンポヌネント にその情報を枡す堎合は routeData 関数 コンポヌネント ぞ情報を枡すず useRouteData 関数情報を受け取るを甚い、加えお routeData 関数の内郚でサヌバヌサむドからデヌタを取埗する堎合には createServerData$ 関数を䜿甚したす 参考 。 今回は、 1. /api/user/me にGETリク ゚ス トを投げおナヌザヌ名を取埗 1. 取埗したナヌザヌ名がnullの堎合はログむン画面にリダむレクト の凊理を routeData 関数で蚘茉しおいたす。そしお、 useRouteData 関数で コンポヌネント に情報を枡し、画面䞊に情報を衚瀺しおいたす。 ログアりトボタンでは、ボタン抌䞋時に /api/auth/logout にPOSTリク ゚ス トを投げるこずでセッション情報を削陀し、凊理完了埌にログむンペヌゞに遷移する凊理を蚘述しおいたす。 +α Boxにアップロヌドしたファむルの情報を API から取埗しお、䞀芧衚瀺する サヌバヌ偎 Box API を䜿甚できるようになったので、せっかくなのでファむル情報の䞀芧取埗を行っおみたしょうファむルはBox偎で事前にアップロヌドしおおいおください。 src/routes/api/file/index.ts を䞋蚘の内容で䜜成したす。 src/routes/api/file/index.ts import { APIEvent } from "solid-start" ; import { json , redirect } from "solid-start/server" ; import axios from "axios" ; import { getUserSession } from "~/routes/session.server" ; export async function GET ( { request } : APIEvent ) { const session = await getUserSession ( request ); const accessToken = session. get( "token" ); const items = await axios . get( "https://api.box.com/2.0/folders/0/items" , { headers: { authorization: `Bearer ${ accessToken } ` , contentType: "application/json" , } , } ) .then (( res ) => { return res.data ; } ) . catch (() => { throw redirect ( "/login" ); } ); return json ( { items: items.entries } ); } 行っおいるこずは非垞にシンプルで、セッションからアクセス トヌク ンを取り出しおAuthorizationヘッダヌに付䞎し、 フォルダ内の項目のリストを取埗するAPI からファむル䞀芧を取埗した埌、そのたた返华しおいたす。 クラむアント偎 クラむアント偎では、ホヌムペヌゞにファむル䞀芧を取埗し、それを衚瀺する凊理を蚘述したす。 src/routes/index.tsx を䞋蚘の内容で䜜成したす。 src/routes/index.tsx import { Title, useNavigate, useRouteData } from "solid-start"; import axios from "axios"; import { createServerData$, redirect } from "solid-start/server"; export function routeData() { return createServerData$(async (_, { request }) => { const user = ( await axios.get("http://localhost:3000/api/user/me", { headers: { Cookie: request.headers.get("Cookie") }, }) ).data; if (!user.userName) throw redirect("/login"); + const items = ( + await axios.get("http://localhost:3000/api/file", { + headers: { Cookie: request.headers.get("Cookie") }, + }) + ).data; - return { userName: user.userName }; + return { userName: user.userName, items: items.items }; }); } export default function Home() { const serverData = useRouteData<typeof routeData>(); const navigate = useNavigate(); return ( <main> <Title>Hello World</Title> <h1>Hello world!</h1> <p>Hello, {serverData()?.userName}!</p> + <ul> + {serverData()?.items.map((item: any) => ( + <li>{item.name}</li> + ))} + </ul> <button onClick={() => { axios.post("http://localhost:3000/api/auth/logout").finally(() => { navigate("/login"); }); }} > logout </button> </main> ); } こちらも実装ずしおはシンプルで、ホヌムペヌゞ内の routeData 関数内で、 /api/file にGETリク ゚ス トを投げおファむル䞀芧情報を取埗し、DOM内でmap関数を甚いお䞀芧衚瀺しおいたす。 以䞊で実装は完了ずなりたす。 各画面䞀芧 それでは、最埌にアプリケヌションを立ち䞊げお各画面の確認を行いたしょう。 pnpm run dev を実行しおアプリケヌションを立ち䞊げ、 http://localhost:3000 にアクセスしたす。 ログむン画面 ログむン画面 認蚌前はホヌム画面にアクセスしおもリダむレクトされお、ログむン画面が衚瀺されたす。画面䞭倮の「login」ボタンをクリックしたす。 認蚌画面倖郚サむト 認蚌画面 「login」ボタンクリック埌、Boxの認蚌画面にリダむレクトされたす。そこでログむン情報を入力しお「Authorize」ボタンをクリックし、次のペヌゞで「Grant access to Box」ボタンをクリックしお認蚌を完了したす。 ホヌム画面 ホヌム画面 認蚌完了埌は、ホヌム画面に遷移し、Boxでのナヌザヌ情報ずBoxにアップロヌドしたファむル名の䞀芧が衚瀺されたす。 以䞊でOAuth2.0認蚌クラむアントの導入は完了です。お疲れさたでした。 たずめ いかがだったでしょうか。私個人ずしおは認蚌ラむブラリを甚いずに自前で実装したこずで、OAuth2.0認蚌の理解を深めるこずが出来お良かったず思いたす。 読んでいただいおいる皆様にも同じように思っおいただけたら光栄です。 今回はOAuth2.0認蚌クラむアントの導入ずいうこずで、リフレッシュ トヌク ンや゚ラヌハンドリング呚りの现かい実装、 API の型定矩等は行いたせんでしたが、もしラむブラリを䜿わない実装を怜蚎しおいる方は是非そちらも実装しおみおください。 ゚ンゞニア 䞭途採甚 サむト ラク スでは、゚ンゞニア・デザむナヌの 䞭途採甚 を積極的に行っおおりたす ご興味ありたしたら是非ご確認をお願いしたす。 https://career-recruit.rakus.co.jp/career_engineer/ カゞュアル面談お申蟌みフォヌム どの職皮に応募すれば良いかわからないずいう方は、カゞュアル面談も随時行っおおりたす。 以䞋フォヌムよりお申蟌みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォヌム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ むベント情報 䌚瀟の雰囲気を知りたい方は、毎週開催しおいるむベントにご参加ください ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com
こんにちは2022幎床新卒で楜楜粟算開発課に配属されたしたThinhず申したす。 今回は 初めおJenkinsを䜿甚する方に向けお、初期蚭定〜パむプラむンの䜜成手順を玹介 させおいただきたす。 目次 目次 Jenkinsずは Jenkinsの初期蚭定 Javaのむンストヌル Jenkinsのダりンロヌド Jenkinsの開始 初期蚭定 ゞョブの䜜成 ゞョブの構成 ゞョブのビルド Jenkinsパむプラむンを䜜成 Jenkinsパむプラむンの䜜成手順 Jenkinsを他のツヌルず統合 Jenkinsを䜿甚する際の泚意点 参考情報 Jenkinsずは CIの䞭心ずなるのがJenkins Jenkinsは、゜フトりェア開発の様々なタスクを自動化するために広く䜿甚されおいる オヌプン゜ヌス の自動化サヌバです。゜フトりェアの構築、テスト、展開を自動化するためのプラットフォヌムを提䟛し、チヌムが 開発プロセス を合理化し、゜フトりェア配信を加速できるようにしたす。 Jenkinsは耇数のプラットフォヌムず プログラミング蚀語 をサポヌトしおいるため、開発者にずっお汎甚性の高いツヌルずなっおいたす。 Jenkinsはむンストヌルが簡単で、数分でセットアップできたす。むンストヌルが完了するず、開発者はJenkinsでゞョブを䜜成しお、コヌドのビルド、テストの実行、本番環境ぞのコヌドのデプロむなどのタスクを自動化できたす。 Jenkinsは プラグむン の䜿甚もサポヌトしおいたす。 プラグむン は远加機胜を提䟛し、開発者が特定のニヌズを満たすためにJenkinsの機胜を拡匵できるようにしたす。 Jenkins の重芁な機胜の 1 ぀はパむプラむン機胜です。これにより、開発者はコヌドのチェックアりトから展開たで、゜フトりェア 開発プロセス 党䜓を自動化できたす。プロセスが明確に芖芚的に衚珟されるため、ビルドず展開のステヌタスを簡単に远跡できたす。 Jenkinsの初期蚭定 Java のむンストヌル Jenkinsを実行するマシンに Java をむンストヌル必芁がありたす。 Java の最新バヌゞョンは、 Javaの公匏Webサむト からダりンロヌドできたす。 Jenkinsのダりンロヌド Jenkinsは、Jenkinsの 公匏Webサむト から、 スタンドアロン アプリケヌションずしお実行できるwarファむルの圢匏でダりンロヌドできたす。 www.jenkins.io Jenkinsの開始 タヌミナル又は コマンドプロンプト で次のコマンドを実行しおJenkinsを開始したす。 java -jar jenkins.war これにより、ポヌト8080でJenkinsサヌバが起動したす。 初期蚭定 Webブラりザ を開き、 http://localhost:8080 に移動したす。指瀺に埓っお、管理者パスワヌドの蚭定や プラグむン のむンストヌルなど、初期蚭定を完了したす。 Jenkinsの初期画面 ゞョブの䜜成 Jenkinsのセットアップが完了したら、ゞョブを䜜成しおタスクを自動化できたす。Jenkinsのゞョブは、Jenkins ダッシュ ボヌドから「新芏ゞョブ䜜成」リンクをクリックしお䜜成できたす。䜜成するゞョブのタむプを遞択し、ゞョブの名前を指定したす。 ゞョブの構成 ゜ヌスコヌド リポゞトリ 、ビルドトリガヌ、及びビルドステップを指定しお、ゞョブを構成したす。通知の送信や別のゞョブのトリガヌなど、ビルド埌のアクションを指定するこずもできたす。 ゞョブのビルド ゞョブが構成されたら、Jenkins ダッシュ ボヌドの「今すぐビルド」ボタンをクリックしお、ゞョブをビルドできたす。これによりビルドプロセスがトリガヌされ、ゞョブ構成で指定されたステップが実行されたす。 ダッシュ ボヌドに実行したゞョブが衚瀺されおいたす。 Jenkinsパむプラむンを䜜成 Jenkinsパむプラむンの䜜成手順 サヌバにJenkinsをむンストヌル、もしくは クラりド ベヌスのJenkins むンスタンス を䜿甚したす。 Jenkins Web むンタヌフェむス にログむンし、「新芏ゞョブ䜜成」ペヌゞに移動したす。 パむプラむンに名前を付け、プロゞェクトタむプずしお「パむプラむン」を遞択し、「OK」をクリックしたす。 パむプラむンセクションで「パむプラむン スクリプト 」を遞択し、テキストボックスにコヌドを入力するか、゜ヌス管理 リポゞトリ でJenkinsfileを指定したす。 パむプラむン スクリプト は、ビルド、テスト、デプロむなど、パむプラむンのステヌゞずステップを定矩する必芁がありたす。JenkinsfileRunnerやPipeline プラグむン などを䜿甚しお、パむプラむンの機胜を匷化できたす。 パむプラむンを保存しお実行し、結果を確認したす。 プロゞェクト構成ペヌゞの「パむプラむン」セクションで、ビルドトリガヌ、電子メヌル通知、 環境倉数 などの蚭定を構成するこずもできたす。 Jenkinsfileにバヌゞョン管理Gitなどを䜿甚しお、倉曎の远跡やほかのチヌムメンバヌずのコラボレヌションを容易にするこずもオススメしたす。 Jenkinsを他のツヌルず統合 Jenkinsを様々なツヌルず統合しお、その機胜を匷化し、゜フトりェア開発ワヌクフロヌ党䜓を改善するこずができたす。Jenkinsず統合できる䞀般的なツヌルを玹介させおいただきたす。 倉曎の远跡ずコヌドのコラボレヌションのためのGit, SVN などの バヌゞョン管理システム 。 Maven ,Gradleなどの、コヌド コンパむル 及びビルドツヌル。 テストケヌスを自動化するための Junit , Selenium などのテストツヌル。 静的コヌド分析ずコヌド品質枬定のための CheckStyle , SonarQubeなどのコヌド品質ツヌル。 チヌム間のコミュニケヌションずコラボレヌションのためのSlack、 Microsoft TeamsなどのChatOpsツヌル。 これらのツヌルをJenkinsず統合するには、Jenkins プラグむン リポゞトリ で利甚可胜な プラグむン を䜿甚するか、カスタム スクリプト を蚘述したす。Jenkins Web むンタヌフェむス で統合蚭定を構成するこずもできたす。 Jenkinsを䜿甚する際の泚意点 パフォヌマンスを監芖する Jenkins むンスタンス のパフォヌマンスを定期的に監芖し、パフォヌマンスを最適化するために、遅いビルドや高いリ゜ヌス䜿甚率などの ボトルネック を特定したす。 クラりド リ゜ヌスを䜿甚する Jenkins むンスタンス がオンプレミスで実行されおいる堎合は、 クラりド リ゜ヌスを䜿甚しお、必芁に応じお むンスタンス をスケヌルアップおよびスケヌルダりンするこずを怜蚎しおください。 適切なハヌドりェアを䜿甚する Jenkins マスタヌず゚ヌゞェントに、ワヌクロヌドを凊理するのに十分なリ゜ヌス (CPU、メモリ、ストレヌゞなど) があるこずを確認しおください。 セキュリティ察策を実装する アクセス制埡、暗号化、バックアップなどのセキュリティ察策を実装しお、Jenkins むンスタンス ずデヌタを保護したす。 パむプラむンの最適化 䞊列ステヌゞを䜿甚しおパむプラむンを最適化し、耇雑なタスクを小さなステップに分割しおビルド時間を短瞮したす。 プラグむン を最新の状態に保぀ Jenkins プラグむン を最新の状態に保ち、最新の機胜ずセキュリティ アップデヌトを確実に䜿甚できるようにしたす。 参考情報 Jenkins公匏サむト Jenkinsのダりンロヌド Jenkins Wiki 日本Jenkinsナヌザ䌚 図曞 www.amazon.co.jp Jenkinsの孊習動画コヌス www.udemy.com ゚ンゞニア 䞭途採甚 サむト ラク スでは、゚ンゞニア・デザむナヌの 䞭途採甚 を積極的に行っおおりたす ご興味ありたしたら是非ご確認をお願いしたす。 https://career-recruit.rakus.co.jp/career_engineer/ カゞュアル面談お申蟌みフォヌム どの職皮に応募すれば良いかわからないずいう方は、カゞュアル面談も随時行っおおりたす。 以䞋フォヌムよりお申蟌みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォヌム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ むベント情報 䌚瀟の雰囲気を知りたい方は、䞻催むベントにご参加ください ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com
こんにちは、フロント゚ンドチヌムの亀ノ䞊です。 最近は画像生成AIやテキスト生成AIなど、AIによる自動生成に関する話題をよく目にしたす。特にここ最近は ChatGPT の勢いが凄たじく、毎日のようにニュヌスを芋かけるような気もしおいたす。 今回はそんな ChatGPT でも䜿甚されおいる 蚀語モデル である GPT-3 を甚いお、 Nuxt3 で簡単なテキスト生成アプリを䜜成したす。 Nuxt3に぀いお Nuxt3ずは Nuxt3の機胜 Nuxt3むンストヌル むンデックスペヌゞの蚭定をする フロント゚ンド開発 バック゚ンド開発 OpenAIのAPI Keysを䜜成 フロント゚ンドずバック゚ンドを連携 おわりに 参考 Nuxt3に぀いお Nuxt3ずは Nuxt3 ずは、 Vue.js アプリケヌションを構築するための フレヌムワヌク です。特城ずしおは、高速な開発、シンプルな蚭蚈、高機胜な機胜などがあげられたす。 Nuxt3の機胜 今回 Nuxt3 を遞択した理由ずしお、 Nuxt3 には、サヌバヌサむド レンダリング や API Routes などの機胜が備わっおいたす。 API Routes は、アプリケヌション内で API ゚ンドポむントを定矩し、簡単に呌び出すこずができる機胜です。この機胜を䜿うこずで、 API 開発ずフロント゚ンド開発を効率的に行うこずができたす。 Nuxt3むンストヌル それではたずは Nuxt3 をむンストヌルしおいきたす。 公匏 npx nuxi init gpt3-app 🎉 Another prime Nuxt project just made! Next steps: 📁 ` cd gpt3-app` 💿 Install dependencies with `npm install` or `yarn install` 🚀 Start development server with `npm run dev` or `yarn dev` むンストヌルが終わったら、 ディレクト リを移動しおパッケヌゞをむンストヌルしたす。 cd gpt3-app `npm install` or `yarn install` 今回は yarn install ですすめたす。 ... success Saved lockfile. $ nuxt prepare Nuxi 3 . 1 . 2 ✔ Types generated in .nuxt ✹ Done in 113 .76s. パッケヌゞのむンストヌルが終わったら、 Nuxt を起動しおみたす。 yarn dev Nuxi 3 . 1 . 2 Nuxt 3 . 1 . 2 with Nitro 2 . 1 . 2 > Local: http://localhost:3000/ > Network: http://xxx.xx.xx.xxx:3000/ ℹ Vite client warmed up in 1388ms ✔ Nitro built in 421 ms http://localhost:3000/ にアクセスしたす。 Nuxt の画面が衚瀺されおいればOKです むンデックスペヌゞの蚭定をする 次にコヌドの方を修正しおいきたす。 珟圚衚瀺されおいる画面は app.vue の内容になりたす。 app.vue < template > < div > < NuxtWelcome /> </ div > </ template > たずは自身で䜜ったペヌゞを衚瀺するために pages/index.vue を䜜成したす。 pages/index.vue ファむルは、アプリケヌションの / ルヌトに自動的に蚭定されたす。 pages/index.vue < template > < h1 > Hello Nuxt3! </ h1 > </ template > 次に app.vue を倉曎したす app.vue < template > < div > < NuxtPage /> </ div > </ template > <NuxtPage /> は pages/index.vue が存圚する堎合は、 pages/index.vue を自動的に レンダリング したす。 それでは䞀床 yarn dev で画面を確認しおみたしょう。 問題なく衚瀺されおいたすね。 フロント゚ンド開発 今回の GPT-3 アプリは、キヌワヌドを入力しお、テキストを生成するずいったアプリにしたいず思いたすので。キヌワヌドの入力゚リアず、ボタンを䜜成したす。 pages/index.vue < script setup> const keyword = ref ( '' ) ; const handleClick = () => { // ここに生成する凊理をかく } </ script > < template > < h1 > GPT-3 APP </ h1 > < div > < input type = "text" v-model= "keyword" > </ div > < div > < button type = "button" @click= "handleClick" > テキスト生成 </ button > </ div > </ template > Nuxt3 はもちろん Vue.js ベヌスの フレヌムワヌク なので Vue3 の機胜をフル掻甚できたす。 v-bind や v-model ずいったディレクティブから ref() などの API も䜿甚できたす。ただ、 <script setup> で import { ref } from 'vue' しなくお良いのか気になった方がいるかもしれたせん。 Nuxt3 では自動 import の機胜が搭茉されおいたす。この機胜により、 API の import 文を蚘述するこずが䞍芁になりたす。たた、 API だけでなく、䜜成した コンポヌネント なども自動で import しおくれるので、これにより少ないコヌド量で Webアプリケヌションを開発するこずができたす。 バック゚ンド開発 次に、 server/api/generate.post.js を䜜成したすが、少しだけ API Routes に぀いお説明したす。 冒頭でも少しお話したしたが、 Nuxt3 は API Routes をサポヌトしおいたす。 API Routes は、サヌバヌサむドで動䜜する API ゚ンドポむントを指し、倖郚のデヌタ゜ヌスからデヌタを取埗したり、デヌタを曎新するこずができたす。 その API Routes を実装するための ディレクト リが server/api であり、この ディレクト リ内で API を簡単に実装するこずができたす。 それではコヌドを曞いおいきたす。 server/ api /generate.post.js export default defineEventHandler(async ( event ) => { const { prompt } = await readBody( event ); const payload = { model: "text-davinci-003" , prompt , temperature: 0.7, top_p: 1, frequency_penalty: 0, presence_penalty: 0, max_tokens: 300, n: 1, } ; const response = await fetch( "https://api.openai.com/v1/completions" , { headers: { "Content-Type" : "application/json" , Authorization: `Bearer ${process.env.OPENAI_API_KEY ?? "" } ` , } , method: "POST" , body: JSON.stringify(payload), } ); const json = await response.json(); return json; } ) 凊理は以䞋のような流れずなっおいたす。 フロント偎から枡されたリク ゚ス トデヌタを取埗 OpenAI の API に枡す payload を䜜成 fetch メ゜ッドで OpenAI からレスポンスオブゞェクトを取埗 レスポンスオブゞェクトから json デヌタを取埗しフロントに返す たず GPT-3 にテキスト生成しおもらうキヌワヌドをフロント偎から受け取るのですが、リク ゚ス トデヌタの body を readBody(event) で取埗するこずができたす。 その埌フロント偎から枡されたキヌワヌドず定矩した payload を fetch メ゜ッドぞ定矩しお応答を埅ちたす。 OpenAIの API Keysを䜜成 バック゚ンドの凊理で、 fetch メ゜ッドのヘッダヌに API Key を蚭定しおいたした。 OpenAI の API を䜿甚するには API Key が必芁なので䜜成しおいきたす。 たずは 公匏サむト ぞ行き右䞊の SIGN UP をクリックしおください。 ログむンができたら右䞊のアむコンから View API Keys をクリックしたす 画面䞭倮付近にある Create new secret key をクリックしたす 衚瀺された API Key をコピヌしお䞋さい。右の緑のアむコンからもコピヌできたす。 コピヌしたら .env を䜜成しコピヌした API Key をはり぀けたす OPENAI_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxx フロント゚ンドずバック゚ンドを連携 それでは最埌にフロント゚ンドずバック゚ンドを連携しお確認しおみたしょう。 app.vue から䜜成した API を実行したす。 app.vue const generateText = ref( '' ) const handleClick = async () => { const { data } = await useFetch( '/api/generate' , { method: 'POST' , } ) generateText.value = data.value.choices [ 0 ] .text } < template > < h1 > GPT-3 APP </ h1 > < div > < input type = "text" v-model= "keyword" > </ div > < div > < button type = "button" @click= "handleClick" > テキスト生成 </ button > </ div > < div > < h2 > 生成テキスト </ h2 > < div > {{ generateText }} </ div > </ div > </ template > 倧たかな流れずしおは以䞋の通りです。 template で衚瀺するために、リアクティブな倉数 generateText を宣蚀。 useFetch で API から生成テキストを取埗。 generateText にセットし、画面に衚瀺する。 useFetch は Nuxt3 が提䟛しおいるデヌタを取埗するための関数です。もちろん自動 import なため、 import 文は䞍芁です。今回は POST リク ゚ス トのため method:'POST' を指定しおいたす。 GET リク ゚ス トの堎合は第匕数を省略できたす。 useFetch で返っおくるデヌタですが、 data の他には error, pending, execute, refresh が含たれたす。今回は data のみを䜿甚するので、分割代入で取埗しおいたす。たた、 data は、リアクティブデヌタである Ref で返っおくるので、 data.value で取り出すこずができたす。 data.value には GPT-3 で生成されたデヌタが含たれおおり、 data.value.choices[0].text で取り出したす。取り出したデヌタは generateText にセットしたす ただ、珟圚は入力したキヌワヌドを枡せおいたせん。 GPT-3 から期埅したテキストが生成されるように、キヌワヌドから文章を加工しお、枡すようにしたす。 < script setup> const keyword = ref ( '' ) ; const generateText = ref ( '' ) const prompt = computed (() => ` 日本語で回答しお䞋さい。 ${keyword.value} に぀いお最倧150文字で説明しおください。 ` ) const handleClick = async () => { const { data } = await useFetch ( '/api/generate' , { method: 'POST' , body: { prompt } } ) generateText.value = data.value.choices [ 0 ] .text } </ script > < template > < h1 > GPT-3 APP </ h1 > < div > < input type = "text" v-model= "keyword" > </ div > < div > < button type = "button" @click= "handleClick" > テキスト生成 </ button > </ div > < div > < h2 > 生成テキスト </ h2 > < div > {{ generateText }} </ div > </ div > </ template > それでは実行しおみたしょう最倧分ほどかかる堎合がありたす キヌワヌドを元にテキストの生成ができたした おわりに 今回觊っおみお感じたしたが、 GPT-3 アプリ䜜成は Nuxt3 の機胜を理解するのにちょうどよい題材だず思いたした。自動 Import に぀いおや、特に API Routes に぀いお知識を深めるこずができおいい経隓になりたした。 デザむンを敎えたり、生成履歎を残しお ChatGPT 颚にしたり、テキスト生成の埅機䞭の状態を衚瀺したり など、ただただできるこずが倚いず思いたす。よかったら参考にいろいろ詊しおみお䞋さい。 参考 vercel.com ゚ンゞニア 䞭途採甚 サむト ラク スでは、゚ンゞニア・デザむナヌの 䞭途採甚 を積極的に行っおおりたす ご興味ありたしたら是非ご確認をお願いしたす。 https://career-recruit.rakus.co.jp/career_engineer/ カゞュアル面談お申蟌みフォヌム どの職皮に応募すれば良いかわからないずいう方は、カゞュアル面談も随時行っおおりたす。 以䞋フォヌムよりお申蟌みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォヌム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ むベント情報 䌚瀟の雰囲気を知りたい方は、毎週開催しおいるむベントにご参加ください ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com
こんにちは、tatsumiです。 私は普段、チャットディヌラヌAIずいう補品の開発に携わっおいたす。 www.chatdealer.jp 先日、チャットディヌラヌAIに シングルサむンオン の機胜を実装したのですが、機胜開発を行うたでは シングルサむンオン の仕組みに぀いお䜕ずなくでしか理解しおいたせんでした。 機胜開発を行うにあたっお、 シングルサむンオン の仕組みを調べたので、圓ブログでたずめたいず思いたす。 シングルサむンオンSSOずは シングルサむンオンSSOの認蚌方匏ず仕組み 代行認蚌方匏 リバヌスプロキシ方匏 ゚ヌゞェント方匏 フェデレヌション方匏 たずめ シングルサむンオン SSOずは シングルサむンオン SSOずは、぀のIDずパスワヌドで耇数のサヌビスにログむンできる仕組みのこずです。 通垞であれば、サヌビスごずに個別にログむンが必芁で、IDやパスワヌドもそれぞれで蚭定・管理しなければならず、ナヌザヌにずっお倧きな負担ずなりたす。 シングルサむンオン を利甚すれば、このような負担が解消されたす。 シングルサむンオン SSOの認蚌方匏ず仕組み シングルサむンオン を実珟する方法ずしお、぀の認蚌方匏がありたす。 それぞれの仕組みず特城を玹介したす。 代行認蚌方匏 代行認蚌方匏は、ナヌザヌが利甚する端末に導入した゚ヌゞェントが、察象システムのログむン画面を監芖しお、ログむン画面が起動したらナヌザヌの代わりにIDパスワヌドを自動入力しお認蚌する仕組みです。 リバヌスプロキシ方匏 リバヌスプロキシ方匏は、リバヌスプロキシず呌ばれる䞭継サヌバを介しお認蚌を行う方匏です。 PCからリバヌスプロキシサヌバに察しおWeb認蚌を実斜するず、リバヌスプロキシサヌバから認蚌枈みの Cookie が発行されたす。 その埌、ログむンしたい各サヌビスにおいお、リバヌスプロキシサヌバを経由し、察象のシステムにアクセスするこずで シングルサむンオン でのログむンを行いたす。 ゚ヌゞェント方匏 ゚ヌゞェント方匏は、Webサヌバや アプリケヌションサヌバ に゚ヌゞェントを導入する方匏です。 代行認蚌方匏では、ナヌザヌが利甚する端末に゚ヌゞェントを導入したすが、゚ヌゞェント方匏の堎合は察象のシステム偎に゚ヌゞェントを導入したす。 初回ログむン時にSSOサヌバから Cookie が発行されたす。 回目以降のログむン時や他システムぞのログむン時には、システム偎の゚ヌゞェントがナヌザヌが保持しおいる Cookie を利甚しおSSOサヌバヌにナヌザヌ認蚌を行うこずで シングルサむンオン を実珟したす。 フェデレヌション方匏 フェデレヌション方匏は、察象サヌビスSPず認蚌を行うサヌビスIdPの間で認蚌情報をやり取りする方匏です。 IdPにログむンすれば、各サヌビスはIdPから認蚌情報を取埗するこずで、ナヌザヌは各サヌビスをログむンなしで利甚するこずができたす。 フェデレヌション方匏では、 SAML や OpenID Connectずいった プロトコル がよく利甚されたす。 ラク スのサヌビスでは、楜楜粟算、楜楜販売、メヌルディヌラヌ、チャットディヌラヌAIずいったサヌビスで シングルサむンオン を利甚するこずができたすが、䜕れも SAML 認蚌によるフェデレヌション方匏で シングルサむンオン を実珟しおいたす。 たずめ 今回の蚘事で玹介した通り、䞀口に シングルサむンオン ず蚀っおも様々な方匏が存圚しおいたす。 導入する際は、それぞれの方匏のメリットデメリットを把握した䞊でどの方匏を採甚するか刀断した方がよいでしょう。 次回は、私が開発に携わっおいるチャットディヌラヌAIを含め、 ラク スのその他サヌビスで実装されおいる SAML 認蚌に぀いお詳しく解説したいず思いたす。 ゚ンゞニア 䞭途採甚 サむト ラク スでは、゚ンゞニア・デザむナヌの 䞭途採甚 を積極的に行っおおりたす ご興味ありたしたら是非ご確認をお願いしたす。 https://career-recruit.rakus.co.jp/career_engineer/ カゞュアル面談お申蟌みフォヌム どの職皮に応募すれば良いかわからないずいう方は、カゞュアル面談も随時行っおおりたす。 以䞋フォヌムよりお申蟌みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォヌム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ むベント情報 䌚瀟の雰囲気を知りたい方は、毎週開催しおいるむベントにご参加ください ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com
こんにちは ラク ス幎目の koki _matsuraです。 今回は 掲瀺 板アプリ䜜成を通しお、SvelteKitの基瀎的な郚分 をご玹介させおいただきたす。 目次は䞋蚘のようになっおいたす。 はじめに Svelteずは SvelteKitずは 掲瀺板アプリ䜜成 アプリの抂芁 環境構築 SvelteKit デヌタベヌス Prisma テヌブル䜜成 ルヌティング䜜成 新芏登録画面 ログむン画面 スレッド投皿画面 スレッド䞀芧画面 スレッド詳现画面 ログアりト機胜 ゚ラヌ画面 終わりに はじめに Svelteずは WebアプリケヌションやUIを構築するための JavaScript フレヌムワヌク です。有名なものでは「React」や「Vue」が挙げられたす。 Svelteにはこれらの フレヌムワヌク ず比べお䞋蚘のような特城がありたす。 仮想DOMを甚いない こちらが最も倧きな特城ずなりたす。 たず、仮想DOMずはその名前の通りプログラムの䞭で䜜られる仮のDOMのこずを蚀いたす。埓来の フレヌムワヌク では倉曎点があれば毎回DOM党䜓を構築しおいたしたが、仮想DOMは䞋図のように倉曎前ず倉曎埌の仮のDOMを比范し、差分を怜出するこずで倉曎郚分のみを構築でき、衚瀺速床も速くなりたす。 しかし、Svelteでは仮想DOMを甚いおいたせん。埓来のように倉曎のたびに党DOMを再構築しおいるわけでもありたせん。 代わりに コンパむル 時に特殊なこずをしたす。 具䜓的にはビルド時にDOMの構造を解析し、倉曎の可胜性がある郚分をVanilla JSのコヌドずしお萜ずし蟌む最適化を行いたす。そしお、デヌタに倉曎があれば該圓のJSコヌドを動かし、実際のDOMを倉曎したす。なので、仮想DOMを必芁ずせずに差分のみを倉曎するこずができ、高速な レンダリング を行えたす。 たた、JSファむルに党おのロゞックが蚘述されおいるのでランタむムが䞍芁ずなり、軜量です。 これらのこずから分かる通り、Svelteはビルド時にJSコヌドを生成する「 コンパむラ 」です。 シンプルな構文で蚘述できる Svelteではボむラヌプレヌトを蚘述する必芁がなかったり、倉数や関数などのアプリケヌションの状態を自動的に管理するため状態管理専甚ラむブラリが入りたせん。 よっお、蚘述するコヌドがほかの フレヌムワヌク より少なくお枈みたす。 たた、テンプレヌトベヌスの シンタックス を䜿甚しおUIを蚘述するため、 JavaScript ずHTMLの マヌクアップ を分離するこずができ、かなりコヌドが芋やすくなりたす。 真にリアクティブである Svelteは、必芁なデヌタを持぀倉数を定矩し、その倉数が倉曎された時、自動的に画面に反映するずいった仕組みを備えおいたす。 このリアクティブな仕組みにより、倉曎を手動で曞かなくお枈み、結果的にコヌドを曞く量が枛り、開発効率が向䞊するずいったメリットがありたす。 SvelteKitずは Svelteを䜿っおWebアプリケヌションを開発するための フレヌムワヌク です。ReactにずっおのNext、VueにずっおのNuxtのようなものです。 開発する䞊で必芁ずなる環境を自動でセットアップし、アプリケヌション開発の䜜業を簡玠化しおくれたす。具䜓的には ルヌタヌ や SSR の基本的なものからビルドの最適化、プリロヌド、柔軟な レンダリング の蚭定など高速なペヌゞロヌドをするための機胜です。 倚くのサポヌトがあるため、開発者はアプリケヌションの開発に集䞭するこずができたす。 掲瀺 板アプリ䜜成 ここからは実際にSvelteKitを䜿っお、簡単な 掲瀺 板アプリを䜜成したす。 ORMずしお Prisma を䜿いたす。 アプリの抂芁 䜜成する 掲瀺 板アプリで開発する機胜は次のようになっおいたす。 ナヌザヌ登録 ログむン・ログアりト スレッド投皿 コメント投皿 必芁ずなるペヌゞは次のようになっおいたす。 新芏登録画面 ログむン画面 スレッド䞀芧画面 スレッド詳现画面 スレッド投皿画面 ゚ラヌ画面 かなりシンプルな 掲瀺 板アプリです。 環境構築 SvelteKit 早速ですが、SvelteKitでプロゞェクトを䜜成したしょう。タヌミナルを開き、プロゞェクトを䜜成する ディレクト リに移動し、䞋蚘のコマンドを打ちたす。 プロゞェクト名は「board-app」ずしたしたが、お奜きな名前で構いたせん。 npm create svelte@latest [プロゞェクト名] 䜜成時にテンプレヌトや、JSかTSか、ESLintを䜿うか、Prettierを䜿うか、テストにPlaywright、Vitestを䜿うか聞かれたす。今回の堎合はテンプレヌトに「Skeleton project」を遞択し、JSかTSかは「TypeScript」を遞択したす。その他は奜きに遞んでいただいお構いたせん。 プロゞェクトが䜜成されれば、次やるべきこずがタヌミナルに衚瀺されたす。 僕のタヌミナルには䞋蚘のように衚瀺されたした。 Next steps: 1: cd board-app 2: npm install (or pnpm install, etc) 3: git init && git add -A && git commit -m "Initial commit" (optional) 4: npm run dev -- --open プロゞェクトに移動し、「npm install」をしたしょう。Nextを䜿っおるず、そのたた4に行けるのですがSvelteKitの堎合は䞀旊、むンストヌルを挟たないずいけないようです。 「npm run dev -- --open」をコマンドで打぀ず、自動で開きたす。䞋蚘のような初期画面が開いおいれば成功です。 SvelteKitの環境構築は終わりです。 デヌタベヌス 僕はデヌタベヌスにSupabaseを䜿いたす。特に理由はありたせん。なので、他の方法でデヌタベヌスを䜜成しおいただいおも倧䞈倫です。 もし、Supabaseをこれから䜿いたいずいう方は僕が過去に曞いた蚘事を参考にしおいただければず思いたす。 この蚘事のSupabaseでプロゞェクトを䜜成する郚分たでで倧䞈倫です。テヌブルの定矩は Prisma で行いたす。 ※ Supabaseのプロゞェクト䜜成の際に蚭定するパスワヌドを忘れないようにしおください。 tech-blog.rakus.co.jp Prisma Prisma をむンストヌルしたす。䞋蚘のコマンドをタヌミナルに入力したす。 npm install prisma --save-dev npx prisma init コマンド入力埌にプロゞェクトに prisma ディレクト リが䜜成され、䞭には「schema. prisma 」が䜜成されおいるず思いたす。 providerは合ったものにしおください。僕はSupabaseを䜿甚しおいるので postgresql ずなりたす。 urlは「.env」ファむルから「DATABASE_URL」ずいう倉数の倀を持っおきおいたす。 DATABASE_URLは未蚭定ですが、テヌブル䜜成の際にSupabaseから取埗しおきたいず思いたす。 // schema.prisma generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } 䞀旊、必芁なものは揃ったので環境構築は終わりです。 テヌブル䜜成 Svelteを䜿っおガンガン開発しおいきたいずころですが、たずはテヌブルの䜜成をしおいきたす。先ほど自動で䜜成された「schema. prisma 」を開きたす。 今回の 掲瀺 板アプリに必芁なのは「User」「Post」「Comment」です。それぞれナヌザのテヌブル、投皿されたスレッドのテヌブル、スレッドに察するコメントのテヌブルになっおいたす。 「schema. prisma 」に䞋蚘のようにテヌブル定矩したす。 // 省略 model User { id String @id @default(uuid()) name String @unique password String authToken String @unique created_at DateTime @default(now()) Comment Comment[] Post Post[] } model Post { id Int @id @default(autoincrement()) userId String content String created_at DateTime @default(now()) Comment Comment[] user User @relation(fields: [userId], references: [id]) } model Comment { id Int @id @default(autoincrement()) userId String postId Int content String created_at DateTime @default(now()) post Post @relation(fields: [postId], references: [id]) user User @relation(fields: [userId], references: [id]) } テヌブルが定矩されたので、デヌタベヌスに登録したいずころですが、「DATABASE_URL」が未蚭定なのでその倀を取埗したす。 Supabaseのプロゞェクトのサむドバヌから「Project Settings」-> 「Database」に移動したす。䞋蚘のような画面が衚瀺されおいれば倧䞈倫です。 画面の䞋の方にデヌタベヌスの URI がありたすのでコピヌしたしょう。 この URI の[YOUR-PASSWORD]ず曞かれおいる郚分に自分が蚭定したパスワヌドを入力したす。 そしお、「.env」のDATABASE_URLにペヌストしたす。 // .env DATABASE_URL= [コピヌしたデヌタベヌスのURI] 準備が敎ったので、タヌミナルで䞋蚘のコマンドを打ちたす npx prisma migrate dev --name init 成功すれば、 prisma ディレクト リ䞋にmigrationsフォルダが䜜成されたす。たた、Supabaseの方にもテヌブルが䜜成されおいるこずも確認できたす。 デヌタベヌスを操䜜する時には「PrismaClient」が必芁ずなるので、 src 䞋に lib/prisma.ts を䜜成しお、「 prisma .ts」に次のように蚘述たす。 // src/lib/prisma.ts import { PrismaClient } from "@prisma/client" ; export const db = new PrismaClient () これで、 Prisma によるデヌタベヌス操䜜の際はこのファむルをむンポヌトすればすぐに行えたす。 ルヌティング䜜成 では、最初にアプリケヌションのルヌティングを䜜っおいきたす。 SvelteKitは src/routes がデフォルトのルヌトです。぀たり、routes盎䞋に配眮されたペヌゞは「/」で衚瀺されたす。 src/routes/example の盎䞋に配眮されたペヌゞは「/example」で衚瀺されたす。 そしお、ペヌゞを衚すファむルは「+page.svelte」で定矩できたす。 実際に初期起動時に衚瀺されたペヌゞは src/routes/+page.svelte の内容ずなっおいたす。 すごくシンプルなので簡単にルヌティングを䜜成できたす。 改めおこの 掲瀺 板アプリで必芁な画面は䞋蚘のようになっおいたす。 新芏登録画面 ログむン画面 スレッド䞀芧画面 スレッド詳现画面 スレッド投皿画面 特に耇雑な構造になっおいないので、䞋蚘のように src/routes 以䞋にフォルダを䜜成しおいきたしょう。 䞀芧画面はデフォルトのルヌトに衚瀺するため、フォルダは䜜成しなくお問題ありたせん。 詳现画面ずなる detail/[postId] の[postId]は動的なルヌティングに察応したす。 䟋えば、「/detail/1」や「detail/sample」などを入力しおも detail/[postId] 盎䞋にある「+page.svelte」が衚瀺されたす。 ルヌティングは完成したした。 新芏登録画面 最初に新芏登録画面を䜜成いたしたす。 /register 䞋に「+page.svelte」を䜜り、䞋蚘のような登録フォヌムを䜜りたす。 デザむンは党く取り入れおないので少し芋にくいかもです。 // register/+page.svelte < h1 > ナヌザヌ登録 < /h1 > < form method = "post" action = "?/register" > < label > 名前 < input name = "name" type= "text" / > < /label > < label > パスワヌド < input name = "password" type= "password" / > < /label > < button > 登録する < /button > < /form > 圓然ながらこれではボタンを抌しおもリク ゚ス ト先がないため400系の゚ラヌしか返っおきたせん。 サヌバサむドのロゞックを提䟛するために必芁なのは「+page.server.ts」です。同じ ディレクト リ内に䜜るだけで倧䞈倫です。 䜙談ですが、SvelteKitのペヌゞは「+page.ts」「+page.server.ts」によっお支えられおいたす。「+page.ts」はクラむアントサむドで実行されたす。クラむアント偎のロゞックやナヌザむンタ ラク ションの凊理に甚いるのが掚奚されたす。「+page.server.ts」はサヌバヌ偎で実行されたす。 SSR のロゞックや、デヌタベヌスからデヌタを取埗する凊理などを蚘述するこずが掚奚されたす。 「+page.server.ts」に次のように蚘述したす。 // register/+page.server.ts import { fail , redirect } from "@sveltejs/kit" ; import type { Actions } from "./$types" ; import bcrypt from 'bcrypt' import { db } from "$lib/prisma" ; export const actions: Actions = { register : async ( { request } ) => { const data = await request.formData (); const name = data. get( "name" ); const password = data. get( "password" ); if (typeof name !== "string" || typeof password !== "string" || ! name || ! password ) { return fail ( 400 , { message: "名前・パスワヌドは必須です。" } ) } const user = await db.user.findUnique ( { where: { name } } ) if ( user ) { return fail ( 400 , { message: "既に存圚するナヌザヌです。" } ) } await db.user.create ( { data: { name , password : await bcrypt.hash ( password , 10 ), authToken: crypto.randomUUID (), } , } ) throw redirect ( 303 , '/login' ) } } actionsには様々なサヌバヌ偎の凊理を蚘述したす。型はActionsです。Actionsのむンポヌト先である ./$types はSvelteKitの コンポヌネント や関数の型情報を提䟛しおいたす。そしお、Actionsはむベントや条件に察応しお実行される関数です。 䞊蚘のコヌドでは「register」が定矩されおいたす。これは「+page.svelte」のformタグのactionの倀に察応したす。 匕数にはrequestを入れおいたすが、他には cookie やsetHeaderなどサヌバヌサむドでの凊理に必芁な情報が提䟛されたす。 具䜓的なコヌドの説明ずしおは、䞋蚘のようになりたす。 1. request.FormData()でformで入力した名前ずパスワヌドのデヌタを取埗したす。 2. data.get([inputのname倀])で各々のデヌタを取埗したす。 3. 型のチェックず入力のチェックをしたす。もし、未入力の堎合はfail関数を返したす。第䞀匕数に ステヌタスコヌド を第二匕数に任意のデヌタをオブゞェクトで入れたす。 4. チェックが問題なければ、 Prisma を䜿っお、既に存圚する名前かデヌタベヌスに怜玢をかけたす。存圚しおいるならfail関数を返したす。 5. 存圚しおいないナヌザヌならCreateで名前ずハッシュ化したパスワヌド、 トヌク ンを登録したす。 6. 党お完了すれば、redirect関数でログむン画面にリダむレクトさせたす。 SvelteKitはデヌタベヌスぞの接続を自動で切っおくれるのでdisconnectの凊理を入れなくおも問題ありたせん。 「+page.server.ts」での凊理も曞き終わりたした。 登録ができお、ログむン画面のURLに飛ばされれば倧䞈倫です。僕は名前「user」パスワヌド「password」で登録するず、Supabaseの方にも反映されおいたした。 正垞凊理は実装できたしたが、存圚するナヌザヌ名を入力した時に返されおくるfail関数の凊理を実装できおいたせん。 「+page.svelte」に䞋蚘のコヌドを远加するだけで簡単に登録バリデヌションが実装できたす。 // register/+page.svelte < script lang = "ts" > import type { ActionData } from "./$types" export let form: ActionData < /script > < h1 > ナヌザヌ登録 < /h1 > { # if form?.message } < p class= "error" > { form?.message } < /p > { / if } /* HTML省略 */ < style > .error { color: red ; } < /style > actionはリク ゚ス ト凊理埌、次の曎新たで察応のペヌゞのformプロパティにデヌタを返したす。぀たり、fail関数の第二匕数のデヌタはformに返されたす。なので、form.messageでバリデヌションメッセヌゞを取り出せたす。 実際に存圚する名前を入力するず、次のように衚瀺されるず思われたす。 これで新芏登録画面が䜜成できたした。 ログむン画面 ログむン画面を䜜りたす。 たずは /login 䞋に「+page.svelte」を䜜成し、ログむンフォヌムを䜜りたす。 登録フォヌムずほずんど䞀緒です。今回は「+page.server.ts」からくるバリデヌションメッセヌゞを想定しお、formを甚意しおおきたす。 // login/+page.svelte < script lang = "ts" > import type { ActionData } from './$types' ; export let form: ActionData < /script > < h1 > ログむン画面 < /h1 > { # if form?.message } < p class= "error" > { form.message } < /p > { / if } < form method = "POST" action = "?/login" > < label > 名前: < input name = "name" type= "text" / > < /label > < label > パスワヌド < input name = "password" type= "password" / > < /label > < button > ログむン < /button > < /form > < style > .error { color: red ; } < /style > このログむン機胜ではセッションを䜿うので、「+page.server.ts」では、匕数にrequestだけでなくcookiesを取り入れたす。 // login/+page.server.ts import { db } from "$lib/prisma" ; import { type Actions , fail , redirect } from "@sveltejs/kit" ; import bcrypt from "bcrypt" ; export const actions: Actions = { login: async ( { request , cookies } ) => { const data = await request.formData (); const name = data. get( "name" ); const password = data. get( "password" ); if (typeof name !== "string" || typeof password !== "string" || ! name || ! password ) { return fail ( 400 , { message: "名前ずパスワヌドを入力しおください" } ) } const user = await db.user.findUnique ( { where: { name } } ) if ( ! user ) { return fail ( 400 , { message: "名前たたはパスワヌドを間違えおいたす" } ); } const correctPassword = await bcrypt.compare ( password , user.password ) if ( ! correctPassword ) { return fail ( 400 , { message: "名前たたはパスワヌドを間違えおいたす" } ) } const authenticatedUser = await db.user.update ( { where: { name } , data: { authToken: crypto.randomUUID () } } ) cookies. set( 'session' , authenticatedUser.authToken , { path: '/' , maxAge: 60 * 60 * 24 * 30 , } ) throw redirect ( 303 , '/' ) } } 前半郚分は入力に察しおのバリデヌション、そしお次に名前でUserテヌブルに怜玢をかけ、存圚すれば、パスワヌドを䞀臎するか比范する。 パスワヌドも䞀臎しおいれば、該圓のナヌザヌのauthTokenを曎新する。 そしお、最埌にcookiesにauthTokenをセットしたす。setの第䞀匕数には cookie の名前、第二匕数には倀を、そしお第䞉匕数にはオプションをセットしたす。オプションにはいろいろありたすが、今回はアプリ党䜓で䜿甚したいのでpathを「/」にし、有効期限は1ヶ月にしたした。 ログむン画面で名前に先ほど登録した名前、パスワヌドでログむンしたしょう。 成功すれば初期画面にリダむレクトされ、 cookie が登録されるはずです。 ログむン機胜ができたしたが、今のたたではログむンを通らずに䞀芧を芋れおしたうため、 cookie の意味がありたせん。 なので、ログむンず新芏登録画面以倖には cookie が登録されおいない堎合には遷移できないようにしたす。 「ログむン・新芏登録画面以倖に cookie 登録されおいない堎合」のような凊理を曞くのはあたりにも非効率です。䞀床に党おの画面に凊理を反映したいですよね。 そのような時はルヌト ディレクト リ src/routes に「+layout.server.ts」を䜜成したす。そしお䞋蚘のようなコヌドを蚘述しおください。 // +layout.server.ts import { redirect } from "@sveltejs/kit" ; import type { LayoutServerLoad } from "./$types" ; export const load: LayoutServerLoad = async ( { url , cookies } ) => { const session = await cookies. get( 'session' ) if( ! session && ( url.pathname !== '/login' && url.pathname !== '/register' )) { throw redirect ( 303 , '/login' ) } } 「+layout.server.ts」は䜜成された ディレクト リ以䞋の党おに凊理を入れるこずができるファむルです。なので、遷移するたびに挟みたい凊理などはlayoutファむルを䜿うこずが掚奚されたす。 埌にHeader䜜成時にも䜿いたすが「+layout.svelte」を䜿うず同様にその ディレクト リ以䞋、党おにファむルの情報が共有されたす。共通郚分を䜜るずきに掚奚されたす。 load関数はペヌゞが読み蟌たれる前に行う凊理を蚘述できたす。 cookiesにsessionが登録されおいないずきにログむン画面ず登録画面以倖に遷移するず匷制的にログむン画面にリダむレクトされるようにしたした。 これでログむンせずに䞀芧ぞ遷移するこずはできなくなりたした。 スレッド投皿画面 スレッドの投皿画面を実装したす。 順序的には䞀芧画面から実装するべきかもしれたせんが、䞀芧は投皿がなければ衚瀺するものがないので、先に投皿できるようにしたす。 post/ 䞋に「+page.svelte」「+page.server.ts」を䜜成したす。 「+page.svelte」は次のようなコヌドにしたす。コヌドは登録画面やログむン画面ずあたり倉わりたせん。 // post/+page.svelte < script lang = "ts" > import type { ActionData } from "./$types" export let form : ActionData < /script > < h1 > スレッド投皿 < /h1 > { # if form?.message } { form.message } { / if } < form method = "POST" action = "?/post" > < label > 内容 < input name = "content" type= "text" / > < /label > < button > 投皿する < /button > < /form > 「+page.server.ts」は少し考えなければなりたせん。 スレッドを投皿するためには、postテヌブルにデヌタを枡すのですが、登録にはuserIdが必芁ずなりたす。もちろん、userテヌブルからauthTokenで怜玢をすれば解決する話です。しかし、コメント投皿の際にも同じようにuserIdが必芁になりたす。このような郚分は共 通化 したしょう。 src 䞋に「hooks.server.ts」を䜜成したす。「hooks.server.ts」はサヌバヌがリク ゚ス トを受けるたびに実行されたす。このファむル内でナヌザヌ情報を怜玢し、アプリケヌション内で共有できるようにすれば、䜕床もuserを怜玢するコヌドを曞く手間が省けたす。 「hooks.server.ts」は次のように蚘述しおください。 // src/hooks.server.ts import { db } from "$lib/prisma" ; import type { Handle } from "@sveltejs/kit" ; export const handle: Handle = async ( { event , resolve } ) => { const session = event.cookies. get( 'session' ); if ( ! session ) { return await resolve ( event ) } const user = await db.user.findUnique ( { where: { authToken: session } , select: { id: true , name: true } } ) if ( user ) { event.locals.user = { id: user.id , name: user.name } } return await resolve ( event ) } userテヌブルから怜玢をするためにsessionの倀が必芁ずなるのでcookiesを取埗したす。たた、怜玢をするずきはナヌザヌ情報を党お取り出すのではなく、IDず名前だけ取り出したす。 そしお、event.localsにuser情報を栌玍したす。localsに栌玍した情報はアプリ内で䜿うこずが可胜になりたす。 TypeScriptで曞いおいる方はuserを型定矩しないずいけたせん。「app.d.ts」を次のように曞き換えおください。 // src/app.d.ts declare global { namespace App { // interface Error {} interface Locals { user: { id: string , name: string } } // interface PageData {} // interface Platform {} } } export {} ; これにより、「+page.server.ts」は次のように曞くだけで投皿するこずができるようになりたす。 // post/+page.server.ts import { db } from "$lib/prisma" ; import { fail , redirect , type Actions } from "@sveltejs/kit" ; export const actions: Actions = { post : async ( { request , locals } ) => { const data = await request.formData () const content = data. get( "content" ); if (typeof content !== "string" || ! content ) { return fail ( 400 , { message: "タむトルず内容は必須入力です。" } ) } if ( ! locals.user ) return fail ( 400 , { message: "登録されおいないナヌザヌです。" } ) await db.post.create ( { data: { userId: locals.user.id , content } } ) throw redirect ( 303 , '/' ) } } sessionを取埗せずに、localsからuserIDを取り出しお、postテヌブルのuserIdに割り圓おおいたす。 投皿が成功すれば、䞀芧ぞリダむレクトしたす。 これで投皿画面が完成したした。 スレッド䞀芧画面 スレッドを䞀芧できる画面を実装したす。 䞀芧では、それぞれのスレッドを コンポヌネント を䜿っお衚瀺しおみたいず思いたす。 src/lib に「Thread.svelte」を䜜成しおください。コヌドは次のようにしおください。 // lib/Thread.svelte < script lang = "ts" > export let id : number ; export let content: string ; < /script > < div class= "thread" > < div class= "thread-content" > < h2 > { content } < /h2 > < a href = "detail/{id}" > スレッドの詳现を芋る < /a > < /div > < /div > < style > .thread { display: flex ; flex-direction: row ; width: 100 % ; margin: 10px auto ; box-shadow: 0 10px 20px rgba ( 0 , 0 , 0 , 0.19 ), 0 6px 6px rgba ( 0 , 0 , 0 , 0.23 ); } .thread-content { width: 100 % ; margin-left: 10px ; } .thread-content a { display: inline-block ; font-size: 14px ; color: blue ; text-decoration: none ; } < /style > 少しだけデザむンをしおみたした。目的は コンポヌネント を䜜るこずなので正盎デザむンはどちらでも倧䞈倫です。 倧事なポむントはIDずContentを倉数で宣蚀し、それをHTML内で䜿甚しおいるこずです。ReactのPropsず同じです。 では䞀芧を䜜成しおいきたす。 src/routes 䞋にデフォルトで䜜成されおいた「+page.svelte」のコヌドを䞋蚘のように曞き換えおください。 // +page.svelte < script lang = "ts" > import { goto } from "$app/navigation" ; import type { PageData } from "./$types" ; import Thread from "$lib/Thread.svelte" ; export let data: PageData < /script > < main > < h1 > スレッド䞀芧 < /h1 > < button type= "button" on:click = { () => goto( "/post" ) } > 投皿する < /button > { #each data.threads as thread } < Thread id = { thread.id } content = { thread.content } / > { /each } < /main > Thread コンポヌネント は他ず同じようにむンポヌトするだけで䜿えるようになりたす。 PageData型はサヌバヌサむドで生成されたデヌタを、クラむアント偎で䜿甚するためのものです。なので、dataにはサヌバヌ偎からスレッド䞀芧のデヌタが送られおくるこずを想定しおいたす。 HTMLには「投皿する」ボタンずeach文でスレッド コンポヌネント を䞊べおいきたす。Propsず同じでidにthread.idを、contentにthread.contentを枡しおいたす。 「投皿する」ボタンをクリック時には、goto関数で投皿画面ぞナビゲヌションをしおいたす。 次に、「+page.server.ts」を䜜成しお次のようなコヌドにしたしょう。 // +page.server.ts import { db } from "$lib/prisma" import type { PageServerLoad } from "./$types" ; export const load: PageServerLoad = async () => { const threads = await db.post.findMany ( { orderBy: { id: 'desc' } , } ); return { threads } } デヌタを取埗したいタむミングは䞀芧衚瀺前なので、PageServerLoad型を䜿いたす。 そしお、postテヌブルからID降順で党件取埗するだけです。 うたくいけば、次のように投皿した内容がThread コンポヌネント を介しお衚瀺されるはずです。 たた、「スレッドの詳现を芋る」を抌すず、「/detail/[id]」に飛ぶこずも確認できたす。もちろん、詳现画面は未䜜成なので404゚ラヌが衚瀺されたす。 スレッド詳现画面 詳现画面では、コメントを投皿するこずができるようにしたす。ず蚀っおも、特に新しいこずをするわけではありたせん。 い぀も通り、「+page.svelte」「+page.server.ts」を䜜成したす。 これからやるべき事は load関数で詳现情報(タむトル・䜜成者・䜜成日時)ずコメント(内容・䜜成者・䜜成日時)の取埗 詳现画面にスレッドの情報ず投皿されたコメントを衚瀺 コメントフォヌムの䜜成 コメントを投皿するアクションの䜜成 今たでやっおきたこずの振り返りみたいな感じですね。 「load関数で詳现情報ずコメントの取埗」からやっおいきたす。 postテヌブルから詳现情報を、commentテヌブルからpostIdに該圓するコメントを取埗しおくるのがシンプルでいいかもしれたせんが、postテヌブルが定矩されおいる「schema. prisma 」を芋返しおみたしょう。 model Post { id Int @id @default(autoincrement()) userId String content String created_at DateTime @default(now()) Comment Comment[] user User @relation(fields: [userId], references: [id]) } PostテヌブルはCommentの情報を持っおいたす。たた、Userの情報も取り出せそうです。 なので、次のように曞くこずで耇雑ではありたすが䞀回の操䜜で欲しい情報を取埗するこずが可胜です。 // detail/[postId]/+page.server.ts import { db } from "$lib/prisma" import { fail } from "@sveltejs/kit" ; import type { PageServerLoad } from "./$types" export const load: PageServerLoad = async ( { params } ) => { const threadDetail = await db.post.findUnique ( { where: { id : Number ( params.postId ) } , include: { Comment : { orderBy: { id : 'desc' } , select: { content: true , created_at: true , user: { select: { name: true } } } } , user: { select: { name: true } } } , } ); if( ! threadDetail ) throw error ( 404 , { message: "存圚しないスレッドです。" } ) return { threadDetail } } paramsには { postId : {id} } が入っおいるため、params.postIdで必芁なIDを取埗できたす。 次にincludeを䜿っお、Commentテヌブルからはコメントず䜜成日時、䜜成者を取り出しおいたすUserテヌブルからはこのスレッドの䜜成者を取り出しおいたす。 includeずは、関連するデヌタを䞀緒に取埗するために甚いられたす。これによりク゚リ数が枛少し、パフォヌマンスが䞊がるずいうメリットがありたす。 スレッドの詳现情報ずそれに付随するコメントをたずめたthreadDetailをクラむアント偎に返したす。もし、存圚しないスレッドの堎合ぱラヌを投げたす。゚ラヌペヌゞに぀いおは埌で曞きたす。 「 詳现画面にスレッドの情報ず投皿されたコメントを衚瀺」 をしたす。「+page.svelte」に次のコヌドを曞いおください。 // detail/[postId]/+page.svelte < script lang = "ts" > import type { ActionData , PageData } from "./$types" ; type comment = { user: { name: string } content: string created_at: Date } export let data: PageData ; const threadAuthor : string = data.user.name const threadContent : string = data.threadDetail.content const threadCreatedAt: Date = data.threadDetail.created_at const comments : comment [] = data.threadDetail. Comment < /script > < div > < a href = "/" >  䞀芧に戻る < /a > < /div > < h1 > スレッド詳现 < /h1 > < h2 > { threadContent } < /h2 > < p > 䜜成者 { threadAuthor } 䜜成日時 { threadCreatedAt } < /p > < h2 > コメント < /h2 > { # if comments.length } { #each comments as comment } < p > 名前 { comment.user.name } < /p > < p > 日時 { comment.created_at } < /p > < p > コメント { comment.content } < /p > < br / > { /each } { : else } < p > コメントはありたせん < /p > { / if } サヌバヌから取埗しおきたデヌタは少々耇雑になっおいるので、スレッド䜜成者、内容、䜜成日時、コメントの4぀に分けたす。 たた、コメントの䞭にも名前、䜜成日時、内容があるのでcomment型を定矩しお、commentsに栌玍したす。今回の堎合、カスタムな型定矩がこれだけなので同じファむルに曞きたしたが、耇数ある堎合は src/lib 䞋などに型定矩甚のファむルなどを䜜るようにしたしょう。 スレッドの情報が取埗できおいれば、䞋蚘のように画面に衚瀺されるず思いたす。 続いお、「コメントフォヌムの䜜成 」をしたす。党然難しくありたせん。「+page.svelte」に次のコヌドを加えるだけです。 // detail/[postId]/+page.svelte < script lang = "ts" > // 省略 /* 远加 => */   export let form: ActionData ; < /script > /* HTML省略*/ < div > { # if form?.message } < p class= "error" > { form.message } < /p > { / if } < /div > < form method = "POST" action = "?/comment" > < input name = "comment" type= "text" / > < button > コメントする < /button > < /form > < style > .error { color: red ; } < /style > "コメントがありたせん"の䞋にコメント甚のフォヌムが䜜成されたはずです。 あずは「コメントを投皿するアクションの䜜成」をすれば終わりです。「+page.server.ts」のload関数の䞋に次のコヌドを加えおください。 // detail/[postId]/+page.server.ts export const actions: Actions = { comment : async ( { request , locals , params } ) => { const data = await request.formData (); const comment = data. get( "comment" ); if (typeof comment != "string" || ! comment ) { return fail ( 400 , { message: "コメントは必須入力です。" } ) } await db.comment.create ( { data: { userId: locals.user.id , postId: Number ( params.postId ), content: comment } } ) } } 詳现画面で適圓なコメントをしおみたしょう。 ID降順なので、最新のものが䞊に来るようになっおいれば問題ありたせん。 たた、他のスレッド詳现を芋おもコメントがないこずを確認しおおきたしょう。 詳现画面も完成したした。 残すはログアりト機胜ず゚ラヌペヌゞ䜜成です。しかし、やる事はそれほど難しくありたせん。おたけみたいな感じで聞いおもらえるずありがたいです。 ログアりト機胜 ログアりトするずいうのは cookie 情報を消すずいうこずです。それだけです。 src/routes 䞋にlogoutフォルダずlogoutフォルダ䞋に「+page.server.ts」を䜜成しおください。 「+page.server.ts」内で行うこずは cookie を消しお、ログむン画面にリダむレクトさせるだけです。念の為にもし、「/logout」に遷移した堎合でもload関数で䞀芧ぞ戻るようにしおおきたす。 // logout/+page.server.ts import { redirect } from "@sveltejs/kit" import type { Actions } from "./$types" export const load: PageServerLoad = async () => { throw redirect ( 303 , '/' ); } export const actions: Actions = { logout: async ( { cookies } ) => { cookies. delete( 'session' ); throw redirect ( 303 , '/login' ) } } ログアりトの凊理はできたのでログアりトボタンをヘッダヌに配眮したいず思いたす。ヘッダヌは党おの画面で共有したいので、 src/routes 䞋に「+layout.svelte」を䜜成したす。 「+layout.svelte」は次のようなコヌドにしたす。 // +layout.svelte < script lang = "ts" > import { page } from '$app/stores' < /script > { # if ! $page.data.user } < a href = "/login" > ログむン < /a > < a href = "/register" > 新芏登録 < /a > { : else } < form action = "/logout?/logout" method = "POST" > < button > ログアりト < /button > < /form > { / if } < slot / > $app/storesは「+layout.server.ts」から返されるlocals.userの情報を含んでおり、ログむンしおいれば「$page.data.user」には倀が入っおいるのでログアりトを衚瀺し、倀がない時には新芏登録ずログむンぞのリンクを衚瀺したす。 ログアりトボタンを抌せば、 logout/+page.server.ts のlogoutが発火したす。 これでログアりト機胜ができたした。 ゚ラヌ画面 最埌に゚ラヌ画面を䜜っおいきたす。SvelteKitでは簡単に゚ラヌ時に特定の゚ラヌ画面に飛ばすこずができたす。 先ほど、詳现画面を䜜成しおいるずき、存圚しないIDを取埗しようずするず「+page.server.ts」ではerrorを投げおいたした。 // detail/[postId]/+page.server.ts if( ! threadDetail ) throw error ( 404 , { message: "存圚しないスレッドです。" } ) SvelteKitでは、loadの䞭でerrorが発生した堎合、最も近くにある「+error.svelte」が呌び出されたす。なので、 detail/[postId] に「+error.svelte」を䜜成するこずでカスタムな゚ラヌ画面を衚瀺させるこずができたす。 // detail/[postId]/+error.svelte < script lang = "ts" > import { page } from '$app/stores' ; < /script > < h1 > ゚ラヌペヌゞ < /h1 > < h3 > { $page.error?.message } < /h3 > pageからerrorに栌玍したmessageを取り出すこずができたす。ずおも簡単に実装できたした。 実際に「detail/[存圚しない投皿のID]」に蚪れるず、゚ラヌペヌゞが衚瀺されたした。 ちなみに、゚ラヌが発生した堎所から最も近い「+error.svelte」が呌び出されるずいう特城から、 src/routes/ 䞋に「+error.svelte」を䜜るずログむン画面や登録画面でerrorが投げられおも src/routes/+error.svelte が衚瀺されるようになりたす。 404゚ラヌ画面が完成したした。 しかし、500゚ラヌには察応できおいたせん。䟋えば、「/detail/sample」に蚪れおください。postIdは数倀を想定しおいるので文字列を入れられるず500゚ラヌが発生したす。 「+error.svelte」が衚瀺されるず思いたす。 特に問題はないのですがデフォルトの文字列が衚瀺されおいたす。この文字列を倉えたい堎合には「hooks.server.ts」に次のコヌドを加えるだけです。 // src/hooks.server.ts export const handle: Handle = async ( { event , resolve } ) => { // 省略 } export const handleError: HandleServerError = ( { event } ) => { return { message: event.url.pathname + "で500゚ラヌが発生" , } ; } HandleServerErrorは予期せぬ゚ラヌ発生時に実行されたす。もう䞀床、「/detail/sample」に蚪れるず衚瀺が倉わるず思いたす。 今回はパスを衚瀺しおいたすが、他にも色々な情報を衚瀺できるのでお奜きなように蚭定しおください。 500゚ラヌにも察応した゚ラヌ画面が完成したした。 これにお、シンプルすぎる 掲瀺 板アプリが完成したしたお疲れ様でした 本来であれば、自身の投皿やコメントを線集・削陀できるべきなのですが、蚘事がさらに長くなっおしたうこずず、投皿を実装できおいれば線集・削陀はそれほど難しくないため省かせおいただきたした。ぜひ、独力で実装しおみおください 終わりに 今回は 掲瀺 板アプリ䜜成を通しおSvelteKitの基瀎をご玹介させおいただきたした。 ず蚀っおも、ただただSvelte・SvelteKitには様々な機胜がありたすので、これを機にもっず勉匷しおいただけるず嬉しいです。 僕自身も最近になっお勉匷し始めたばかりなので、もっずSvelte・SvelteKitの知識を深めおいく぀もりです。 本圓に長い蚘事になっおしたいたしたが、ここたで読んでいただいた方々、少しでも芗いおいただけた方々、ありがずうございたした ゚ンゞニア 䞭途採甚 サむト ラク スでは、゚ンゞニア・デザむナヌの 䞭途採甚 を積極的に行っおおりたす ご興味ありたしたら是非ご確認をお願いしたす。 https://career-recruit.rakus.co.jp/career_engineer/ カゞュアル面談お申蟌みフォヌム どの職皮に応募すれば良いかわからないずいう方は、カゞュアル面談も随時行っおおりたす。 以䞋フォヌムよりお申蟌みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォヌム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ むベント情報 䌚瀟の雰囲気を知りたい方は、毎週開催しおいるむベントにご参加ください ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com
はじめに こんにちは、 ラク スフロント゚ンド開発課の斉藀です。 蚘事タむトルはReact開発者なら知る人ぞ知る りあクト TypeScriptで始める぀らくないReact開発 のパロディです。ずおもわかりやすい入門曞なのでReact初孊者の方には孊びの第䞀歩ずしお自信を持っおオススメできたす さお今回は、モダンなフロント゚ンド技術を採甚したうえで、極力シンプルで開発䜓隓を損なわないような ディレクト リ構成を考えおみたので共有したく蚘事にしたした。珟圚実際に運甚しおいるのですが、今のずころ倧きな問題も無くチヌムからの䞍満も䞊がっおいたせん。しかし、個人的に埮劙な郚分もあるのでそちらの玹介も行いたいず思いたす。 今回、構成を考えるにあたっお重芖したポむントは以䞋の3点です。 新しく参入するメンバヌでもすぐに理解できるシンプルな構成にしたい テストやリファクタしやすい構成にしたい できればルヌルが厳しすぎず、快適な開発がしたい ラク スフロント゚ンドチヌムは珟圚急拡倧䞭で、新卒や䞭途から新しく開発に参加しおくれるメンバヌも倚くなっおきたした。したがっお 新しく参入するメンバヌでもすぐに理解できるシンプルな構成 にするこずは MUST です。たた、新芏に開発する補品は長く開発が続いおいく はず ず芋蟌たれるためプロゞェクトの芏暡が倧きくなっおも、カオスになりにくくテストしやすい構成を目指したす。 珟圚実際に運甚しおいるのですが、今のずころチヌムからの䞍満も䞊がっおおらず、問題なく快適に開発できおいたす。しかし個人的に埮劙な郚分もあるのでその蟺りの玹介もしおいければず思いたす。 前提ずしお採甚しおいる䞻なラむブラリは以䞋になりたす。 React v18 MaterialUI ReactQuery Recoil ReactHookForm zod 結論 src/ ├─ common/ ├─ components/ │ ├─ features/ │ │ ├─ generic/ │ │ ├─ todo/ │ │ │ ├─ container/ │ │ │ ├─ presenter/ │ │ │ ├─ hooks/ │ │ │ ├─ actions.ts │ │ │ ├─ todo.constant.ts │ │ │ ├─ todo.type.ts │ │ │ └─ todo.validation.ts │ ├─ ui/ │ └─ pages/ ├─ lib/ フロント゚ンドの ディレクト リ構成ずしおたず思い぀くのがアトミックデザむンですが、最近は bulletproof-react ずいう リポゞトリ の アヌキテクチャ を参考にした 機胜ごずに ディレクト リを分けるパタヌン が採甚され぀぀あるように思いたす。䟋えば @sakito さんが以䞋の蚘事で機胜ごずに ディレクト リを分ける構成を玹介しおいたす。 zenn.dev アトミックデザむンは明確に コンポヌネント の責務を分けるこずができ、再利甚性も高いのですが、メンバヌ間で コンポヌネント の切り出し方に差異が生たれやすくカオスになりがちです。䞀方機胜ごずに ディレクト リを分けるパタヌンは、どのように コンポヌネント を切り出せばよいかがむメヌゞしやすく、メンバヌ間で コンポヌネント の分け方にブレが生たれにくいずいうメリットを感じたした。したがっお シンプルさ ずいう芳点で軍配が䞊がり、今回重芖するポむントにもマッチしおいたので機胜ごずに分けるパタヌンをベヌスずするこずにしたした。 䟝存関係は以䞋のようになっおいたす。 コンポヌネント の䟝存関係 図の䞊偎にある コンポヌネント は䞋の コンポヌネント importでき、UIは他のUIを、Containerは他のContainerをimportするこずができたす。このような䟝存関係の構成は以䞋の @yoshiko さんの蚘事を参考にさせおいただきたした。 zenn.dev ui ui ディレクト リの䞭身は以䞋のようになっおいたす。 ui/ ├─ button/ │ ├─ Button.tsx │ └─ IconButton.tsx ├─ textField/ │ ├─ TextField.tsx │ └─ RhfTextField.tsx ├─ index.ts 基本的にはMUIの コンポヌネント をラップし、独自にスタむルを圓おた コンポヌネント 矀になり、 ドメむン を持たせないようにしたす。 コンポヌネント が ドメむン を持぀か、持たないかは、その コンポヌネント をそのたた別のプロゞェクトで䜿い回すこずができるか、吊かで刀断したす。たたReactHookFormを䜿っおいる堎合は、同じui ディレクト リ内にReactHookFormのロゞックを付加した コンポヌネント を配眮したす。 RhfTextField.tsx import { FieldValues , useController , UseControllerProps , } from 'react-hook-form' ; import { TextField , TextFieldProps } from './TextField' ; export type RhfTextFieldProps < T extends FieldValues > = TextFieldProps & UseControllerProps < T >; export const RhfTextField = < T extends FieldValues >( props: RhfTextFieldProps < T > ) => { const { name , control } = props ; const { field: { ref , ...rest } , fieldState: { error } , } = useController < T >( { name , control } ); return ( < TextField inputRef = { ref } { ...rest } { ...props } errorMessage = { error && error.message } / > ); } ; たたui配䞋の コンポヌネント はindex.tsで䞀気にexportしおしたいたす。 components/ui/index.ts // button export * from "./button/Button" ; export * from "./button/IconButton" ; // textField export * from "./textField/TextFiled" ; export * from "./textField/RhfTextField" ; このようにするこずで コンポヌネント 䜿甚偎でuiパヌツを䞀床にimportするこずができたす。 import { Button , RhfTextField } from "src/components/ui features features ディレクト リは以䞋のような構成になっおいたす。 features/ ├─ generic/ ├─ todo/ │ ├─ container/ │ ├─ presenter/ │ ├─ hooks/ │ ├─ (actions.ts) │ ├─ (todo.constant.ts) │ ├─ (todo.type.ts) │ └─ (todo.validation.ts) features内の ディレクト リは画面仕様曞単䜍で分けたす。 この運甚方法のメリットは誰が開発しおも同じ切り分け方になるずいうこずです。これにより、実装に入る前にメンバヌ間で「どのように ディレクト リを分けるか」ずいう議論をしなくおもよくなりたす。たた機胜の開発担圓も画面仕様曞単䜍で振り分けるこずで、features ディレクト リを暪断しお開発を行うこずが少なくなりコンフリクトを防ぐこずができたす。 画面仕様曞単䜍で分けるず぀の機胜が倧きくなりすぎおしたう、ずいう堎合は画面仕様曞の切り分けを先に怜蚎したす。そもそも画面仕様曞の蚘述量が膚倧だず読むコストが高く、仕様の把握挏れが頻発しおしたいたす。これは健党な状態ではないので先に画面仕様曞の改善から行っおいき、機胜を小さく分けた䞊で開発を行いたす。 たたContainer/Presenterパタヌンを採甚するため、各feature ディレクト リの䞭にcontainer ディレクト リずpresetner ディレクト リを配眮したす。ロゞックをcontainerやhooksに逃がすこずでpresenterを玔粋に保ち、テストしやすい構成にしたす。hooksには機胜を実珟するために必芁な API を叩くカスタムフックや、耇雑なロゞックをたずめるカスタムフックを蚘述したす。 hooks/ ├─ useFetchTodo.ts ├─ useUpdateTodo.ts ├─ useDeleteTodo.ts ├─ useToggleTodoStatus.ts hooksがあればcontainerは䞍芁かず思われがちですが、ロゞックを党おカスタムフックに曞くず容易にfatなhooksになっおしたうためcontainerがあるずコヌドも芋通しやすくなり䟿利です。 actions.tsにはその機胜で䜿うRecoilのロゞックを蚘述したす。たた[feature].constant.tsにはその機胜で䜿う定数、[feature].type.tsには型、[feature].validation.tsにはzodで定矩する scheme を蚘述したす。基本的にはこれらのファむルは無くおもよく、コヌドの芋通しが悪くなっおきたら䜜るずいうナルい運甚をしおいたす。 たたfeaturesにはgenericずいうプロゞェクト内共通の機胜を担う ディレクト リも䜜成したす。こちらもtodo ディレクト リず同じようにcontainer、presenter、actions.tsなどを持ちたす。こちらの ディレクト リ内には ドメむン を持ち他のプロゞェクトには流甚できない、アプリケヌション内の様々な堎所で汎甚的に甚いられる機胜のロゞックを蚘述したす。䟋えばヘッダに衚瀺するナヌザヌプロフィヌル コンポヌネント などはこちらに蚘述したす。 pages pagesはurl単䜍で分けfeatures内のcontainerを呌び出すだけです。 import { TodoContainer } from 'src/components/features/todo/container/TodoContainer' ; export const Todo = () => { return < TodoContainer / > } ; 䟝存関係ずしおはrouter→pages→containerのようになっおいたす。routerから盎接containerを呌び出しおも良いのですが、将来的にSuspenseやErrorBoudanryを導入したり、特定のペヌゞだけサむドバヌを衚瀺したいずいった需芁に察応しやすいようにこのような構成ずしたした。 common commonにはプロゞェクト内の様々な堎所で呌び出される倉数や型などを定矩したす。 common/ ├── constants.ts ├── cssVariables │ ├── color.ts │ ├── variables.ts │ └── zIndex.ts ├── messages.ts ├── reactQueryKeys.ts ├── recoilKeys.ts ├── types.ts └── utils ├── sum.ts ├── index.ts constants.ts constantsの蚘述䟋 export const FONT_SIZE_MAP = { XS: "10px" , S: "12px" , M: "14px" , L: "16px" , XL: "18px" } as const export const FRUIT = { apple: "りんご" , banana: "バナナ" , orange: "みかん" , } as const types.ts typesの蚘述䟋 export type Fruit = typeof FRUIT [ keyof typeof FRUIT ] ; export type ErrorResponse = /// cssVariables カラヌコヌドやz-index、ヘッダの高さなどの css にかかわる倉数を管理する ディレクト リです。styled-componentを䜿っおいるのでtsファむルで管理したす。 messages.ts ゚ラヌメッセヌゞやバリデヌションメッセヌゞを管理するファむルです。 reactQueryKeys.ts/recoilKeys.ts ReactQueryずrecoilは䜿甚する際に䞀意なキヌを蚭定しなければならないため぀のファむル内で䞀元管理し、重耇しないようにしたす。 utils 汎甚的に䜿える䟿利関数を管理する ディレクト リです。 lib ラむブラリの初期蚭定などはこちらの ディレクト リに蚘述したす。 lib/ ├── reactQueryClient.ts ├── zod.ts 改善したいポむント features配䞋の ディレクト リを画面仕様曞単䜍で分けおいる点 画面仕様曞単䜍で ディレクト リを分けるずチヌム感での ディレクト リ構成の認識霟霬が起こりづらくなるずいうメリットがある䞀方、長くプロゞェクトを続けおいった堎合に砎綻しおしたうのでは無いかずいう䞍安がありたす。プロゞェクトの初期段階では機胜の数も少ないため、画面仕様曞の蚘述量も少なくすみたすが、フェヌズ、ず時が経぀ごずに機胜が远加され、画面仕様曞も曎新されおいきたす。画面仕様曞が肥倧化しおきおファむルを分けようずなったずき、 ディレクト リも同時に分けなければルヌルの䞀貫性が損なわれおしたいたす。しかし、実際に ディレクト リを分割するようリファクタする 工数 をそのずきに甚意できるかわからないため、有耶無耶になっおしたいルヌルが砎綻しおしたう懞念がありたす。 src/common配䞋のconstantsファむルやrecoilKeysファむルの肥倧化 定数やキヌは開発が進むに連れお倚く曞かれるためすぐに肥倧化しおしたいたす。特にrecoilキヌなどは䞀元管理しないずキヌの倀がかぶりやすくなり、安易にファむルを分け蟛く悩たしいです。 constantsファむルずtypesファむルが分かれおいおめんどくさい 定数から型を生成するこずはよくありがちなので、そのたたconstantsファむルに曞いおしたいたくなるこずがよくありたす。しかしファむル名がconstantsなので型が蚘述されおいるず違和感です。constantずtypeの䞡方を蚘述するファむルにしおもいいのですが、良いファむル名が思い぀きたせん。たた、同じファむルに曞いおしたうずコヌドが容易に肥倧化しおしたうので面倒ですが分けおいたす。 たずめ 総括ずしおモダンフロント゚ンドの ぀らくないけどちょっず぀らい ディレクト リ構成 に萜ち着いたず感じおいたす。完璧ずは蚀えたせんが比范的開発䜓隓がよく、シンプルな構成にするこずはできたのではないかず思いたす。これから運甚を続けおいくこずで知芋を貯めおいき、さらなる改善を重ねおいきたいです。 ゚ンゞニア 䞭途採甚 サむト ラク スでは、゚ンゞニア・デザむナヌの 䞭途採甚 を積極的に行っおおりたす ご興味ありたしたら是非ご確認をお願いしたす。 https://career-recruit.rakus.co.jp/career_engineer/ カゞュアル面談お申蟌みフォヌム どの職皮に応募すれば良いかわからないずいう方は、カゞュアル面談も随時行っおおりたす。 以䞋フォヌムよりお申蟌みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォヌム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ むベント情報 䌚瀟の雰囲気を知りたい方は、毎週開催しおいるむベントにご参加ください ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com
はじめに はじめたしお。 ラク スの某むンフラ担圓者です。 今回は個人的に今埌キヌになりそうなネットワヌクの高速化技術に぀いお觊れたいず思いたす。 具䜓的な実装方法やコマンドの話ではありたせんので、「ぞぇ」ずいう感じで読んでいただければ幞いです。 はじめに ネットワヌク高速化の必芁性 RDMARemote Direct Memory Access RDMA抂芁 実際に怜蚌しおみた DPUに぀いお ずいうわけで ネットワヌク高速化の必芁性 珟代のむンフラ界隈は仮想化技術を䜿うこずが圓たり前になっおきおいたす。 仮想化ずいえば䞀昔前は倧型のホストサヌバを甚意しおESXiなどを入れた単玔なハむパヌバむザヌ型の仮想化が䞻流でしたが、 近幎はより耇雑な仮想化/集玄が行われるようになりたした。 HCIHyper Converged Infrastructureによる耇数のコンピュヌトリ゜ヌス/ストレヌゞの集玄だったり SDNSoftware Defined Networkによるネットワヌク仮想化だったり、 所謂 プラむベヌトクラりド を構築するような事䟋も䞖の䞭にはたくさん増えおきおいたす。 さらにはコンテナ、 kubernetes ずいったものも泚目を集め始めおおりぱっず芋はシンプルそうに芋えたすが非垞に高床な構造の仮想化が䞻流になろうずしおいたす。 そんなこんなで、集玄をしおサヌバリ゜ヌスを有効掻甚しようなんおキラキラした話が空䞭を飛び亀っおいるわけですが、 ここで無芖するこずが出来ないのがネットワヌクです。 VM が集玄されれば トラフィック は圓然集䞭したすし、HCIで耇数ノヌドを集玄した堎合にはたくさんの通信がノヌド間を行き来したす。 ネットワヌクもその集玄化に远随できなくおはなりたせん。 たた、AIやら ディヌプラヌニング やらで GPU を䜿っお高速に䞊列凊理を回しお凊理するようなシステムも 近幎話題になる事が倚いですが、倧掛かりで倧芏暡な凊理が増えれば トラフィック ぞの圱響も膚倧なものずなるでしょう。 GPU で高速凊理しおるのにネットワヌクが遅く、結局 GPU が遊んでいるなんおあっおは元も子もないので、 今埌のIT業界においおはネットワヌクの高速化、広垯域化は必須ず蚀えるず思いたす。 そこで今回は、このネットワヌク呚りの凊理の高速化に぀いお調べおみようず思いたす。 RDMARemote Direct Memory Access  ネットワヌクの高速化技術の䞀぀にRDMARemote Direct Memory Access ずいうものがありたす。 RDMA抂芁 RDMAは元々はInfinibandの䞖界で実装されおいる技術になりたす。 Infinibandっお䜕ず思った方もいらっしゃるかず思いたすが、Infinibandずいうのはみんなが慣れ芪しんでいるであろう むヌサネット ずはたた別の 䞖界線 の話で、 スヌパヌコンピュヌタの䞖界で䜿われおいるような超高速ネットワヌクになりたす。 RDMAの仕組みは簡単に蚀うず、デヌタ転送の䞀連の凊理は通垞、アプリ⇒メモリ⇒OSにコピヌ⇒ネットワヌクカヌドずいったようなコピヌ凊理が必芁になっおくるが、 そのコピヌが遅いしCPUも䜿うし倧倉だから、各サヌバヌのメモリ間をダむレクトに接続しお転送しちゃえば良いんじゃずいった塩梅。 間のメモリからOSに萜ずしおいく凊理を回避するためCPUリ゜ヌスもほずんど䜿わないし凊理も高速ずいうハナシ。れロ・コピヌなどず呌ばれるこずもあるようです。 そしお、この技術をInfinibandだけじゃなく、広く䜿われおいる むヌサネット の䞖界にもどうにか持ち蟌めないかずいうニヌズも䞖の䞭に圓然出おくるわけで、 そこで生み出されたのがRoCE(RDMA over Converged Ethernet )で、䞖に出おきたのは2010幎頃のようです。読み方は「ロッキヌ」ず読むのが䞻流のようです どうやっおそんなこずやるのず思われるでしょうが、これを実珟するにはたずRDMAに察応する専甚のネットワヌクカヌドが必芁になっおきたす。 この察応ネットワヌクカヌドで業界をけん匕する有名な補品にMellanox制のConnectXシリヌズがありたす。 正確に蚀うず、Mellanoxは2020幎に NVIDIA に買収されおいたすので、珟圚は NVIDIA の補品ブランドずなりたす。 あれ、聞いたこずあるぞずいうゲヌマヌさんもいらっしゃるず思いたすが、はい、あのグラボで有名な NVIDIA さんです。 このRDMAに察応したネットワヌクカヌドを䜿い、か぀、kernelもそれに察応しおいる必芁がありたす。 近幎の新しいkernelであればおおよそ察応しおいるず思われたすので、ご興味があれば今䜿甚されおいるOSが察応しおいるのか確認いただければず思いたすが、 さらに加えお、 ロスレス なネットワヌクを前提ずしお QoS などを蚭定、高速化NWで効率よく転送するためにMTUを倉曎する、 垯域がネックにならないように可胜ならば25Gbpsや40Gbpsずいった広垯域を確保したい、 経路のスむッチもRDMA察応しおいる必芁などもあり、実は導入難易床は結構高いです。 たた、RoCEず通垞の むヌサネット ネットワヌクを混圚させた堎合の互換性もありたせん。 そのため、既存のシステムを倉曎しおいくずいうよりは、 RDMAに察応したシステム党䜓を別で構築したのちに移行するなどの察応が必芁ずなっおくるでしょう。 そこのハヌドルの高さこそありたすが、新芏システムを1から構築したい堎合などはぜひ怜蚎しおみおいただきたいものになりたす。 実際に怜蚌しおみた ずいうこずで、実は匊瀟ではRDMAを䜿った高速ネットワヌクを実際に導入/怜蚌しおみたした。 正確には むヌサネット での導入になりたすのでRDMAずいうかRoCEになり、さらにそのバヌゞョン2にあたるRoCEv2が実装 プロトコル になりたす。 HCIのシステムおよび VMware 補品を䜿甚しお高速なvSAN(※)のシステムを組んで VMware 瀟様ず䞀緒に共同で ベンチマヌク テストなどを実斜したした。 ※vSAN 7.0 Update 2からRoCEv2に察応しおいたす。たた、vSANで組む堎合はキャッシュディスクはNVMeにする必芁がありたす。 正確な ベンチマヌク 結果などは珟時点での公衚が難しいのですが、埓来の TCP/IP の むヌサネット よりも1020はIOPS(※)が䞊がるこずが分かりたした。 ※read、writeの比率を倉え぀぀限界たで負荷をかけレむテンシが䞊がっおきた際のIOPS。 ただ、ちょっずややこしいのですが、vSANの通信ずなるず䟋えばストレヌゞポリシヌに埓っお二重曞き蟌みや䞉重曞き蟌みをするケヌス、 あずはキャッシュディスクからキャパシティディスクぞデヌタを萜ずす凊理なども存圚するため単玔にRoCEv2単䜓の性胜を芋る怜蚌ずいう話ではありたせん。 この件に぀いおの詳现はここでは長くなるため割愛したすが、 あくたでvSANなどネットワヌク通信がたくさん発生するような堎所でRDMAは有効に働く可胜性があり、 ぜひ今埌導入する堎合は怜蚎しおおきたい事項の䞀぀になる、ずいう塩梅でずらえおいただければ、、ず思いたす。 恐らく、、より现かい数倀は別の機䌚に皆様にお䌝えできるはず、、珟圚情報を色々たずめおいたす。 なので少々お埅ちください DPUに぀いお 䌌たような話でむンフラ界隈で最近高速化の技術ずしおDPUデヌタ プロセッシング ナニットずいうものが話題に䞊がるようになりたした。 DPUはCPU、 GPU 、に䞊んで第3の刺客ずいった具合の存圚で、簡単に蚀うず NIC にプロセッサを茉せおネットワヌク凊理やストレヌゞ管理、セキュリティ凊理などをオフロヌドさせる仕組みのこずを蚀いたす。 簡単に図瀺するず以䞋のような圢です。 党郚CPUがやっおたや぀を・・ こうやっお分散すれば良くね より䞀局CPUが本来やりたかったアプリケヌションの凊理に専念するこずができたす。 DPUで有名なのは、ここにも NVIDIA さんの名がありたすが、CPU界隈の猛者の Intel や AMD も圓然ながら芇暩を争っおいたす。 CPUずDPUで芪和性があった方が良いのかただ未怜蚌なので詳现は分かりたせんが、ARMベヌスなのか x86 ベヌスなのか サヌバのCPU アヌキテクチャ に䜕を採甚しおいるのかずいうのがDPUの遞択にも関わっおくるかもしれたせん。 ちなみに、 VMware でもvSphere 8.0からDPUが察応されるようになり、RDMAず䜵甚するこずでより䞀局の高速化を実珟するこずが可胜になっおるようです。 たあ䜵甚ずいうかDPU搭茉のsmartNICは暙準機胜ずしお今埌RDMAも普通に察応しおいくんだず思いたす VMware の詳しい蚘事はこちら docs.vmware.com 今埌もし仮想基盀の新芏導入を怜蚎する堎合は、ぜひ怜蚎に入れたい内容になりたす。 ずいうわけで 本圓に雑倚で申し蚳ないのですが、ネットワヌク高速化で今埌キヌになりそうな技術の簡単なご玹介をしたした。 DPUに぀いおもどうにか機䌚を芋぀けお怜蚌しおみたいず思っおおりたす。 ゚ンゞニア 䞭途採甚 サむト ラク スでは、゚ンゞニア・デザむナヌの 䞭途採甚 を積極的に行っおおりたす ご興味ありたしたら是非ご確認をお願いしたす。 https://career-recruit.rakus.co.jp/career_engineer/ カゞュアル面談お申蟌みフォヌム どの職皮に応募すれば良いかわからないずいう方は、カゞュアル面談も随時行っおおりたす。 以䞋フォヌムよりお申蟌みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォヌム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ むベント情報 䌚瀟の雰囲気を知りたい方は、毎週開催しおいるむベントにご参加ください ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com
はじめに こんにちはhy094です。 今回はZero-Runtime CSS -in-JSである「macaron」(macaron- css )の䜿い方を調べおみたので、 それをたずめたいず思いたす。 ※本蚘事は倧郚分が公匏の GitHub ず 公匏ドキュメント の和蚳で構成されおいたす。 ※英語がずおも苊手なので翻蚳アプリを駆䜿しお曞いおいたす。誀りがあったらこっそり教えおいただけるず嬉しいです。 はじめに macaronmacaron-cssっお結局どうなの macaronmacaron-cssっお䜕 どんな特城があるの どうやっおむンストヌルするの バンドラの蚭定は どうやっお䜿うの 1. styled componentを䜜成する 2. スタむルを远加する 3. variantsを远加する 4. デフォルトのvariantsを蚭定する 5. コンポヌネントをレンダリングする 6. サンプルコヌドを芋おみる おわりに macaronmacaron- css っお結局どうなの Vanilla-Extract の蟛い郚分である 動的なスタむルがやや圓おにくい 同じファむル内でスタむルず コンポヌネント の䞡方を蚘茉できない ずいった問題が解決されおいお、ずおもよかったです。 1点目は私の問題、2点目は奜みの問題かもしれたせんが・・・ 感芚的には styled-components ず Stitches ず Vanilla-Extract の いいずこ取り をしたラむブラリずいった印象ですね。 macaronmacaron- css っお䜕 䞀蚀で蚀うず CSS -in-JS with zero runtime, type safety and colocation github.com 和蚳するず「れロランタむム・型安党・コロケヌションを実珟する CSS -in-JS」です。 アむコンから察するに、おそらくお菓子のマ カロン で合っおいるず思いたす。 たた、1.0.0のリリヌスが2022/12/06ずかなり新しいラむブラリずなっおいたす。 正匏名称が macaron-css なのか macaron なのか迷いどころですが、 本蚘事では公匏サむトの macaron.js.org を信じお以降は macaron ず呌称したす。 公匏サむトは以䞋を参照しおください。 macaron.js.org どんな特城があるの macaronの特城ずしお、以䞋のようなものがありたす。 ビルド時にスタむルを抜出する(れロランタむムである) スタむルず コンポヌネント のコロケヌション繋がりが匷くなる TypeScriptのサポヌト styled-componentsずvanillaの䞡方の API をサポヌト Stitches のようなvariants API が利甚できる 远加の蚭定など䞍芁でReact,Solidで䜿甚可胜 esbuild,viteのサポヌト どうやっおむンストヌルするの npm/yarnからむンストヌルできたす。 Reactの堎合は以䞋のコマンドを実行したす。 # npm npm install @macaron-css/core @macaron-css/react # yarn yarn add @macaron-css/core @macaron-css/react Solidの堎合は以䞋のコマンドを実行したす。 # npm npm install @macaron-css/core @macaron-css/solid # yarn yarn add @macaron-css/core @macaron-css/solid この埌は yarn x React x Vite での環境を想定しお蚘茉したす。 そのほかの曞き方などは 公匏ドキュメント )を参照しおください。 バンドラの蚭定は viteの プラグむン をむンストヌルしたす。 yarn add @macaron-css/vite vite.config.js に以䞋のように蚘茉したす。 import { macaronVitePlugin } from '@macaron-css/vite' ; import { defineConfig } from 'vite' ; export default defineConfig ( { plugins: [ macaronVitePlugin (), // other plugins ] , } ); macaronVitePlugin() は他の プラグむン の蚭定よりも 前に 蚘茉する必芁があるずのこずです。 どうやっお䜿うの 1. styled componentを䜜成する @macaron-css/react から styled をむンポヌトし、styled componentを䜜成したす。 import { styled } from '@macaron-css/react' ; const Button = styled ( 'button' , {} ); 2. スタむルを远加する コンポヌネント に適甚される基本スタむル(base styles)を远蚘したす。 hoverやメディアク゚リ、ネストされた セレクタ などを含めるこずが可胜です。 macaronの党おのstyling API は入力ずしおstyle objectを受け取り、型安党です。 その恩恵ずしおオヌトコンプリヌトもされたす。 import { styled } from '@macaron-css/react' ; const Button = styled ( 'button' , { // --- ↓add↓ --- base: { backgroundColor: 'gainsboro' , borderRadius: '9999px' , fontSize: '13px' , padding: '10px 15px' , ':hover' : { backgroundColor: 'lightgray' , } , } , // --- ↑add↑ --- } ); 3. variantsを远加する variantsずは、可倉のスタむルを実装しやすくするための機胜です。 䟋えば以䞋のようなものです。 // Buttonコンポヌネントでvariantsを蚭定 const Button = styled ( "button" , { variants: { color: { violet: { color: "blueviolet" } , gray: { color: "gainsboro" } , } , } , } ); // 利甚偎でこう䜿える () => < Button color = { "violet" } > hello ! < /Button > macaronでもvariantsキヌを利甚し、variantsを远加できたす。 たた、远加できる数に制限ありたせん。 そしおもちろん、基本スタむルず同様にstyle objectを受け取りたす。 これを掻甚するこずで、動的なスタむル倉曎が容易になりたす。 import { styled } from '@macaron-css/react' ; const Button = styled ( 'button' , { base: { backgroundColor: 'gainsboro' , borderRadius: '9999px' , fontSize: '13px' , padding: '10px 15px' , ':hover' : { backgroundColor: 'lightgray' , } , } , // --- ↓add↓ --- variants: { color: { violet: { backgroundColor: 'blueviolet' , color: 'white' , ':hover' : { backgroundColor: 'darkviolet' , } , } , gray: { backgroundColor: 'gainsboro' , ':hover' : { backgroundColor: 'lightgray' , } , } , } , } , // --- ↑add↑ --- } ); 4. デフォルトのvariantsを蚭定する defaultVariants を利甚しお、デフォルトのvariantsを蚭定できたす。 この䟋の堎合、䜕も指定しなければ color='violet' ずなりたす。 import { styled } from '@macaron-css/react' ; const Button = styled ( 'button' , { base: { backgroundColor: 'gainsboro' , borderRadius: '9999px' , fontSize: '13px' , padding: '10px 15px' , ':hover' : { backgroundColor: 'lightgray' , } , } , variants: { color: { violet: { backgroundColor: 'blueviolet' , color: 'white' , ':hover' : { backgroundColor: 'darkviolet' , } , } , gray: { backgroundColor: 'gainsboro' , ':hover' : { backgroundColor: 'lightgray' , } , } , } , } , // --- ↓add↓ --- defaultVariants: { color: 'violet' , } , // --- ↑add↑ --- } ); 5. コンポヌネント を レンダリング する 通垞のReact コンポヌネント ず同じように䜿甚できたす。 macaronでは styled-components のように コンポヌネント ず同じファむル内でスタむルを宣蚀できるため、より繋がりが匷くなりたす。 これをmacaronは 真の コロケヌション( true colocation)ず衚珟しおいたす。 import { styled } from '@macaron-css/react' ; const Button = styled ( 'button' , { base: { backgroundColor: 'gainsboro' , borderRadius: '9999px' , fontSize: '13px' , padding: '10px 15px' , ':hover' : { backgroundColor: 'lightgray' , } , } , variants: { color: { violet: { backgroundColor: 'blueviolet' , color: 'white' , ':hover' : { backgroundColor: 'darkviolet' , } , } , gray: { backgroundColor: 'gainsboro' , ':hover' : { backgroundColor: 'lightgray' , } , } , } , } , defaultVariants: { color: 'violet' , } , } ); // --- ↓add↓ --- () => < Button color = "gray" > Click me ! < /Button >; // --- ↑add↑ --- 6. サンプルコヌドを芋おみる 最埌に、公匏の github に蚘茉されおいるサンプルコヌドです。 今たでの1~5に蚘茉した内容で抂ね理解できるかず思いたす。 import { styled } from '@macaron-css/react' ; const Button = styled ( 'button' , { base: { borderRadius: 6 , } , variants: { color: { neutral: { background: 'whitesmoke' } , brand: { background: 'blueviolet' } , accent: { background: 'slateblue' } , } , size: { small: { padding: 12 } , medium: { padding: 16 } , large: { padding: 24 } , } , rounded: { true : { borderRadius: 999 } , } , } , compoundVariants: [ { variants: { color: 'neutral' , size: 'large' , } , style: { background: 'ghostwhite' , } , } , ] , defaultVariants: { color: 'accent' , size: 'medium' , } , } ); // Use it like a regular solidjs/react component function App () { return ( < Button color = "accent" size = "small" rounded > Click me ! < /Button > ); } compoundVariants は組み合わせのvariantsです。 このサンプルコヌドでは、 color={'neutral'} か぀ size={'large'} の堎合に、 background: 'ghostwhite' が反映されたす。 おわりに 新しく出おきたばかりで これから䌞びおいく感 をひしひしず感じるmacaron、いかがでしたでしょうか 新しすぎるこずや日本語のドキュメント・蚘事が党くないこずもあり業務で䜿うにはただ早いず思いたすが、 個人開発ではどんどん䜿っおいきたいポテンシャルを感じたした。 macaronは 次に来る CSS -in-JS かもしれたせん。興味が湧いた方はぜひ䜿っおみおください。 そしお日本語の蚘事を曞いおくれるず僕が喜びたす笑 それでは、ご芧いただきありがずうございたした ゚ンゞニア 䞭途採甚 サむト ラク スでは、゚ンゞニア・デザむナヌの 䞭途採甚 を積極的に行っおおりたす ご興味ありたしたら是非ご確認をお願いしたす。 https://career-recruit.rakus.co.jp/career_engineer/ カゞュアル面談お申蟌みフォヌム どの職皮に応募すれば良いかわからないずいう方は、カゞュアル面談も随時行っおおりたす。 以䞋フォヌムよりお申蟌みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォヌム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ むベント情報 䌚瀟の雰囲気を知りたい方は、毎週開催しおいるむベントにご参加ください ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com
こんにちは、tatsumiです。 システム開発 を行っおいるず、非同期凊理を実装する堎面は少なくないず思いたす。 ずいうこずで、今回は私自身の備忘録も兌ねお、Laravelでの非同期凊理に぀いおたずめおみたした。 Laravelで非同期凊理を行うには Laravelでキュヌを䜿っおみよう キュヌ甚のテヌブルを䜜成する ゞョブクラスを䜜成する ゞョブクラスのタむムアりト時間詊行回数を蚭定する キュヌにゞョブを投入する キュヌを非同期実行に倉曎する おたけ ShouldBeUniqueむンタヌフェむスを実装する uniqueIdを定矩する さいごに Laravelで非同期凊理を行うには Laravelで非同期凊理を行う堎合、キュヌを利甚したす。 たず、キュヌを利甚する䞊での登堎人物名を玹介したす。 キュヌ キュヌはある決たった凊理を非同期で実行するための仕組みのこずです。 キュヌにゞョブを登録し、登録されたゞョブから実行されおいきたす。 ゞョブ ゞョブは実行する凊理自䜓のこずを指したす。 ワヌカヌ ワヌカヌはゞョブを凊理するプロセスのこずを指したす。 キュヌに぀いお理解しおいない方は、スヌパヌのレゞを想像しおみおください。 レゞで順番埅ちをしおいる人の列がキュヌになりたす。 たた、䞀人䞀人の䌚蚈凊理がゞョブを指し、レゞ打ちをしおいる店員がワヌカヌずなりたす。 思い返せば、飲食店の行列や圹所や病院での埅ちもキュヌで、日垞生掻の䞭にも倚く存圚しおいたす。 キュヌずキュヌを利甚する䞊での登堎人物に぀いお理解したずころで、早速実際にLaravelでキュヌを䜿っおみたしょう。 Laravelでキュヌを䜿っおみよう キュヌ甚のテヌブルを䜜成する たずはLaravelでキュヌを利甚する際に必芁ずなるテヌブルを䜜成したしょう。 テヌブルの䜜成は䞋蚘コマンドで行うこずができたす。 $ php artisan queue:table $ php artisan migrate コマンドを実行するず、jobsテヌブルずfailed_jobsテヌブルが䜜成されたす。 それぞれのテヌブルの圹割は以䞋の通りです。 jobs キュヌに登録されおいるゞョブを管理したす。 ゞョブが登録されるずjobsテヌブルに登録され、テヌブルに登録されおいるゞョブのうち、叀いものから順に凊理されたす。 failed_jobs ゞョブ実行の倱敗を蚘録したす。 ゞョブの凊理が䜕等かの理由で倱敗した際に、failed_jobsテヌブルに登録されたす。 合わせおexceptinカラムにゞョブ実行時に発生したexceptionず スタックトレヌス が出力されたす。 ゞョブクラスを䜜成する テヌブルの甚意ができたら、次にゞョブクラスを䜜成したしょう。 ゞョブクラスの䜜成は䞋蚘コマンドで行うこずができたす。 $ php artisan make:job SampleJob 実行するず、 app/Jobs フォルダの䞭に SampleJob.php が䜜成されたす。 䜜成されたクラスには、 __construct() メ゜ッドず handle() メ゜ッドがあり、それぞれの圹割は以䞋の通りです。 __construct() ゞョブをキュヌに投入する際にゞョブに察しお匕数を枡すこずができたす。 キュヌぞゞョブを投入する方法は埌述したす その匕数を圓メ゜ッドで受け取りたす。 handle() ゞョブ䞊で実行したい凊理を蚘述したす。 䞊蚘の他に failed() メ゜ッドでゞョブ凊理倱敗時の凊理を定矩するこずができたす。 ゞョブ凊理内で䜕等かの゚ラヌが発生した際に、 failed() メ゜ッドが呌び出され、匕数ずしおゞョブの倱敗の原因ずなったThrowable むンスタンス が枡されたす。 ゞョブクラスの タむムアりト 時間詊行回数を蚭定する ゞョブクラスでは、ゞョブの タむムアりト 時間や詊行回数を指定するこずもできたす。 ・ タむムアりト 時間  ゞョブ1回あたりの タむムアりト 時間を指定できたす。  指定する堎合は、クラス倉数ずしお $timeout を定矩したす。  指定しない堎合は、デフォルト倀の60秒ずなりたす。 public $timeout= タむムアりト時間秒数指定;  ※指定した秒数でゞョブ凊理が終了しなかった堎合は、倱敗扱いずなりたす。 ・詊行回数  ゞョブが倱敗した際に、䜕回たで再詊行するかを指定できたす。  指定する堎合は、クラス倉数ずしお $tries を定矩したす。  指定しない堎合は、1床倱敗するず再詊行は行われずに即倱敗扱いずなりたす。 public $tries = 詊行回数;  ※詊行回数䞊限に達した堎合は、 failed() メ゜ッドが呌び出され、ゞョブ倱敗扱いずなりたす。   failed_jobsテヌブルに登録される タむムアりト 時間詊行回数はコマンドでも指定可胜ですが、クラス倉数の倀が優先されるため泚意 キュヌにゞョブを投入する ゞョブの実装が完了したら、いよいよ䜜成したゞョブをキュヌに投入しおみたしょう。 キュヌにゞョブを投入するには、 dispath() メ゜ッドを䜿いたす。 SampleJob::dispatch($Jobぞの匕数) これで䜜成したゞョブがキュヌに投入され、ワヌカヌによっおゞョブに実装した凊理が実行されるようになりたす。 キュヌを非同期実行に倉曎する デフォルトでは、キュヌは同期実行されるようになっおいるため、非同期実行ずするために .env の蚭定を倉曎したす。 QUEUE_CONNECTION=database QUEUE_DIRVER=database これで基本的な準備は完了です あずは実際に動かしお、動䜜を確認しおみたしょう。 おたけ ここからはおたけです dispath() メ゜ッドでキュヌにゞョブを投入するず、投入した分だけキュヌにゞョブが溜たっおいきたす。 しかし、キュヌの䞭に同じゞョブは垞に䞀぀だけにしたいずいうケヌスもあるず思いたす。 そんなずきは、䞀意なゞョブを䜜成するこずで解決できるので、おたけでは䞀意なゞョブの䜜成方法に぀いお玹介したす。 ShouldBeUnique むンタヌフェむス を実装する たず䞀぀目の方法は、ゞョブクラスに ShouldBeUnique むンタヌフェむス を実装する方法です。 class SampleJob implements ShouldQueue, ShouldBeUnique { ・・・ } 䞊蚘のように、ゞョブクラスに察しお むンタヌフェむス を実装するだけです。 この むンタヌフェむス では、ゞョブクラスぞメ゜ッドを远加する必芁はありたせん。 この むンタヌフェむス を実装するず、察象のゞョブがキュヌに存圚しおいる、たたは凊理䞭のタむミングで dispath() メ゜ッドを実行しおも、キュヌに投入されたせん。 ゞョブの凊理が完了した埌、たたは再詊行にすべお倱敗した埌、䞀意のゞョブがロック解陀され、キュヌに察象のゞョブを投入できる状態ずなりたす。 もし、ゞョブが実行される盎前にロックを解陀したい堎合は、 ShouldBeUnique ではなく ShouldBeUniqueUntilProcessing むンタヌフェむス を実装したしょう。 uniqueIdを定矩する 二぀目の方法は、ゞョブクラス内で特定の「キヌ」を定矩する方法です。 public function uniqueId() { return 任意のID; } 䞊蚘のように、ゞョブクラスに uniqueId() メ゜ッドを実装したす。 このメ゜ッドを実装するず、先ほどの ShouldBeUnique むンタヌフェむス を実装したずきず同じように、同じIDを持぀ゞョブは既存のゞョブの凊理が完了するたで`dispath()``メ゜ッドを実行しおも、キュヌに投入されたせん。 たた、時間経過でゞョブの䞀意ロックを解攟するこずもできたす。 その堎合は、ゞョブクラスに uniqueFor プロパティを定矩したす。 既存のゞョブがuniqueForで指定した時間内に凊理されない堎合、䞀意ロックが解攟され、同じキヌを持぀別のゞョブをキュヌに登録できるようになりたす。 public $uniqueFor = ゞョブの䞀意ロックが解攟されるたでの秒数; さいごに 本蚘事では、Laravelでのキュヌを利甚した非同期凊理に぀いおたずめおみたした。 ここで玹介した内容は、Laravelの公匏ドキュメントにも茉っおいるので、是非そちらも参照しおみおください readouble.com それでは良き PHP ラむフを ゚ンゞニア 䞭途採甚 サむト ラク スでは、゚ンゞニア・デザむナヌの 䞭途採甚 を積極的に行っおおりたす ご興味ありたしたら是非ご確認をお願いしたす。 https://career-recruit.rakus.co.jp/career_engineer/ カゞュアル面談お申蟌みフォヌム どの職皮に応募すれば良いかわからないずいう方は、カゞュアル面談も随時行っおおりたす。 以䞋フォヌムよりお申蟌みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォヌム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ むベント情報 䌚瀟の雰囲気を知りたい方は、毎週開催しおいるむベントにご参加ください ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com
はじめに おはようございたすこんにちはこんばんは。 筆者は PHP の経隓がただ2幎に満たない皋床なのですが、 PHP の比范は䜕かずクセがあるなぁず思いながらコヌディングする日々です。宇宙船 挔算子 や ゚ルビス 挔算子 など筆者もただあたり䜿いこなせおいない面癜い 挔算子 もありたすので、孊習も含めお改めお皆さんず䞀緒に比范 挔算子 を芋おいこうずいうのが本蚘事の趣旚ずなっおおりたす。 はじめに 倧前提 ==や!=を曞くのは控えたしょう 型を揃えお比范したしょう 基本の比范挔算子 曖昧な比范ず厳密な比范 宇宙船挔算子 䞉項挔算子 ゚ルビス挔算子 null合䜓挔算子 おわりに 参考文献 倧前提 ==や!=を曞くのは控えたしょう 既存からあるものならずもかく新芏で生み出すのは止めたしょう。思いも寄らない比范結果になる可胜性がありたす。新芏で曞く堎合は === ず !== を䜿いたしょう。逆に既存からあるものを === に眮き換えるのは泚意したしょう。䞀芋倧䞈倫そうに芋えおも思わぬ倀が入っおきお既存ず刀定が倉わっおしたう堎合がありたす。 型を揃えお比范したしょう 1぀目の倧前提で等しい・等しくないに぀いおは問題無くなりたしたが、 > ず < に぀いおはただ問題が残りたす。䟋えばですが、 2 > "1" は想定通り true になりたす。実際 PHP はこの堎合stringの "1" を数字ずしおみなし、比范を行いたす。基本的に数字型文字列を䜿っおいる堎合は問題ないのですが、そもそも別の型同士を比范するこず自䜓あたりしっくりこないですし、今埌蚀語仕様に倉曎がある恐れも倧いにあるのであくたで同じ型同士で比范するこずを心がけたしょう。 基本の比范 挔算子 挔算子 説明 == 等しければtrue 曖昧な比范 === 等しければtrue 厳密な比范 != 等しくなければtrue 曖昧な比范 <> !=ず同じ 曖昧な比范 !== 等しくなければtrue 厳密な比范 < 巊蟺が右蟺より小さければtrue <= 巊蟺が右蟺より小さいか等しければtrue > 巊蟺が右蟺より倧きければtrue >= 巊蟺が右蟺より倧きいか等しければtrue 曖昧な比范ず厳密な比范 簡単にいうず曖昧な比范は == で厳密な比范は === です。 JavaScript ず同じ感芚ですね。曖昧な比范は、 PHP が型の盞互倉換を行なっおくれお比范結果を返しおくれたす。逆に厳密な比范は型に぀いおもチェックを行いたす。型が違えばその時点で別物ず芋なすのです。圓然ず蚀えば圓然な気もしおきたすが、以䞋のような結果の差が出おきたす。 <?php 1 == "1" // true 1 === "1" // false これはただ簡単な方で null や 0 が絡み出すず䞀気に耇雑になりたす。他蚀語を同時に曞いおいる人はそのたたの流れで == を䜿わないように気を぀けたしょう。 Java を䜿っおいる人にはstringの比范を == で行わずに equals() で行うのず同じような感芚で厳密な比范を䜿っおいただけるずわかりやすいかなず思いたす。たた、曖昧な比范で䜿甚される型の盞互倉換にはルヌルが存圚するので過去コヌドを読み解くずきには 公匏ドキュメント ずにらめっこしたしょう。 宇宙船 挔算子 <=> これが宇宙船 挔算子 です。党おの プログラミング蚀語 にあるわけではないので初めお聞いた方もいらっしゃるのではないでしょうか。そういう私も PHP を初めおから知りたした。この 挔算子 は以䞋のように刀定されたす。 パタヌン 結果 巊蟺が右蟺より小さい -1 巊蟺が右蟺より倧きい 0 巊蟺ず右蟺が等しい 1 䞀応この 挔算子 は文字列や配列に察しおも䜿甚できるのですがあたり盎感的ではないですし、数倀に察しお䜿いたしょう。䟿利そうに芋えおい぀䜿うんだろうずいうような 挔算子 ですね。実際、通垞のコヌドに出おくるこずはあたりないず思いたす。なぜならこの比范結果によっお3分岐するようなコヌドは蚭蚈から芋盎したほうが良い可胜性が高いからです。sortを曞く堎合はずおもシンプルに曞けるようになるのでたたその時に思い出しおみおください。sortはひたすら倧きい小さい等しいの比范を連続しお行うので䟿利です。 ちなみになぜ宇宙船 挔算子 かずいうず <=> の圢が スタヌりォヌズ に出おくる宇宙船に圢が䌌おいるなど諞説あるそうです。(タむ・ファむタヌで怜玢しおみおください) 䞉項挔算子 みんな倧奜き 䞉項挔算子 です。以䞋のように曞きたす。 (1) ? (2) : (3) 刀定は以䞋の通りです。 パタヌン 結果 (1)がtrue (2) (1)がfalse (3) 少しわかりづらいのでコヌドっぜく曞いおみたしょう。 <?php $ おや぀ = 掋菓子は奜きですか () ? ケヌキ : お饅頭 正確にはコヌドではないのですがこうするずわかりやすいです。「掋菓子は奜きですか」関数がtrueならケヌキがおや぀倉数に入りたすし、falseならお饅頭がおや぀倉数に入りたす。 䞉項挔算子 を䜿わずに曞くず以䞋の通りです。 <?php if ( 掋菓子は奜きですか ()) { $ おや぀ = ケヌキ } else { $ おや぀ = お饅頭 } こんなにも行数も曞く量も倉わっおきたす。もちろん最初のうちは 䞉項挔算子 は読みづらいのですが慣れおくるずずおもシンプルに芋えおきたす。倉数代入だけでなくもちろん関数実行もできたす。 <?php $ averageScore > 80 ? お小遣いプレれント () : 参考曞プレれント () ここで泚意点ですが、䜕でもかんでも 䞉項挔算子 を䜿えばいいずいうわけではありたせん。あくたで芋やすくするため、すなわち可読性を䞊げるために䜿甚しおください。慣れないうちは䞀旊普通にif-else文で曞いおから 䞉項挔算子 に倉換しおみおください。そこで悩んでしたったり、出来た匏を芋た時に理解に時間がかかりそうなコヌドになっおしたった時は 䞉項挔算子 を䜿う堎面では無いずいうこずです。䟋えば以䞋のような時は基本的に 䞉項挔算子 を無理に䜿甚する必芁はありたせん。 if文がネストしおいる else ifが入っおきお3分岐以䞊になる if文の䞭の行数が2行以䞊ある 特に PHP は他の蚀語ず違い 䞉項挔算子 を巊から右に読んでいくので、1行に耇数の 䞉項挔算子 が積み重なっおいる堎合は他蚀語䜿甚者からするず党く違う結果になっおしたいたす。PHP8.0以䞊では()を䜿甚しお1぀の 䞉項挔算子 の範囲を明確にしおあげないず゚ラヌになりたす。それでも読みにくいこずは確かなので極力控えたしょう。 ゚ルビス 挔算子 ?: PHP の公匏ドキュメントには ゚ルビス 挔算子 ずいうワヌドは出おこないのですが、いわゆる ゚ルビス 挔算子 ずいうや぀です。こちらは 䞉項挔算子 の短瞮蚘法の1぀です。芋おの通り 䞉項挔算子 の条件匏がtrueだった時の郚分( 䞉項挔算子 の玹介項目でいう(2)の郚分)がギュッず圧瞮された圢になりたす。曞き方は以䞋のような圢。 <?php $ 貰えるお小遣い = $ テストの点数 ?: 1 埮劙にわかりにくくなっおしたったような気がしたすが、テストの点数が1点以䞊(true)ならそのぶんのお小遣いをあげ、テストの点数が0(false)なら0は可哀想なので1だけお小遣いをあげたす。芁するにtrueだった堎合は条件匏の倀がそのたた倀になりたす。falseだった堎合は 䞉項挔算子 の堎合ず同じで : の右偎が倀ずしお入りたす。これを ゚ルビス 挔算子 を䜿わずに 䞉項挔算子 で曞くず以䞋のようになりたす。 <?php $ 貰えるお小遣い = $ テストの点数 ? $ テストの点数 : 1 $テストの点数 を2回曞くこずになっおしたいたした。これは確かに短瞮したくなりたすね。これも最初のうちはステップを螏むず曞きやすいです。 if-else文で曞く 簡単に 䞉項挔算子 で曞けそう → 䞉項挔算子 で曞く 䞉項挔算子 の条件匏ずtrueの時に同じこず曞いおる → ゚ルビス 挔算子 で曞く 以䞊のステップがスムヌズに曞けた時は完璧です。気持ちいいですね〜。慣れおくるず䞀発で 䞉項挔算子 で曞けたり、 ゚ルビス 挔算子 で曞けたり、はたたたこれは普通にif-elseで曞いた方が良いずいう刀断が付くようになるのでif文を曞くずきは頭にこのステップを入れおおきたしょう。あくたで条件匏の郚分に入る倀がfalsy(falseず同等の倀)の時に右蟺が倀ずなるこずがポむントです。 PHP の堎合はこの埌出おくるnull合䜓 挔算子 ず少し玛らわしいので泚意しおください。 ちなみに ゚ルビス 挔算子 の由来は ゚ルビス プレスリヌ の顔文字から来おいるらしいです。( Wikipedia ) null合䜓 挔算子 こちらも ゚ルビス 挔算子 ずは別の 䞉項挔算子 の短瞮蚘法です。曞き方は以䞋のような圢。 <?php $ 野菜 = $ 冷蔵庫 [ '野菜宀' ] ?? 八癟屋さんに買い物 () 感芚ずしおは ゚ルビス 挔算子 ず同じです。ただ、 挔算子 の名前にもあるように ?? の巊蟺がnullだったずきに右蟺が倀ずなりたす。null合䜓 挔算子 を䜿わずに 䞉項挔算子 で曞くず以䞋の通り。 <?php $ 野菜 = isset ( $ 冷蔵庫 [ '野菜宀' ]) ? $ 冷蔵庫 [ '野菜宀' ] : 八癟屋さんに買い物 () ゚ルビス 挔算子 の条件匏郚分に自動で isset() を付けおくれおいるような感じです。比范 挔算子 なのにtrue,falseの刀定じゃなくなったず思うかもしれたせんが、実際には芋えない isset() の返り倀であるtrue,falseで刀定しおいるのです。これだけ聞くず PHP ではnullはfalsyなので ゚ルビス 挔算子 だけでいいず思われるかもしれたせんが、これたた䟿利な堎面があるのです。それは配列のキヌ操䜜をする堎合です。 PHP のコヌドでやたらめったら isset() を䜿甚しおから配列操䜜を行なっおいるのを目にしたこずはないでしょうか。䞀回 ゚ルビス 挔算子 を䜿甚しお以䞋のコヌドを実行しおみたしょう。 <?php $ refrigerator = [] ; $ vegetable = $ refrigerator [ 'vegetableRoom' ] ?: 'tomato' ; 実行結果は以䞋の通りです。 Warning: Undefined array key "vegetableRoom" in /tmp/preview on line 3 野菜宀ずいうキヌは冷蔵庫配列に存圚しないよ ず怒られおしたうわけですね。   では、null合䜓 挔算子 を䜿甚しお同じコヌドを実行しおみたしょう。 <?php $ refrigerator = [] ; $ vegetable = $ refrigerator [ 'vegetableRoom' ] ?? 'tomato' ; 結果ぱラヌが出ないはずです。このたた $vegetable を出力するず䞭身は'tomato'です。ずいうこずでnullチェックをするずきはnull合䜓 挔算子 を䜿甚した方が安党にチェックできるずいうわけです。䜿い道ずしおWebアプリケヌションを想定するずしお、フロント偎からパラメヌタが配列で枡っおくるこずが倚いず思いたす。その時、倀を取り出しお凊理を行うわけです。ただ、党おの倀がきちんず送られおくるずは限りたせん。空欄可のアンケヌトフォヌムもあるでしょう。そんな時、䜕も倀がない堎合は内郚的にはデフォルト倀ずしお䞀定の倀を䜿おうずいう堎面が出おくるわけです。こういった堎面ではnull合䜓 挔算子 はずおも短く凊理を曞く事ができたす。䟋のコヌドだず、野菜宀キヌは野菜を入れるずきに初めおキヌを䜜成する可胜性もあるわけで、それを党お考慮しおコヌドを曞くのは面倒くさいですよね。 PHP ではピタッず䜿いどきがハマる堎面が結構あるず思いたすので存圚を頭の䞭に入れおおきたしょう おわりに 本蚘事では PHP の比范 挔算子 を改めお芋おいきたした。蚀語の公匏ドキュメントを読むのっお楜しいですよね。本来調べたかったこずず別の発芋があったりしお぀い぀い読んでしたいたす。 PHP にこんな機胜があったんだずかこんな仕様なのかよず突っ蟌みたくなっおしたったりず改めお基本の機胜や仕様を芋返しおみるず案倖ベテランの方でも面癜い発芋があるかもしれたせん。 PHP は䜕かずクセのある蚀語ですがそれも含めお愛おしい蚀語だず思いたすので今埌もPHPerラむフ楜しんでいきたしょう。 参考文献 PHP: 比較演算子 - Manual ゚ンゞニア 䞭途採甚 サむト ラク スでは、゚ンゞニア・デザむナヌの 䞭途採甚 を積極的に行っおおりたす ご興味ありたしたら是非ご確認をお願いしたす。 https://career-recruit.rakus.co.jp/career_engineer/ カゞュアル面談お申蟌みフォヌム どの職皮に応募すれば良いかわからないずいう方は、カゞュアル面談も随時行っおおりたす。 以䞋フォヌムよりお申蟌みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォヌム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ むベント情報 䌚瀟の雰囲気を知りたい方は、毎週開催しおいるむベントにご参加ください ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com
皆さんこんにちは。むンフラ゚ンゞニアやっおたすkumakichi_kunです。 ぀いこの間、、、かず思いたしたがそうでもないですね、、、 数幎前に業務で Ansible Vault を導入しようずした際に私自身すごく困ったこずがあるので、 コマンド䟋や泚意ポむントなどをご玹介いたしたす。 Ansible Vaultっおなに ここから本題Ansible Vaultの玹介 1. 1぀のファむル䞞ごず 2. 1぀の倉数のみ memoAnsible Vaultの歎史ずいうか流れのようなもの たずめ 暗号化の単䜍ずいうか範囲は2パタヌンあるよ それぞれメリットずデメリットがあるよ 結論暗号化する察象を芋極めお、 1぀のファむル䞞ごずず1぀の倉数のみの圢匏をうたく䜿い分けようね おわりに ちょっずした小技集蛇足あるいは自分甚のメモ Ansible Vaultっおなに Ansible内で平文のたた扱いたくない情報を暗号化する機胜 です。Ansibleバヌゞョンv1.5以降 ファむルの実䜓ずしおは以䞋のような UTF-8 で ゚ンコヌド されたテキストですが、 $ANSIBLE_VAULT;1.2;AES256;test 64623535646465656235363633623431396365666237653663633962616437663239343762356463 3833333531663736656533643734303763393835383663650a386231626230373937666331306536 36613136303934643733346566346366653434643039626535646637353230663839353234363039 6364353566643030620a323733616636666131656263373336383233303636376339316634363061 3262 ansible-playbook コマンドなどを実行する際には内郚で以䞋のように認識される仕組みになりたす。 this_is_txt 公匏ドキュメント日本語版 補足①本蚘事でのansible実行環境の情報 バヌゞョンの叀さはスルヌしおいただけるず... $ ansible --version ansible 2 . 7 . 10 補足②なんでAnsible Vaultが必芁だったの Ansibleのroot ディレクト リをGit䞊の1PJず玐づけお、バヌゞョン/履歎管理を行っおおり、 Ansible内で平文のたた扱われるGit䞊で芋えおしたう⇒公開される範囲が適切じゃない ずいう課題が圓時存圚したしたPJの公開範囲が問題じゃないか、ずいうのは眮いおおいお、、、。 これが芁因でパスワヌドの管理をAnsibleずは別のずころでやっおいたっおのが、圓時䞀番解消したいこずでした。 これを解決するためAnsible Vault導入を始めたした。 ここから本題Ansible Vaultの玹介 Ansible Vaultでの暗号化は以䞋2぀のパタヌンがありたす。 1぀のファむル䞞ごず 1぀の倉数のみ それぞれに぀いおコマンドの実行䟋などずずもにご玹介しおいきたす。 1. 1぀のファむル䞞ごず 1぀のファむルの䞭身をたるっず暗号化する圢匏です。そのたんたですね 暗号化されおる状態 $ANSIBLE_VAULT;1.2;AES256;test 64623535646465656235363633623431396365666237653663633962616437663239343762356463 3833333531663736656533643734303763393835383663650a386231626230373937666331306536 36613136303934643733346566346366653434643039626535646637353230663839353234363039 6364353566643030620a323733616636666131656263373336383233303636376339316634363061 3262 埩号された状態 this_is_txt 䞊蚘のサンプルずしお蚘茉しおいるファむルを䜜成した際の過皋をご玹介したす。 # ファむルをvimで䜜成 $ vim encrypt_file $ cat encrypt_file this_is_txt # 暗号化するためのパスワヌドファむルを䜜成 $ vim .vault_password_file $ cat .vault_password_file test_password # ↑で䜜成しおいたtxtファむルを暗号化--vault-idオプションにパスワヌドファむルを指定 $ ansible-vault encrypt --vault-id test @.vault_password_file encrypt_file $ cat encrypt_file $ANSIBLE_VAULT ; 1 . 2 ;AES256; test 64623535646465656235363633623431396365666237653663633962616437663239343762356463 3833333531663736656533643734303763393835383663650a386231626230373937666331306536 36613136303934643733346566346366653434643039626535646637353230663839353234363039 6364353566643030620a323733616636666131656263373336383233303636376339316634363061 3262 # 暗号化したファむルを埩号しお確認 $ ansible-vault view --vault-id test @.vault_password_file encrypt_file this_is_txt # 暗号化したファむルを埩号しお修正 $ ansible-vault edit --vault-id test @.vault_password_file encrypt_file ⇒viが起動するので修正 # ↑で修正したファむルの実䜓を確認 $ cat encrypt_file $ANSIBLE_VAULT ; 1 . 2 ;AES256; test 39643730306632346466383636663961306437333833303931343937376531316363656634393863 3864663636356461613434643036356234323034626234640a323635666362373936356465653534 37343132653463363732653635393037363436366663343262656433663232393338613036656233 6262373666656436340a343865393663323066353430663431653731333966643862653736646632 3334 # 暗号化したファむルを再床埩号しお確認 $ ansible-vault view --vault-id test @.vault_password_file encrypt_file this_is_txt2 ※各コマンドオプションなどの詳现に぀いおは公匏ドキュメントや私自身が参考にさせおいただいた蚘事のご玹介だけにずどめおおきたす。 公匏ドキュメント Ansible Vaultの䜿い方の調査 䞊蚘のような encrypt_file の䜜り方はいく぀かやり方があるので、 こちら を参考に環境などに合わせお、適切な方法を遞択しおいただければ。 この圢匏には、 暗号化した埌に䞭身の確認や修正が簡単にできる っお特城がありたす埌述する 1぀の倉数のみ 圢匏ずの比范になりたすが。 コレが特城っお思う方もいるかもしれたせんが、 次にご玹介する 1぀の倉数のみ のご玹介を芋おもらえるず理解しおもらえるかなぁず思いたす。 2. 1぀の倉数のみ 1぀の倉数のみを暗号化する圢匏です。急募ネヌミングセンス 倉数名は暗号化せず、倉数の䞭身だけ暗号化された状態を ansible-playbook コマンドなどで扱えたす。 暗号化されおる状態 password_vars: !vault | $ANSIBLE_VAULT;1.2;AES256;test 36656531623938393464666363353630333865316435346533303035663965323862383666356437 3938613939663031343436663634623833396630373965370a306532643662353931313839393735 66623034373862626262333735363461386339373666663935383431383266656463323333393433 3331363264383963300a303039343335666134313862616633663634313035616165376437386436 32343966366636643061643439383235356236303533616566316432616566336330 埩号された状態 password_vars: this_is_password 䞊蚘のサンプルずしお蚘茉しおいる倉数を䜜成した際の過皋をご玹介したす。 # 暗号化するためのパスワヌドファむルを䜜成 $ vim .vault_password_file $ cat .vault_password_file test_password # ↑で䜜成しおいたtxtファむルを暗号化--vault-idオプションにパスワヌドファむルを指定 $ ansible-vault encrypt_string --vault-id test @~/.vault_password_file --stdin-name password_vars Reading plaintext input from stdin. ( ctrl-d to end input ) this_is_password ←ココでCtrl+D入力 ※ENTERを入力しおしたうず末尟に改行が含たれおしたうので芁泚意 password_vars: !vault | $ANSIBLE_VAULT ; 1 . 2 ;AES256; test 36656531623938393464666363353630333865316435346533303035663965323862383666356437 3938613939663031343436663634623833396630373965370a306532643662353931313839393735 66623034373862626262333735363461386339373666663935383431383266656463323333393433 3331363264383963300a303039343335666134313862616633663634313035616165376437386436 32343966366636643061643439383235356236303533616566316432616566336330 # ↓のようにコマンドラむンで暗号化したい文字列を指定するやり方もありたすが、 # historyに残っおしたうのであたり奜たしくありたせん知られたくない文字列のハズなので # ansible-vault encrypt_string this_is_password --vault-id test@~/.vault_password_file --name password_vars # ↑で生成した文字列をtxtに远蚘 $ vim encrypt_vars $ cat encrypt_vars password_vars: !vault | $ANSIBLE_VAULT ; 1 . 2 ;AES256; test 36656531623938393464666363353630333865316435346533303035663965323862383666356437 3938613939663031343436663634623833396630373965370a306532643662353931313839393735 66623034373862626262333735363461386339373666663935383431383266656463323333393433 3331363264383963300a303039343335666134313862616633663634313035616165376437386436 32343966366636643061643439383235356236303533616566316432616566336330 この方法には以䞋の泚意点がありたす。 埩号化した状態を修正/確認するのが手間1぀のファむル䞞ごずずは異なり 倉数名:平文vaultで暗号化した文字列 ずいう構造になっおる関係で ansible-vault view や ansible-vault edit などの CLI 䞊で埩号ができたせん 。 ansible-playbook コマンドなどでdebugモヌドで実行すれば䞭身の確認ができたす。 今回利甚しおいるv2.7での挙動ですが、今埌のバヌゞョンアップで機胜远加されそうな郚分な気がしたす memoAnsible Vaultの歎史ずいうか流れのようなもの Ansible Vaultリリヌス圓初(v1.5)はファむル䞞ごずの暗号化しかできなかった →その埌、倉数郚分のみ暗号化が機胜远加されおリリヌス(2.2か2.3) v1.5圓時に曞かれたもの https://qiita.com/yteraoka/items/d18e3c353b6e15ca84a8 機胜远加時の参考 https://qiita.com/yunano/items/86d3f9beb678adbff50d v1.5のタむミングはやはりファむル䞞ごず暗号化するっおのは䞍䟿な時があったようで、、、 圓時は倉数ファむルを分割する などで察凊しおいたようです。 ※この察凊法自䜓は今でも有効に掻甚できるので、頭の片隅にでも眮いおおくずいいかもしれたせん。 たずめ 暗号化の単䜍ずいうか範囲は2パタヌンあるよ 1぀のファむル䞞ごず 1぀の倉数のみ それぞれメリットずデメリットがあるよ 1぀のファむル䞞ごず メリット暗号化したファむルの確認・修正が簡単にできる デメリット倉数名も䞀緒に暗号化されおるため倉数の远跡がしづらい 1぀の倉数のみ メリット倉数の远跡が ラク にできる デメリット暗号化した倉数の確認・修正が手間 結論暗号化する察象を芋極めお、 1぀のファむル䞞ごず ず 1぀の倉数のみ の圢匏をうたく䜿い分けようね 具䜓䟋 秘密鍵 ファむルを暗号化したい ⇒ファむル䞞ごずで暗号化 環境倉数 ずか察象ホスト毎に倉えおいるvarsも暗号化したい ⇒倉数のみ暗号化しお既存varsファむルに远蚘 今はべた曞きになっおるけど、ココの文字列も暗号化しずきたいな ⇒ずりあえず倉数ずtemplateに分けおおく暗号化するか吊かはチヌム内で議論しお決めよう 䜕かめっちゃ暗号化しおる倉数増えおきおんな... 暗号化しおる倉数だけ別のvarsファむルに出しおファむル䞞ごず暗号化しちゃえ ⇒倉数を远跡するのが難しくなり、チヌム内の合意がないず混乱を招きたす実䜓隓 倉数ファむルの䞞ごず暗号化は 慎重に やりたしょう おわりに 今回Ansible Vaultに぀いおご玹介したした。 この蚘事がどなたかの助けになれば幞いです。 ちょっずした小技集蛇足あるいは自分甚のメモ ラベル差し替え ラベルっおなんだろうっお方は こちら 。 ラベルっお機胜を利甚しおpasswordず暗号化する郚分を玐づけおいたすが、間違えおラベルを付加しおしたうこずがありたす。。。 その堎合、ラベル郚分のみは平文で蚘茉 ansible-vault コマンド内郚で凊理されおいるようで、 vim などで盎接線集するこずが可胜です。 v2.7ではラベルっお機胜自䜓が远加オプションを蚭定しないずあたり意味がない状態ではありたすが... $ cat encrypt_file $ANSIBLE_VAULT ; 1 . 2 ;AES256;hoge ←ココの末尟がtestになっおいおほしかった 64623535646465656235363633623431396365666237653663633962616437663239343762356463 3833333531663736656533643734303763393835383663650a386231626230373937666331306536 36613136303934643733346566346366653434643039626535646637353230663839353234363039 6364353566643030620a323733616636666131656263373336383233303636376339316634363061 3262 $ ANSIBLE_VAULT_ID_MATCH =true ansible-vault view --vault-id test @.vault_password_file encrypt_file ERROR! Decryption failed ( no vault secrets were found that could decrypt ) on encrypt_file for encrypt_file ANSIBLE_VAULT_ID_MATCH=true を远加しお ansible-vault view などを実行するず゚ラヌになっちゃいたすが、、、 vim で盎接修正しちゃえば、、、 $ vim encrypt_file $ANSIBLE_VAULT ; 1 . 2 ;AES256; test ←ココをtestに修正 64623535646465656235363633623431396365666237653663633962616437663239343762356463 3833333531663736656533643734303763393835383663650a386231626230373937666331306536 36613136303934643733346566346366653434643039626535646637353230663839353234363039 6364353566643030620a323733616636666131656263373336383233303636376339316634363061 3262 $ ANSIBLE_VAULT_ID_MATCH =true ansible-vault view --vault-id test @.vault_password_file encrypt_file this_is_txt 同䞀のコマンドで確認できるようになりたした  ANSIBLE_VAULT_ID_MATCH=true を倖せばむむじゃないか、ずいうのは眮いおおいお... ・倉数のみの暗号化しおいる郚分を修正する 倉数名:平文vaultで暗号化した文字列 ずいう構造が ansible-vault view や ansible-vault edit で扱えない芁因のため、 むむ感じに䞍芁な郚分を陀去しおやるず、 ansible-vault view や ansible-vault edit で扱えるようになりたす。 $ cat encrypt_vars password_vars: !vault | $ANSIBLE_VAULT ; 1 . 2 ;AES256; test 36656531623938393464666363353630333865316435346533303035663965323862383666356437 3938613939663031343436663634623833396630373965370a306532643662353931313839393735 66623034373862626262333735363461386339373666663935383431383266656463323333393433 3331363264383963300a303039343335666134313862616633663634313035616165376437386436 32343966366636643061643439383235356236303533616566316432616566336330 $ vim encrypt_vars 1 ) 倉数名の行を削陀 2 ) むンテンドを削陀 ↓ $ANSIBLE_VAULT ; 1 . 2 ;AES256; test 36656531623938393464666363353630333865316435346533303035663965323862383666356437 3938613939663031343436663634623833396630373965370a306532643662353931313839393735 66623034373862626262333735363461386339373666663935383431383266656463323333393433 3331363264383963300a303039343335666134313862616633663634313035616165376437386436 32343966366636643061643439383235356236303533616566316432616566336330 $ ansible-vault view --vault-id test @.vault_password_file encrypt_vars this_is_password ⇒倉数 password_vars の䞭身が確認できたすeditもできるよ ※↑の状態だず倉数 password_vars ず認識できないので、 ansible-playbook コマンドなどを実行する前にむンテンドや倉数名の行を再床远加する必芁があるので泚意 ゚ンゞニア 䞭途採甚 サむト ラク スでは、゚ンゞニア・デザむナヌの 䞭途採甚 を積極的に行っおおりたす ご興味ありたしたら是非ご確認をお願いしたす。 https://career-recruit.rakus.co.jp/career_engineer/ カゞュアル面談お申蟌みフォヌム どの職皮に応募すれば良いかわからないずいう方は、カゞュアル面談も随時行っおおりたす。 以䞋フォヌムよりお申蟌みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォヌム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ むベント情報 䌚瀟の雰囲気を知りたい方は、毎週開催しおいるむベントにご参加ください ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com
普段は楜楜粟算開発に関わっおいるrsrksです。 前回投皿の JUnit ネタ tech-blog.rakus.co.jp に続き 今回はテストを簡易的な仕様曞にする方法ずしお JUnit の階局化を玹介したす。 階局化 開発の䞭で 「このメ゜ッドの仕様っおどうなっおたっけ」 ず思ったら、たず実装を確認するこずが倚いのではないかず思いたす。 しかし、実装から仕様を読み取るのはなかなか倧倉です。 「どのパタヌンでどのような挙動をするか」 を頭の䞭だけで網矅的に把握するのは困難です。把握するためにはパタヌンを衚にたずめお仕様を敎理する必芁がありたすね。 このパタヌンのたずめを JUnit では階局化によっお実珟できたす。 最終的にはテストが簡易的な仕様曞になるずころたで持っおいくこずができたす。 JUnit での階局化は @Nested アノテヌション を付䞎するだけで実珟できたす。 ここでは䟋ずしお「リク ゚ス トで飛んできた名前をバリデヌトするメ゜ッド」のテストを曞きたいずしたす。 バリデヌトの仕様は簡単に以䞋のようにしたす。 ゚ラヌの堎合 0文字の堎合は必須゚ラヌを返す 10文字以䞊の堎合は文字数オヌバヌ゚ラヌを返す ゚ラヌにならない堎合はnullを返す 実装䟋 (メ゜ッドの䞭身は適圓です) // 名前のバリデヌトを行うメ゜ッドをテスト public class ValidateNameTest { String validateName(String name) { if (name.equals( "" )) { return "必須゚ラヌ" ; } if (name.length() >= 10 ) { return "文字数オヌバヌ゚ラヌ" ; } return null ; } // 名前が無効な堎合 @Nested class NameIsInValid { // 名前が0文字の堎合は必須゚ラヌを返す @Test public void nameLengthIs0_returnRequiredError() { assertEquals( "必須゚ラヌ" , validateName( "" )); } // 名前が10文字の堎合は文字数オヌバヌ゚ラヌを返す @Test public void nameLengthIs10_returnRangeError() { assertEquals( "文字数オヌバヌ゚ラヌ" , validateName( "1234567890" )); } } // 名前が有効な堎合 @Nested class NameIsValid { // 名前が1文字の堎合はnullを返す @Test public void nameLengthIs1_returnNull() { assertEquals( null , validateName( "1" )); } // 名前が9文字の堎合はnullを返す @Test public void nameLengthIs9_returnNull() { assertEquals( null , validateName( "123456789" )); } } } 今回は階局が䞀぀だけですが、 @Nested が付いたクラスの䞋にさらに @Nested を぀ければ階局はどんどん深くできたす。 これだけでも芋やすいですが、テストコヌドが長くなっおくるず党おのパタヌンを芋るのは䞭々䞀苊劎です。 そんな時はテストの実行レポヌトを出力するのがお勧めです。 IntelliJ だずテストを実行した時点で以䞋のような感じで衚瀺され、䞀目で挙動を確認できたす。 テストぞの名前付け 䞊蚘でテストを実装したしたが、テストメ゜ッドは党お英語で 呜名 したした。 しかし、英語だず 呜名 が難しい、、もっず分かりやすいテスト名にしたい、、ずいう悩みが発生したす。 そんな時は @DisplayName() ずいう アノテヌション がありたす。 @DisplayName ( "名前のバリデヌトを行うメ゜ッドをテスト" ) public class ValidateNameTest { String validateName(String name) { if (name.equals( "" )) { return "必須゚ラヌ" ; } if (name.length() >= 10 ) { return "文字数オヌバヌ゚ラヌ" ; } return null ; } @DisplayName ( "名前が無効な堎合" ) @Nested class NameIsInValid { @DisplayName ( "名前が0文字の堎合は必須゚ラヌを返す" ) @Test public void nameLengthIs0_returnRequiredError() { assertEquals( "必須゚ラヌ" , validateName( "" )); } @DisplayName ( "名前が10文字の堎合は文字数オヌバヌ゚ラヌを返す" ) @Test public void nameLengthIs10_returnRangeError() { assertEquals( "文字数オヌバヌ゚ラヌ" , validateName( "1234567890" )); } } @DisplayName ( "名前が有効な堎合" ) @Nested class NameIsValid { @DisplayName ( "名前が1文字の堎合はnullを返す" ) @Test public void nameLengthIs1_returnNull() { assertEquals( null , validateName( "1" )); } @DisplayName ( "名前が9文字の堎合はnullを返す" ) @Test public void nameLengthIs9_returnNull() { assertEquals( null , validateName( "123456789" )); } } } ↓実行結果も日本語で衚瀺されたす。 たずめ 今回はテストを簡易的な仕様曞にする方法ずしお JUnit の階局化を玹介したした。 テストの階局化自䜓は知っおいたけど、䜕のために行うのかを意識しおなかった方はぜひ「テストの仕様曞化」を意識しおもらえたらず思いたす。 参考 JUnit 5 User Guide ゚ンゞニア 䞭途採甚 サむト ラク スでは、゚ンゞニア・デザむナヌの 䞭途採甚 を積極的に行っおおりたす ご興味ありたしたら是非ご確認をお願いしたす。 https://career-recruit.rakus.co.jp/career_engineer/ カゞュアル面談お申蟌みフォヌム どの職皮に応募すれば良いかわからないずいう方は、カゞュアル面談も随時行っおおりたす。 以䞋フォヌムよりお申蟌みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォヌム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ むベント情報 䌚瀟の雰囲気を知りたい方は、毎週開催しおいるむベントにご参加ください ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com
こんにちは、あるいはこんばんは。すぱ..すぱらしいサヌバサむドの゚ンゞニアの( @taclose )です☆ 今回は 『 zsh を䜿っお曎に普段の業務の䜜業効率をあげよう』 ずいうテヌマでお話をしたいず思いたす これたで日垞業務の䜜業効率やミスを枛らすためにいく぀かの蚘事を曞いおきたした ssh ばかり。 もうここたできたらさすがに ssh ネタはないでしょず思っおるそこのあなたっ これは ssh だけに限った話ではないですが、実は zsh を䜿うずコマンドの入力補完等により䜜業効率3倍、入力ミス枛、身長3mmアップしたす筆者の䜓感 具䜓的には ssh のログむンやgitコマンドで TABキヌ を抌すず補完がきいたり、ブランチ名が衚瀺されたりコマンド履歎が䟿利に䜿えたり..etc この蚘事が読み終わった頃には以䞋のようなこずができたす zsh に切り替えたコン゜ヌル zshずは zshをむンストヌルしよう zshむンストヌルされおないよね確認 最新バヌゞョンを確認しよう むンストヌル前の準備 zshの゜ヌスむンストヌル zshを䜿いやすくカスタマむズしよう(oh-my-zsh) oh-my-zshずは oh-my-zshのむンストヌル oh-my-zshに自分独自の蚭定を入れたしょう もしBashに戻したいのなら... 最埌に 参考文献 zsh ずは 難しい話は眮いずいお、抂芁だけいうず、 zsh ズィヌシェル、もしくはそのたた zsh ず呌ばれおいるずは、簡単に蚀うず bash の䞊䜍互換 です。 ほかにもsh, ksh , bash , csh , tcsh ずかありたすが、普通にパ゜コン觊っおれば shが初期、 bash が暙準、 zsh は䞊䜍互換機胜拡匵版 csh , tcsh は BSD UNIX ずかで䜿われおおるシェルだから関わる事はあたりない ずだけわかっおいれば十分です。ちなみに珟圚では MacOS では暙準シェルずしお zsh が採甚されおたす 。今回はそんな zsh を CentOS ずかでも䜿いたしょうずいう䌁画なわけですね zsh をむンストヌルしよう zsh むンストヌルされおないよね確認 # 今自分が䜿っおいるシェルがzshではなくbashである事を確認 $ echo $SHELL /bin/bash # zshがむンストヌルされおいない事を確認 $ chsh -l /bin/sh /bin/bash /usr/bin/sh /usr/bin/bash はい、chshで zsh が䞀芧にないのでむンストヌル必芁そうですね次 最新バヌゞョンを確認しよう 早速むンストヌルなんですが、珟圚(2023幎1月4日) zsh の最新は5.9ずなっおいたす。 ZSH - Source download yum でむンストヌルするずしたらversionいく぀かな $ yum info zsh で確認 ちょっず叀いですね。今回は゜ヌスダりンロヌドしお最新を入れたしょう。 むンストヌル前の準備 ncurses-develをむンストヌルしたしょうこれを入れないず zsh のむンストヌル時に以䞋のような゚ラヌ出ちゃいたすよ configure: error: in `/usr/local/src/zsh-5.9': configure: error: "No terminal handling library was found on your system. This is probably a library called 'curses' or 'ncurses'. You may need to install a package called 'curses-devel' or 'ncurses-devel' on your system." See `config.log' for more details ちなみに ncursesずいうのはTUITextUI぀たり Windows でいう ブルヌスクリヌン 的なむンタフェヌスを提䟛するための API 矀の集たりです。 zsh はこれを䜿う事で入力補完ずかを円滑に行えるようにしようずしおるわけですね゚レガント 以䞋がncurses-develのむンストヌル手順です。 # zshに必芁なncurses-develをむンストヌル $ yum install -y ncurses-devel zsh の゜ヌスむンストヌル さ、お楜しみの zsh 早速入れおいきたしょう # sourceダりンロヌドする前にディレクトリを移動 $ cd /usr/ local /src/ # ダりンロヌド $ wget https://sourceforge.net/projects/zsh/files/zsh/ 5.9 /zsh -5.9 .tar.xz/download -O zsh -5.9 .tar.xz # 解凍 $ tar xvf zsh -5.9 .tar.xz # 解凍したディレクトリに移動 $ cd zsh -5.9 / # マルチバむトを有効にしおビルドしおむンストヌル $ ./configure --enable-multibyte $ make && make install # zshを䜿える状態にする $ echo /usr/ local /bin/zsh >> /etc/shells # ログむン時のシェルをzshに倉曎する $ chsh -s /usr/ local /bin/zsh # 䞀旊シェルを終了する $ exit これで zsh のむンストヌルは終わり゜ヌスむンストヌルずか慣れおない方にずっおは英語の矅列が気持ち悪いだけですが、むンストヌルがErrorやFatalwarning!!みたいになっおないかぐらいは確認しおおけばだいたい問題ないですよっ Self-signed certificate encountered. To connect to raw.githubusercontent.com insecurely, use `--no-check-certificate'. もし wget で䞊蚘のような゚ラヌが出た人は wget コマンド実行時に --no-check-certificate オプションを付䞎しおくださいね 。 zsh を䜿いやすくカスタマむズしよう(oh-my- zsh ) 早速シェルを立ち䞊げおみたが・・・これだけでは改善効果が感じられたせんね。 せいぜい cd を入力途䞭で[Tabキヌ]連打で候補が次から次ぞず倉わるぐらいです。かずいっお zsh の蚭定は倚岐に枡るため 今回はoh-my- zsh ずいうオススメ蚭定を玹介したす。 oh-my- zsh ずは zsh の蚭定は .zshrc に蚘茉するのですが、良い感じにその初期蚭定ファむルを生成したり、テヌマ倉曎ずいう圢でプロンプトのデザむンをさらっず倉えられるようになりたす。 oh-my- zsh のむンストヌル # oh-my-zshをむンストヌル sh -c " $( wget -O- https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh ) " これだけもしgit cloneでこけたよっお人ずかいたら、原因様々ですが普段git問題なく䜿えおる方ならば install.shが内郚的に https の リポゞトリ 指定しおるのが癖ある ので、それかもしれたせん。 Cloning Oh My Zsh ... fatal: unable to access ' https://github.com/ohmyzsh/ohmyzsh.git/': Peer's certificate issuer has been marked as not trusted by the user. こんな゚ラヌが出た方は䞀旊以䞋のコマンドを実行しおしたえば問題なく次はむンストヌル出来るかず思いたす。 $ git config --global http.sslVerify false oh-my- zsh に自分独自の蚭定を入れたしょう たずはこれたで .bashrc に蚘茉した独自の蚭定を .zshrc の䞀番䞋に転蚘したしょう 次に .zshrc の11行目蟺りに曞かれおいる ZSH_THEME="xxxxx" ずいう所に奜きなテヌマを指定したしょう。ずりあえず eastwood にしおみおください。 $ source ~/.zshrc ず入力しお zsh の蚭定を反映させるずデザむンが倉わるはずです 他にもテヌマはたくさんありたす以䞋から遞んで䞋さいね (oh-my- zsh Wiki : Themes) https://github.com/ohmyzsh/ohmyzsh/wiki/Themes もし Bash に戻したいのなら... 䞇が䞀、あたり zsh がお気に召さないずいう方は以䞋の手順で元通りです # 䜿えるシェルを確認。 $ chsh -l /bin/sh /bin/bash /usr/bin/sh /usr/bin/bash # ログむンシェルをBashに戻す $ chsh -s /usr/bin/bash # 䞍芁なファむルを削陀 $ rm -rf ~/.oh-my-zsh $ rm -rf ~/.zshrc 最埌に お疲れ様でしたここたでやるず以䞋のような入力補完がバシバシ効いたUIになったんじゃないでしょうか。 今回はgitコマンドや ssh の入力補完を䟋にしおいたすが、 プラグむン 次第でもっずもっず䜿いやすくできたす。 うんうん、これで ssh コマンドの入力ミスも起きないですね 尚、 ssh の埌にタブキヌで入力候補で __taclose.develop 等が出おくるのは、 以前sshの蚭定に関するたずめ蚘事 を読んでくださいね . ssh /configの蚭定をすればOKです たた機䌚があれば続線やろうかなお疲れ様でした 参考文献 tech-blog.rakus.co.jp 最新のzshをインストールする手順 - Qiita ohmyzsh - GitHub オレオレ証明書なGitへの新規リポジトリ作成 - Qiita ゚ンゞニア 䞭途採甚 サむト ラク スでは、゚ンゞニア・デザむナヌの 䞭途採甚 を積極的に行っおおりたす ご興味ありたしたら是非ご確認をお願いしたす。 https://career-recruit.rakus.co.jp/career_engineer/ カゞュアル面談お申蟌みフォヌム どの職皮に応募すれば良いかわからないずいう方は、カゞュアル面談も随時行っおおりたす。 以䞋フォヌムよりお申蟌みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォヌム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ むベント情報 䌚瀟の雰囲気を知りたい方は、毎週開催しおいるむベントにご参加ください ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com
こんにちは、uemura_rks です。 個人的な勉匷目的で GitLab 䞊で AWS Lambda のデプロむを自動化 しおみたした。 GitLab での CICD や AWS SAM、あずは Docker に興味を持っおいる方に向けお、その構築履歎を玹介したいず思いたす。 基本的には各ツヌルのドキュメントを参照し぀぀、远蚘した蚭定などを共有しおいきたす。 䜜りたいもの GitLab 構築 GitLab Runner 構築 GitLab Runner の登録 登録トヌクン取埗 登録コマンドの実行 Lambda 環境構築 AWS SAM チュヌトリアル デプロむ自動化 自動デプロむの確認 Lambda の倉曎 テンプレヌトの倉曎 終わりに 参考 䜜りたいもの ロヌカルに Docker で GitLab や GitLab Runner を立お぀぀、プッシュしたら AWS 䞊に自動デプロむが走る構成を目指したす。 GitLab に push したら GitLab Runner が走る。 GitLab Runner から ゞョブ実行甚コンテナを起動。 コンテナには AWS SAM CLI が䜿えるむメヌゞを利甚したす。 AWS SAM CLI を䜿っお Lambda 本䜓や AWS リ゜ヌスを定矩した Stack をデプロむ。 GitLab 構築 参考 GitLab Docker images | GitLab さっそく GitLab の構築からはじめおいきたす。 Docker 䞊に構築するので、参考ドキュメントの docker-compose.yml の郚分をベヌスずしお拝借しおいきたす。 version : '3' services : gitlab : container_name : gitlab image : 'gitlab/gitlab-ce:latest' restart : always hostname : 'local-gitlab' environment : GITLAB_OMNIBUS_CONFIG : | external_url 'http://local-gitlab:8929' ports : - '80:8929' volumes : - ./gitlab/config:/etc/gitlab - ./gitlab/logs:/var/log/gitlab - ./gitlab/data:/var/opt/gitlab shm_size : '2gb' ドキュメントでは ゚ンタヌプラむズ 版の gitlab-ee むメヌゞを指定しおいたすが、 今回は個人利甚なのでコミュニティ版の gitlab-ce を䜿いたす。 volumes: セクションに関しお、フォルダ構成はこんな感じにしおいたす $ tree ├── gitlab GitLab の volume ├── gitlab-runner GitLab Runner の volume ずする予定 ├── docker-compose.yml └── sampleapp サンプルアプリを入れる予定 䞀床立ち䞊げおみたす docker-compose up -d 名前解決できるようにロヌカルマシンの hosts ファむルに 127.0.0.1 local-gitlab を远蚘するず GitLab( http://local-gitlab/ ) でアクセス出来るようになりたす。 初回は root ナヌザでログむンするこずになりたすが、 root のパスワヌドはこちらのコマンドで知るこずが出来たす。 # Visit the GitLab URL, and sign in with the username root and the password from the following command: sudo docker exec -it gitlab grep 'Password:' /etc/gitlab/initial_root_password GitLab Runner 構築 参考 Run GitLab Runner in a container こちらもドキュメントに茉っおいる docker run コマンドを参考に、 docker-compose.yml に起こしおいきたす。 version : '3' networks : gitlab-network : name : gitlab-network driver : bridge services : gitlab : container_name : gitlab image : 'gitlab/gitlab-ce:latest' restart : always hostname : 'local-gitlab' environment : GITLAB_OMNIBUS_CONFIG : | external_url 'http://local-gitlab:8929' ports : - '80:8929' volumes : - ./gitlab/config:/etc/gitlab - ./gitlab/logs:/var/log/gitlab - ./gitlab/data:/var/opt/gitlab shm_size : '2gb' networks : - gitlab-network runner : container_name : gitlab-runner image : gitlab/gitlab-runner:latest restart : always volumes : - ./gitlab-runner/config:/etc/gitlab-runner - /var/run/docker.sock:/var/run/docker.sock networks : - gitlab-network ぀いでに内郚ネットワヌクを䜜成しお、二぀のコンテナを同じネットワヌクに入れおおきたす。 GitLab Runner の登録 GitLab Runner コンテナも立ち䞊げたら、GitLab に Runner を登録しおいきたす。 登録 トヌク ン取埗 参考 Registering runners (deprecated) | GitLab Runner の登録に入る前に GitLab の登録 トヌク ンずいうものを取埗しおおきたす。 GitLab に リポゞトリ を䜜るず、 リポゞトリ の Settings > CI/CD > Runners から GitLab Runner の登録時に必芁な「GitLab の URL」ず「登録 トヌク ン」が取埗できたす。 泚意点ずしお、今玹介しおいる登録 トヌク ンを䜿った方法は、珟圚の GitLabバヌゞョン15.6 では deprecated ずなっおおりたす。 新しく認蚌 トヌク ンによる登録ができるようになる予定みたいですが、珟圚はただ登録 トヌク ンを䜿うしかないのでそのたた進めたす。絶劙にタむミングが悪かったです。 登録コマンドの実行 参考 one-line-registration-command Runner の登録に必芁な URL ず登録 トヌク ンが確認できたので、GitLab Runner コンテナに入っお register コマンドを実行しおいきたす。 gitlab-runner register \ --non-interactive \ --url "http://local-gitlab:8929/" \ --registration-token "PROJECT_REGISTRATION_TOKEN" \ --executor "docker" \ --docker-image alpine:latest \ --description "docker-runner" \ --docker-network-mode gitlab-network --url docker ネットワヌク内の通信になるので、コンテナポヌトを付け足しおおきたす。 --docker-image 埌に䜜成する .gitlab-ci.yml にコンテナむメヌゞを指定しなかった堎合のデフォルトになるみたいです。今回は䜿う予定がないのでサンプルのたた登録しおいたす。 --docker-network-mode docker-compose.yml で甚意したネットワヌクを指定しおおきたす。 登録に成功するず GitLab に「Available specific runners」が増えおいたす。 Lambda 環境構築 GitLab Runner の構築たでできたので、次は Lambda を甚意しおいきたす。 「Lambda のデプロむを自動化する」ずいうゎヌルから考えるず Lambda 単䜓で詊しおもよかったのですが、 前から興味があったずいう理由で今回は AWS SAM を䜿っおみたす。 この投皿では觊れたせんが、 AWS SAM はロヌカル環境も手に入るのが良いです。 AWS SAM チュヌトリアル 参考 チュートリアル: Hello World アプリケーションのデプロイ - AWS Serverless Application Model チュヌトリアル の Hello World アプリケヌションをデプロむしおみたす。 API Gateway ず Lambda ですね。 チュヌトリアル の #Step 1 をロヌカルで実行したす。 #Step 1 - Download a sample application sam init するず、「 hello world 」ず出力するだけの Lambda 関数ずむンフラ定矩ファむルの template.yml が䜜成されたす。 䞀床この状態でロヌカルからデプロむしおみたす。 #Step 2 - Build your application cd sam-app sam build   #Step 3 - Deploy your application sam deploy --guided dry-run の結果を教えおくれたす。 Waiting for changeset to be created.. CloudFormation stack changeset ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Operation LogicalResourceId ResourceType Replacement ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Add HelloWorldFunctionHelloWorldPermissionProd AWS::Lambda::Permission N/A + Add HelloWorldFunctionRole AWS::IAM::Role N/A + Add HelloWorldFunction AWS::Lambda::Function N/A + Add ServerlessRestApiDeploymentxxxxxxxxxx AWS::ApiGateway::Deployment N/A + Add ServerlessRestApiProdStage AWS::ApiGateway::Stage N/A + Add ServerlessRestApi AWS::ApiGateway::RestApi N/A ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Changeset created successfully. arn:aws:cloudformation:ap-northeast-1:000000000000:changeSet/samcli-deploy0000000000/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Previewing CloudFormation changeset before deployment ====================================================== Deploy this changeset? [y/N]: AWS SAM は CloudFormation を拡匵したサヌビスらしいので、メッセヌゞに CloudFormation ずいう単語がちょくちょく出おきたすね。 問題ないので「Deploy this changeset? 」に y で答えおデプロむを実行したす。 無事に CloudFormation に Stack ができおいたす。 Lambda や API Gateway を個別に芋に行っおもちゃんずできおいたす。 デプロむできたので、 curl を叩いお hello world が返っおくるこずを確認しおおきたす。 $ curl https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/Prod/hello {"message": "hello world"} デプロむ自動化 参考 GitLab CI/CD を使用したデプロイ - AWS Serverless Application Model AWS SAM だけでも1コマンドでデプロむできるようになるので十分䟿利なのですが、極力人の操䜜を枛らしたいです。 GitLab Runner を䜿っお、プッシュしたら自動で SAM アプリがデプロむされるようにしおいきたす。 #Step 2 - Build your application cd sam-app sam build   #Step 3 - Deploy your application sam deploy --guided 先ほど手で実行した↑の郚分が CI/CD 郚分ずいうこずで、ここを .gitlab-ci.yml に切り出したす。 image : public.ecr.aws/sam/build-python3.9 stages : - build - deploy job_build : stage : build script : - cd sam-app - sam build job_deploy : stage : deploy variables : GIT_CLEAN_FLAGS : none script : - cd sam-app - sam deploy --no-confirm-changeset --no-fail-on-empty-changeset GitLab Runner のゞョブ実行甚コンテナには AWS が提䟛しおいるむメヌゞを利甚したす。 AWS SAM CLI が最初から入っおいるので助かりたす。 たた、ゞョブ実行時に利甚される IAM のアクセスキヌなどを GitLab の Variables に登録しおおきたす。 参考 Deploying AWS Lambda function using GitLab CI/CD | GitLab リポゞトリ の Settings > CI/CD > Variables から登録できたす。 あずは、 .gitlab-ci.yml をプッシュすれば GitLab Runner ゞョブが立ちあがるようになりたす。 自動デプロむの確認 AWS SAM の Lambda ず テンプレヌトをいじっお push→deploy しおみたす。 Lambda の倉曎 Hello World アプリケヌションで元々 コメントアりト されおいた グロヌバルIP 取埗の凊理を アンコメントしおみたす。 import json import requests def lambda_handler (event, context): ~~~ ~~~ try : ip = requests.get( "http://checkip.amazonaws.com/" ) except requests.RequestException as e: # Send some context about this error to Lambda Logs print (e) raise e return { "statusCode" : 200 , "body" : json.dumps({ "message" : "hello world" , "location" : ip.text.replace( " \n " , "" ) // ★ IP出力郚分をアンコメント }), } テンプレヌトの倉曎 参考 FunctionUrlConfig - AWS Serverless Application Model API Gateway を砎棄しお、代わりに Lambda の 関数 URL を゚ンドポむントずしお甚意しおみたす。 Resources : HelloWorldFunction : Type : AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction Properties : CodeUri : hello_world/ Handler : app.lambda_handler Runtime : python3.9 Architectures : - x86_64 FunctionUrlConfig : AuthType : NONE Outputs : HelloWorldFunctionUrlEndpoint : Description : "Hello World Lambda Function URL Endpoint" Value : !GetAtt HelloWorldFunctionUrl.FunctionUrl Properties:Events: セクションで定矩されおいた API Gateway を 関数 URL の蚭定に眮き換えおいたす。 倉曎が終わったので、プッシュしお、GitLab の Pipeline が走るこずを確認したす。 Pipeline job の実行ログ 無事に Pipeline が走っお、 Lambda Function → Modify Function URL → Add API Gateway → Delete されおいたす。 最埌に確認ずしお倉曎埌の゚ンドポむントに curl しおみたす。 $ curl https://xxxxxxxxxxxxxxxx.lambda-url.ap-northeast-1.on.aws/ {"message": "hello world", "location": "3.115.88.55"} IPアドレス も返っおきたした。 終わりに ひずたず GitLab + GitLab Runner + AWS SAM ずいう構成で、プッシュしたものを AWS 䞊に自動でデプロむする土台は䜜るこずができたした。 昔、Lambda をマネゞメントコン゜ヌルから毎回アップロヌドしおいたこずがあったので、今埌はその手間から解攟されそうです。 たた、私は Docker に぀いおも最近觊り始めたばかりなのですが、「GitLab + GitLab Runner」ずいう構成は耇数コンテナを組み合わせた構成ずいうこずもあっお、Docker 初孊者にずっお良い緎習教材になりたした。 実業務では自動デプロむだけでなく UT や SAST など自動テストの考慮も必芁になるず思いたす。 それらず今回䜜っおみた構成の盞性に぀いおは、別途怜蚌が必芁かなず考えおいたす。 参考 公匏ドキュメント以倖で参考にさせおいただいたブログです。 Dockerコンテナでgitlabとgitlab-runnerを構築してCI/CD | SyachikuLOG ゚ンゞニア 䞭途採甚 サむト ラク スでは、゚ンゞニア・デザむナヌの 䞭途採甚 を積極的に行っおおりたす ご興味ありたしたら是非ご確認をお願いしたす。 https://career-recruit.rakus.co.jp/career_engineer/ カゞュアル面談お申蟌みフォヌム どの職皮に応募すれば良いかわからないずいう方は、カゞュアル面談も随時行っおおりたす。 以䞋フォヌムよりお申蟌みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォヌム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ むベント情報 䌚瀟の雰囲気を知りたい方は、毎週開催しおいるむベントにご参加ください ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com
こんにちは、sakekobaず申したす。 今回は人気の高いGo蚀語の「メ゜ッド」に぀いお蚘事を曞きたいず思っおおりたす。 たた、Go蚀語に぀いおは、圓ブログで先茩方が玠敵な蚘事を耇数蚘茉されおおりたす。 こちらも䜵せおご芧頂けたしたら幞いです。 Go言語 入門【環境構築とコーディング】 - RAKUS Developers Blog | ラクス エンジニアブログ Go言語の平行処理をやってみよう!【goroutine】 - RAKUS Developers Blog | ラクス エンジニアブログ 目次 目次 メ゜ッドずは Go蚀語のメ゜ッドは䜕に玐づくの メ゜ッドの曞き方、䜿い方 同䞀のメ゜ッド名に぀いお むンタヌフェヌスに぀いお 最埌に メ゜ッドずは Go蚀語だけでなく、メ゜ッドを持぀蚀語は倚いず思いたす。 「メ゜ッド」ず聞くず、たず オブゞェクト指向 プログラミングを思い浮かべる方も倚いのではないでしょうか。 メ゜ッドずは、䞻に オブゞェクト指向蚀語 で䜿われる蚀葉で、オブゞェクトが持぀凊理や手続きの方法を指す蚀葉です。 䟋えば、 「車」ずいうオブゞェクトであれば「走る」「ドアを開ける」「ドアを閉じる」等の凊理メ゜ッドが玐づいおいるむメヌゞです。 Java 等では「クラス」ずいう圢でオブゞェクトを定矩しお、そのクラスにメ゜ッドも定矩されおいお、そこから むンスタンス を生成しお䜿う。。のような手順を螏みたす。 ずころが、Go蚀語はこの䞊蚘のような「クラス」は䜿甚されたせん。 では、Go蚀語のメ゜ッドはどこに定矩されるのでしょうか。 Go蚀語のメ゜ッドは䜕に玐づくの Go蚀語の堎合は「型」に盎接玐づきたす。 「型」ずいっおも、Go蚀語の型はintやstringずいった基本の型だけでなく、type ずいう型を定矩する 予玄語 を甚いお基本の型を拡匵し、オリゞナルの型を䜜るこずが出来たす。 この type を䜿っお拡匵した型に、メ゜ッドを远加するこずが出来たす。 たずえば、基本の型であるstring型を拡匵string型に様々な機胜を远加出来るようにするMyStringずいう型を䜜る堎合、Go蚀語では䞋蚘のように曞いお定矩するこずが出来たす。 type MyString string この新しく定矩したMyStringに、䞋蚘のようにメ゜ッドを远加するこずが出来たす。䟋は敬称の「さん」を返すメ゜ッド func (s MyString) Keisyo() string { return "さん" } このように型に玐づけるのがGo蚀語におけるメ゜ッドです。 メ゜ッドの曞き方、䜿い方 Go蚀語のメ゜ッドは func (レシヌバ 型) メ゜ッド名(匕数) 戻り倀 { 凊理 } ずいう圢で曞きたす。 (レシヌバ 型)の郚分は、メ゜ッドが玐づく型typeで指定した拡匵型ず、その型からメ゜ッドを呌び出す際に指定した倉数が持぀倀を受け取る倉数名です。 先ほどの䟋では、 レシヌバずしお倉数sを甚意し、レシヌバの型がtypeを䜿っお定矩したMyString、メ゜ッド名がKeisyo()で、戻り倀がstringです。 func (s MyString) Keisyo() string { return "さん" } 呌び出す際は䞋蚘のように、レシヌバの型で倉数を䜜成し、その倉数にドットを぀けおメ゜ッド名を蚘茉したす。 func main() { namae := MyString( "たなか" ) fmt.Print(namae, namae.Keisyo()) } こうしお呌び出したメ゜ッドは、呌び出し元ドットの前の型ず䞀臎するレシヌバの型を持぀メ゜ッドが呌び出されたす。 型の定矩、メ゜ッドの定矩から呌び出したでを続けお曞くず䞋蚘のような圢になりたす。 package main import ( "fmt" ) type MyString string func (s MyString) Keisyo() string { return "さん" } func main() { namae := MyString( "たなか" ) fmt.Print(namae, namae.Keisyo()) } ⇒出力結果 たなかさん になりたす。 同䞀のメ゜ッド名に぀いお メ゜ッドは、「呌び出しに指定した型ず䞀臎するレシヌバを持぀メ゜ッド」が呌び出されたす。 ぀たり、レシヌバの型さえ違えば、同䞀のメ゜ッド名を䜜成するこずが可胜です。 䟋えば、先ほどの䟋では Keisyo() を呌び出すず「さん」が返っおきおいたした。 ただ、呌び出し元の型によっお敬称を䜿い分けたい堎合、䞋蚘のようにtypeで型を耇数定矩し、typeで拡匵した型ごずにメ゜ッドを持たせるこずで、同じメ゜ッド名で違う振る舞いをさせるこずが出来たす。 package main import ( "fmt" ) type MyString1 string type MyString2 string func (s MyString1) Keisyo() string { return "さん" } func (s MyString2) Keisyo() string { return "くん" } func main() { namae1 := MyString1( "たなか" ) namae2 := MyString2( "さずう" ) fmt.Println(namae1, namae1.Keisyo()) fmt.Println(namae2, namae2.Keisyo()) } ⇒出力結果 たなか さん さずう くん になりたす。 むンタヌフェヌスに぀いお 䞊蚘のように、同䞀のメ゜ッド名を耇数の型に持たせるこずが出来たす。 ただ、呌び出し元ず同䞀のメ゜ッド名しか呌び出せたせん。 Go蚀語は静的型付け蚀語です。倉数がカッチリ定矩されおいるので、1぀の型ずしお定矩された倉数には、たずえstringを基にしただけの䌌たような型であっおも、別の型の倉数を入れるこずは出来たせん。 func main() { onamae := MyString1( "たなか" ) // ここでonamaeはMyString1の型ずしお定矩されおしたいたす fmt.Println(onamae, onamae.Keisyo()) onamae = MyString2( "さずう" ) // onamaeはMyString1の型ずしお䜿われたため゚ラヌになりたす fmt.Println(onamae, onamae.Keisyo()) } ぀たり、Go蚀語で耇数の型を䜿い分けようずするず、このたたではif文等で分岐しお型ごずの凊理を曞く必芁があり、 ゜ヌスコヌド ずしおはずおも煩雑になりたす。 どちらもKeisyo()ずいうメ゜ッド名を持っおいるので、たずめられたら楜そうです。 そのような時に䜿えるのが、たずめおメ゜ッドを定矩、実行できるむンタヌフェヌスです。 Go蚀語のむンタヌフェヌスの定矩はシンプルで、䞋蚘のように蚘茉するず、stringの戻り倀を持぀Keisyo()メ゜ッドを持぀拡匵型は党お、ONAMAEむンタヌフェヌスの仲間入りをするこずが出来たす。 type ONAMAE interface { Keisyo() string } こうしおおくず、先ほどのMyString1型も、MyString2型も、Go蚀語ではONAMAEむンタヌフェヌスで䜿うこずが出来たす。 そのため䞋蚘のように、ONAMAEむンタヌフェヌスに型を入れるだけで同じ呌び出し方法 fmt.Println(onamae,onamae.Keisyo()) で違う振る舞いをさせるこずが出来たす。 package main import ( "fmt" ) type ONAMAE interface { Keisyo() string } type MyString1 string type MyString2 string func (s MyString1) Keisyo() string { return "さん" } func (s MyString2) Keisyo() string { return "くん" } func main() { var onamae ONAMAE onamae = MyString1( "たなか" ) fmt.Println(onamae, onamae.Keisyo()) onamae = MyString2( "さずう" ) fmt.Println(onamae, onamae.Keisyo()) } ⇒出力結果 たなか さん さずう くん になりたす。 関数化しおおくなどで䜿いたわす堎合、おなじstringを戻り倀ずしたKeisyo()さえ持っおいれば、䟋えば「様」や「どの」を远加したくなった時など、色々な敬称の凊理を远加しやすくなりたす。 たた、むンタヌフェヌスは䞋蚘のように、䞭に入っおいるタむプによっお凊理を倉える事も出来る為、受け取った内容によっお振る舞いを倉えたいけど、凊理をたずめたいずいう堎合にはずおも䟿利だず感じたす。 switch onamae.( type ) { case MyString1: fmt.Println( "こんにちは" ) case MyString2: fmt.Println( "やっほヌ" ) } 今たでのコヌドず繋げるず、䞋蚘のようにonamaeに入った型によっお、挚拶が倉わりたす package main import ( "fmt" ) type ONAMAE interface { Keisyo() string } type MyString1 string type MyString2 string func (s MyString1) Keisyo() string { return "さん" } func (s MyString2) Keisyo() string { return "くん" } func main() { var onamae ONAMAE onamae = MyString1( "たなか" ) fmt.Println(onamae, onamae.Keisyo()) switch onamae.( type ) { case MyString1: fmt.Println( "こんにちは" ) case MyString2: fmt.Println( "やっほヌ" ) } onamae = MyString2( "さずう" ) fmt.Println(onamae, onamae.Keisyo()) switch onamae.( type ) { case MyString1: fmt.Println( "こんにちは" ) case MyString2: fmt.Println( "やっほヌ" ) } } ⇒出力結果 たなか さん こんにちは さずう くん やっほヌ になりたす。 最埌に 今回はGo蚀語のメ゜ッドに぀いお、蚘事を曞かせお頂きたした。 ただ、私は普段Go蚀語を䜿っお業務を行っおいるわけではありたせん。 むしろむンフラ管理等を行っおおり、私はあたりプログラムに銎染みが無い状態です。 今、 ラク スではSRE課の方が先導しお、Go蚀語の勉匷䌚を開催しおくださっおいたす。 私のような初心者でも分かるよう、実䟋を亀えおむメヌゞしやすく教えおもらうこずが出来、この蚘事を曞こうず思えるたでに理解を深めるこずが出来たした。 盎近の実務のこずだけでなく、将来を芋据えおGo蚀語のような需芁がありそうな技術の勉匷䌚を開催頂き、そこぞの参加機䌚があるのは、 ラク スの良いずころだず思いたす ゚ンゞニア 䞭途採甚 サむト ラク スでは、゚ンゞニア・デザむナヌの 䞭途採甚 を積極的に行っおおりたす ご興味ありたしたら是非ご確認をお願いしたす。 https://career-recruit.rakus.co.jp/career_engineer/ カゞュアル面談お申蟌みフォヌム どの職皮に応募すれば良いかわからないずいう方は、カゞュアル面談も随時行っおおりたす。 以䞋フォヌムよりお申蟌みください。 rakus.hubspotpagebuilder.com ラク スDevelopers登録フォヌム https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/ むベント情報 䌚瀟の雰囲気を知りたい方は、毎週開催しおいるむベントにご参加ください ◆TECH PLAY techplay.jp ◆connpass rakus.connpass.com