【Nuxt.js/Vue.js】スタートアップ導入事例 LTイベントに参加しました!

f:id:marron-web-engineer:20190202124120p:plain

こんにちは! ITプロパートナーズ(https://itpropartners.jp/)インターンの栗岡です!

普段は、Laravelで自社サービスの開発をしたり、新卒採用関係の業務をやっています。

今回は、1月30日に弊社渋谷オフィスで行われたNuxt.js/Vue.jsで開発しているスタートアップ企業によるLTイベントのレポートを行います!

弊社のエンジニアの米川も登壇しました!

re-build.connpass.com

続きを読む

Vue.jsの開発コードネームが〇〇オタ仕様だという話と、次のコードネームを予想してみる

  • Vue 2.6 が2/4に正式リリース
  • そもそも開発コードネームとは
  • ここでVue.jsの過去のコードネームを見てみましょう
  • となれば予想したくなりますよね
  • 次バージョン(2.7.0)は「N」始まりです。
  • おわりに

 

 

intee 担当エンジニアの五藤です。

弊社では、フロントエンドの処理ではVue.jsを採用することが多いです。

 

そんなVue.jsですが、最近新バージョンがリリースされました。

 

Vue 2.6 が2/4に正式リリース

 

medium.com

 

今回注目すべきはここです。

 

— today we are excited to announce the release of Vue 2.6 “Macross”!

 

開発コードネームが Macross ??

 

しかもリリース記事には何やらそれっぽい戦闘機の画像が。ちゃんと可変ギミックもありそう

 

そもそも開発コードネームとは

ソフトウェアやライブラリの開発で、いわゆる正式名称やバージョン番号とは別に、愛称のような物を付けるケースがあります。

有名どころでは、Android OSの「Lolipop」「KitKat」のようなお菓子縛りや、MacOS では「Mavericks」「Sierra」など、カリフォルニアの地名が付けられています。

 開発コードをつける背景としては

  • 正式名称が決まるまでの仮の通称
  • 開発時、バージョン数字で呼ぶよりも識別しやすい(OSSの場合は、たいてい複数のバージョンを平行して開発するため、var2.0ではこの機能があってvar2.1ではこうする〜みたいな話が入り乱れます)
  • ユーザー側に愛着を持ってもらう

などなどです。

ここでVue.jsの過去のコードネームを見てみましょう

version 開発コードネーム 日本語名称 アニメ初出年 制作会社
v2.6 Macross 超時空要塞マクロス 1982年 タツノコプロ
v2.5 Level E レベルE 2011年 Studioピエロ✕david production
v2.4 Kill la Kill キルラキル 2013年 TRIGGER
v2.3 JoJo's Bizarre Adventure ジョジョの奇妙な冒険 1993年 A.P.P.P
v2.2 Initial D 頭文字D 1998年 スタジオコメットぎゃろっぷ
v2.1 Hunter X Hunter HUNTER✕HUNTER 1999年 スタジオディーン日本アニメーション
v2.0 Ghost in the Shell GHOST IN THE SHELL / 攻殻機動隊 1995年 Production I.G
v1.0 Evangelion 新世紀エヴァンゲリオン 1995年 タツノコプロGAINAX
v0.12.0 Dragon Ball ドラゴンボール 1986年 東映動画
v0.11.0 Cowboy Bebop カウボーイビバップ 1998年 サンライズ
v0.12.0 Blade Runner - 1982年 -
v0.12.0 Animatrix アニマトリックス 2003年 スクウェアUSA、STUDIO 4℃マッドハウス

 ・・・予想以上にアニオタだぞこれ!?   

海外アニメファンの評価が高い「攻殻機動隊」「カウボーイビバップ」「ドラゴンボール」辺りを押さえつつ、2010年台の「キルラキル(2013-2014)」「レベルE(2011)」あたりを混ぜてみたりと、結構なこだわりようです。

そして命名にはルールがあり、Animatrix から Macross まで、綺麗に先頭の頭文字がアルファベット順に並んでいます。 (頭文字Dのイニシャルが「D」ではなくて「I」扱いなのは若干納得がいかない)

ちなみに最初期は
Animatrix(超有名SF映画マトリックス」のアニメスピンオフ作品)
Blade Runner(カルト的な人気を誇る古典SF映画)」

と、どちらかといえばSF路線の名前をつけていたけど、少しずつ吹っ切れてきた模様。

 

また、Vue.jsの作者である Evan Youの個人サイトのプロフィールには

evanyou.me

 

Outside of programming and helping my wife take care of our two kids, I enjoy video games, karaoke, sushi and collecting watches.

プログラミングと育児以外では 、ビデオゲームやカラオケ、寿司、時計の収集が趣味です。

とあります。ものすごくアニメが好き!というのを全面に押し出しているわけではないですが、コードネームの並びを見る限りは、結構なアニメ好きなのが見て取れます。

(なお、後述の予想サイトには、Kazuponさんを始めとしたContributorも次Verの予想を書き込んでいるため、コードネームはEvan氏が一人で決めている可能性が高いです。)

 

となれば予想したくなりますよね

アルファベット順、というルールがある以上、予想したくなるのが人の常、ということで、次バージョンのコードネームの予想を議論するサイトもすでに出来ていたりします。

 

github.com

 

最新の2.6に対するissueでは「Macross」と「Monster」が2大予想になっていたので、見事的中していた模様。

 

次バージョン(2.7.0)は「N」始まりです。

折角なので本ブログでも次バージョンを予想してみます。

大本命:NARUTO

大本命は、忍者をフューチャーした世界観と、圧倒的なアクション作画で海外から圧倒的な支持を得ているこの作品。海外においては、アニメ好き=NARUTO好き、と言っても過言ではありません。
過去のコードネームで「DRAGON BALL」「攻殻機動隊」などの超有名作品をしっかりと押さえていることを考えると非常に可能性は高いです。
という雰囲気すらします。むしろ、この先Vue.jsのシェアが伸びてきた場合、Vue.jsのコードネームに採用される=超有名アニメとして認められる 、というコンセンサスが社会的に形成されることも十分考えられるので、むしろ、
「この流れでNARUTOを外していいのか?」
という雰囲気すら感じられます。

微妙に何を言っているのかわかりませんが、2.7.0はかなりの可能性で「NARUTO」が採用されると言って間違いがないと思います。

次点:機動戦艦ナデシコ(Mobile Buttleship Nadeshiko)

エヴァンゲリオンで一般層を巻き込んだ空前のアニメブームが起きていた90年代後半時代に、重厚なSF設定と軽妙なシナリオで人気を博した名作です。唯一対抗馬になりそうなのはこれくらいでしょうか。

有力な要素

  • 直近で「レベルE」「キルラキル」「マクロス」など、アニメファン以外も知っているような超有名作品ではない作品を出してきており、「私はこんな作品も知ってるよ!」という路線で考えた場合は非常に有力

懸念点

  • 前バージョンがマクロスだったので、同じロボット系SFアニメを連載することを避けるのではないか
  • 海外での知名度がそれほど高くない

 個人的には好きなんですけどね、ナデシコ

大穴:風の谷のナウシカ(Nausicaa of the Valley of The Wind)

言わずとしれたジブリアニメの雄ですね。

 

有力な要素

  • コードネームを考える中で「ジブリアニメから1回は採用したい」と考えている場合はかなり有力。(他のタイトルは、「千と千尋の神隠し(Spirited Away)」など作品名に修飾語が多く、イニシャルを意識しづらいものが多い)

懸念点

  • 海外での評価はそれほど高くない(いわゆる海外アニメ人気の文脈において、日本のそれほど王道的な立ち位置ではない)

ジブリアニメ自体は非常に有力なのですが、
NARUTO」か「ナウシカ」の2択だと、NARUTOを選ぶような気がするんですよね・・・。
これが「NARUTO」と「ナデシコ」の2択だと、ナデシコを選ぶ可能性がありそうに感じてしまうのは、なんとなくアニメファンの業みたいなものを感じます。

 

 

以上、Vue.jsのコードネーム界隈の話でした!
フロントエンド界隈では確固たる地位を得たVue.jsですが、本筋とは別に、こんな楽しみ方も提供していることを知ってもらえれば幸いです!

 

続きを読む

毎月恒例!#ProLabo(プロラボ)渋谷もくもく会@渋谷1月12日(土)に開催しました! 

こんにちは! ITプロパートナーズ(https://itpropartners.jp/)インターン栗岡です!

普段は、Laravelで自社サービスの開発をしたり、新卒採用関係の業務をやっています。

今回は、1月12日に弊社渋谷オフィスで開催されたもくもく会をレポートします!

続きを読む

Nuxt.js + QiitaAPIで開発したWebアプリケーションをFirebaseにデプロイする

こんにちは。

ITプロパートナーズでエンジニアの米川(@keiuwk0614)です。

 

普段は、自社プロダクトである中途向けの転職サービスGraspy(https://graspy.jp/)の開発をしています。フロントエンドはNuxt.js、サーバサイドはLaravelを使用し開発しています。

今回は、初学者向けにNuxtのプロジェクト作成から、外部APIを呼び出して簡単なWebアプリケーションを開発し、Firebaseのホスティングにデプロイするまでを紹介していきたいと思います。

f:id:itpro_yonekawa:20181212172913p:plain

 

 

実行環境

  • node v10.3.0
  • yarn 1.9.4
  • nuxt 2.0.0
  • firebase CLI 5.0.1

 1. Nuxtプロジェクト作成

1-1. プロジェクト作成

プロジェクトを作成するディレクトリに移動し、公式ドキュメント(インストール - Nuxt.js)にならい下記コマンドを実行します。

※今回はyarnを使用

yarnが入っていない方は yarnを使ってみた - Qiita  を参照してください。

$ yarn create nuxt-app <my-project> 

 いくつか質問されます 。

    ※今回は、UI frameworkにbulma、rendering modeはUniversal、axios moduleを使用するのでyesで選択してください。

? Project name nuxt-firebase
? Project description My tiptop Nuxt.js project
? Use a custom server framework none
? Use a custom UI framework bulma
? Choose rendering mode Universal
? Use axios module yes
? Use eslint no
? Use prettier no
? Author name kei yonekawa
? Choose a package manager yarn

選択後、全ての依存関係がインストールされプロジェクトが作成されます。

 

1-2.  起動

作成したプロジェクトのディレクトリに移動し、下記コマンドを実行します。

$ yarn run dev

デフォルトで3000番ポートが開きます。 http://localhost:3000 でアクセスし下記画面が表示されれば成功です。

f:id:itpro_yonekawa:20181211235205p:plain

デフォルトのポート番号を変更したい場合は、package.jsonのdevの引数にポートを指定するか、

"scripts": {
"dev": "nuxt --port 3333",
}

nuxt.confing.js内に設定することで変更できます。

module.exports = {
server: {
port: 8888,
},
// その他設定
}

 

2. axiosでQiita APIを呼び出す

2-1. 使用するQiita API

今回使用するのは、GET /api/v2/items という記事の一覧を作成日時の降順で返却するAPIを使用します。詳細は下記のAPI仕様書をご確認ください。

qiita.com

 

2-2. ayncData内でqiita apiを呼び出す

 その前にasyncDataには次のような機能があります。

 

ページコンポーネントがロードされる前に毎回呼び出される

・サーバサイドレンダリングや、ページ遷移前にも呼び出される

・contextを引数にとる

・asyncDataの結果は、dataとマージされる

 

asyncDataと似たようなメソッドに、fetchというメソッドもあります。

fetchもasyncDataもほぼほぼ機能は同じですが、asyncDataの場合はdataとマージされるため、必ずプロパティをreturnする必要があります。取得したデータをvuexに入れて使用する場合はfetchを使用し、ページコンポーネント内で使用する場合はasyncDataを使用するのが良さそうです。

 

それでは、プロジェクト作成時にデフォルトで生成されたpages/index.vueを編集します。今回は、apiで取得した結果をそのままページコンポーネント内で使用するため、asyncData内でapiを呼び出します。

<script>
// axios
import axios from 'axios';
// qiita api URL
const BASE_URL = 'https://qiita.com/api/v2/';

export default {
async asyncData(context) {
try {
const response = await axios.get(BASE_URL + 'items', {
params: {
page: 1,
per_page: 10,
}
});
return {
articleList: response.data,
};
} catch (error) {
console.log(error);
}
}
}
</script>

/api/v2/itemsAPIには次のパラメータが設定できます。

  • page ページ番号 (1から100まで)
  • per_page 1ページあたりに含まれる要素数 (1から100まで)
  • query 検索クエリ

今回は、10件のデータを取得してくるように固定で設定します。

何かキーワード検索したい場合は、queryというパラメータに検索したいキーワードを設定することも可能です。

params: {
page: 1,
per_page: 10,
query: 'Nuxt.js',
}

 

2-3. apiのレスポンス結果を画面に表示

2-2ではasyncData内でapiを呼び、レスポンス結果をarticleListに設定してreturnしています。先ほども述べたように、asyncDataの結果はdataとマージされるため、pages/index.vueでarticleListを展開していきます。

articleListをv-forでループし、記事のタイトル、記事URL、アイコン画像、ユーザーID、いいね数を表示します。

レスポンスには他にも本文、タグ、更新日など様々あります。必要に応じカスタマイズしてください。

まずは、下記のコードをコピペでOKです。

<template>
<section>
<article
v-for="(article, index) in articleList"
:key="index"
class="box media">
<figure class="media-left">
<p class="image is-64x64">
<img :src="article.user.profile_image_url">
</p>
</figure>
<div class="media-content">
<div class="content">
<p>
<
strong><nuxt-link :to="article.url">{{ article.title}}</nuxt-link></strong> <br>
{{ article.user.id }}<br>
<small>Like · {{ article.likes_count }}</small>
</p>
</div>
</div>
</article>
</section>
</template>

 

ブラウザに戻り、上記コードコピペしていれば次のような画面が表示されていると思います。

 

 

f:id:itpro_yonekawa:20181212234848p:plain

 

これで一旦、Qiita APIを呼び出し記事の一覧を表示するところまでは完了になります。

コンポーネントの切り出し、デザイン等は各自でカスタマイズして貰えればと思います。

 

3. Firebase Hostingにデプロイ

3-1. Firebaseの準備

Firebase Console(https://console.firebase.google.com/?hl=ja)にアクセスし、googleアカウントでログインします。

f:id:itpro_yonekawa:20181213001128p:plain

プロジェクト、ロケーションの設定、規約に同意しプロジェクトを作成を押下します。

自動でFirebaseの管理画面に遷移します。

f:id:itpro_yonekawa:20181213001208p:plain

 

3-2. Firebase Hostingにデプロイ

3-2-1. Firebase CLIをインストール

先ほど作成したプロジェクトのディレクトリで、Firebase CLIをインストールしFirebaseコマンドを使用できるようにします。

$ yarn global add firebase-tools
3-2-2. firebaseにログイン

下記のコマンドを実行し、firebaseにログインします。

このコマンドを実行するとローカルコンピュータがFirebaseアカウントに接続され、プロジェクトへのアクセス権が付与されます。

$ firebase login
 3-2-3. firebaseのホスティングの初期設定

下記コマンドを実行し、ホスティングの初期設定を行います。

$ firebase init hosting

先ほど作成したfirebaseプロジェクトを選択します。

? Select a default Firebase Project for this directory: nuxt-tutorial(nuxt-tutorial-491c1)

公開ディレクトリはdistにします。

? What do you want to use as your public directory ? dist

SPAとして公開するか聞かれますが、今回はasyncDataを使用しSSRしているのでNoを入力します。

? Configure as a single-page app (rewrite all urls to /index.html)? No

プロジェクト直下にfirebase.jsonと.firebasercというファイルが自動で作られます。

 

 3-2-4. firebase デプロイ

 下記コマンドを実行します。

 dist/ 配下に静的ファイルが生成されます。

$ yarn build

本番環境に公開します。

$ firebase deploy

無事にデプロイできましたでしょうか。

firebase Hostingのダッシュボードでデプロイが成功したか、デプロイ先のドメインが分かります。

f:id:itpro_yonekawa:20181225171535p:plain

 

 

筆者がデプロイしたものは下記のURLからご確認頂けます。

https://nuxt-tutorial-491c1.firebaseapp.com/

 

 

今回作成したコードは、githubに公開していますので全体を見たい人はこちらを参考にしてください。

GitHub - keiyonekawa0614/nuxt-firebase: nuxt + qiita API + firebase hosting sample

 

ちょっと応用してキーワード検索できるものも作ってみました。

daryl-f5622.firebaseapp.com

こちらもgithubソースコードを公開しておりますので、参考にしてみてください。

GitHub - keiyonekawa0614/nuxt-tutorial: Web service to search qiita articles.


 

 最後に

ITプロパートナーズでは、Laravel、vue.js、Nuxt.jsで開発に挑戦したいエンジニア・デザイナーを絶賛募集中です。少しでも興味のある方は、DMでもGraspy、Wantedlyでもお気軽にご連絡頂けますと嬉しいです。お待ちしております。

 

 

サービスの管理画面で Vue + element.ui を活用する(table編)

ITプロパートナーズの新卒採用サービス「intee」のエンジニアの五藤です。

intee.jp

inteeの技術スタックは、バックエンドがPHP(CakePHP3)、フロントエンドがVue.jsを採用しています。 ユーザーが見る画面はもちろんの事、弊社スタッフが利用する管理画面に関しても、新しく実装する画面に関してはほとんどVueを使って管理画面を構築しています。

「何で管理画面のフロントエンドをリッチにする必要が?」

って思われるかもしれませんが、管理オペレーションが複雑になってくると、

  • 一度に複数のユーザーに対して操作したり、複数のレコードを追加する際にいちいち画面遷移したくない
  • 複雑なリレーションのデータ登録を、モーダルなどを用いて効率的にやりたい

などなど、オペレーション最適化の面で、リッチなフロントエンドを提供するメリットは意外と多く、営業サイドから 「この画面をVueを使ってサクサク使えるようにしてほしい」 という要望を受けることもしばしばだったります。

そんな中で、UI/コンポーネントライブラリとして愛用しているのが、Element です!

Element - The world's most popular Vue UI framework

各種フォーム部品やモーダルやアラート、簡単なグラフ表示などの、リッチな画面を作るのに必要なコンポーネントが揃っているニクいやつです。しかも、Vueのコンポーネントとして実装されているため、

<el-tag type="success">Elementに用意されてるめっちゃきれいなタグUI</el-tag>

という感じに、HTMLライクな書き方で簡単にコンポーネントを配置できるのも嬉しいところです。

今回は、その中でも、管理画面の画面設計の中核を占める <el-table> の使い方や、実装上のポイントについてまとめます!

tableコンポーネントてどんなの?

スクリーンショット 2018-11-28 10.07.36.pngelement-ui公式 より引用 )

簡単に言うと、管理画面でよくある、「データ一覧をテーブル形式で表示する」事ができるコンポーネントです。 これだけ書くと凄くシンプルなので、elementのtableのすごい所をガンガン紹介します!

el-tableを使うと捗るポイント

データ投入が簡単で、いい感じに表示してくれる

データ設定の方法は簡単で、配列形式のデータをVueのdata属性に格納して、<el-table> のプロパティとして指定するだけ。

(データ側)

data: {
          tableData: [{
            date: '2016-05-03',
            name: 'Tom',
            address: 'No. 189, Grove St, Los Angeles'
          }, {
            date: '2016-05-02',
            name: 'Tom',
            address: 'No. 189, Grove St, Los Angeles'
          }, {
            date: '2016-05-04',
            name: 'Tom',
            address: 'No. 189, Grove St, Los Angeles'
          }, {
            date: '2016-05-01',
            name: 'Tom',
            address: 'No. 189, Grove St, Los Angeles'
          }]
        }

(コンポーネント)

<el-table :data="tableData">

これだけで、tableDataプロパティに格納した配列データを、<el-table>内で使用することが出来ますし、el-dataの値を切り替えれば、リアルタイムでテーブル上の値も更新されます。

また、dataに格納する値は、

<el-table :data="tableData">

      <!-- 日付データを表示するカラム -->     
      <el-table-column
        prop="date"
        label="Date"
        width="180">
      </el-table-column>

      <!-- 名前データを表示するカラム -->
      <el-table-column
        prop="name"
        label="Name"
        width="180">
      </el-table-column>

<el-table>

という感じで、table側で自由に各カラムを抽出、表示できます。 dataに設定された全カラムが勝手に出力されるのではなく、コンポーネント側で出したい情報を自由にピックできる のがポイントで、実際の想定シーンとしては、

  • dataプロパティには、サーバーサイド側の参照APIをまるっと格納させ、<el-table>側で、必要なデータを必要な形でレイアウトする

というやり方で、 汎用的なAjaxの戻り値を、そのまま<el-table>にぶちこめる のが実装上は凄く楽だったりします。

各カラムの表示内容が、タグベースで柔軟に設定できる

各カラムに表示する値は、HTML形式で動的に設定可能で、更に言うと、他のelementのコンポーネントを配置することも出来ます。

[いろんなタグを配置してみるとこんな感じ]

f:id:itpro_goto:20181203220644p:plain
いろんなタグを配置してみた

こんな感じで、画像やアイコン、タグ、ボタンなどを各カラムにポチポチ配置して、可読性の高い画面をデザイナー抜きで簡単に作ることが出来ちゃいます。 もちろんボタンに導線を作ることもできるので、

  • ボタンを押すとチェックリストにチェックが付く
  • ボタンを押すとモーダルを表示してデータ編集ができる

といった処理を組むことも簡単です。 ちなみにモーダルもelementで用意されています。

http://element.eleme.io/#/en-US/component/dialog

いたれりつくせりですね。

・・・どうですか?管理画面に<el-table>使いたくなりませんか?

実際に使う上でのtips

<el-table>の素晴らしさがわかったところで、実際に作っていく上でのポイントをいくつか書いていきます。

基本的なデータフロー

前項でも述べましたが、<el-table>に格納するデータは、Ajaxの戻り値をそのまま格納するのがわかりやすいので、 「データを取得する共通処理」を一つの共通メソッドにまとめておき、表示・更新したいタイミングで呼び出す のが基本的な実装パターンになります。以下はデータ読み込み処理のコード例です。

// レコード取得を実施
getModels:function(){
  var that = this
  this.isLoading = true // (1)ローディング表示をON
  $.ajax({ // jQuery ajax使ってますが他のライブラリでも対して変わらないはず
    url:this.apiUrl,
    type:'GET',
    data:this.condition // (2)GETパラメータをプロパティ
  }).done(function(data){
    // API戻り値をtableDataに格納
    that.tableData = data.models 
    that.isLoading = false
  })
},

いくつかポイントを上げると、

  • APIを呼び出すタイミングでローディング用のプロパティをONにし、読み込み後にOFFにすることでローディングを実装
    • ローディングステータスは<el-table v-loading="loading"> という感じで、v-loadingディレクティブにbindすることで、プロパティと同期できます。
  • 検索クエリとページネーションはプロパティにまとめておくと、そのまま渡せる(検索ボックス側でthis.conditionを編集する作りにすると、検索側と読み込み側が疎結合になるので扱いやすい

という感じです。

データ表示の基本2タイプ

表示カラムは<el-table-column> を使うといいましたが、2つの記法があります。

el-table-column::prop で簡単カラム指定

<el-table-column prop="full_name" label="氏名">
</el-table-column>

propプロパティに直接Objectのキーを指定すると、文字列としてデータが表示されます。

template slot-scope="scope" で細かく指定

もう少しリッチに各カラムのデータを書きたい場合は、このように書きます。

<el-table-column label="タグ一覧">
  <template slot-scope="scope">
       <el-tag v-for="tag in scope.row.tags" :key="tag.id" type="success">{{tag.name}}<el-tag>    
  </temlate>    
</el-table-column>

ポイントとしては

  • <template slot-scope="scope"> で囲んだ中に、そのカラムで表示したいHTMLを配置
  • scope.row.[カラム名] で各レコードの情報が参照できる

です。このやり方を使うと、カラムの中で自由にレコード情報を表示ことができるため、 先程あげたような

f:id:itpro_goto:20181203220644p:plain

  • 画像を貼り付けたり
  • カラム内で改行して複数の情報を表示したり
  • アクションボタンを配置したり

とかなり応用が効くようになります。

テーブルの行番号を取得したい。

行番号は scope.$index で取得できます。

<el-table-column width="50" fixed>
  <template slot-scope="scope" label="No">
    {{ scope.$index}}
  </template>
</el-table-column>

発展パターンとして、ページネーションを実装している場合のレコード番号は、

<el-table-column width="50" fixed>
  <template slot-scope="scope" label="No">
    {{ getRecordSequence(scope.$index)}}
  </template>
</el-table-column>

というふうに外部メソッドにscope.$index を投げて、

getRecordSequence(index){
  if(!this.paginate.page || !this.paginate.perPage){
    return index + 1
  }
  return (this.paginate.page - 1) * this.paginate.perPage + index + 1
},

こんな感じで、ページネーションの値と組み合わせて算出したりもします。

ページネーション

<el-table> はページングのための特別な仕組みを持たないため、

  • dataプロパティに「ページ情報」と「総ページ数」を用意しておき、API更新のタイミングで同期する
  • 画面側のページング表示、操作は<el-paginate> コンポーネントを別途配置して、こちらもAPI更新と紐付ける

というやり方で実装します。

データ構造

data:{
  condition:{
    page: 1, // 現在のページ数(conditionに含めることでクエリパラメータとして渡される
  },
  pageCount: 1, //ページ数を取得
},
methods: {
  getModels:function(){
    var that = this
    $.ajax({ // jQuery ajax使ってますが他のライブラリでも対して変わらないはず
      url:this.apiUrl,
      type:'GET',
      data:this.condition 
  }).done(function(data){
    that.tableData = data.models 
    that.isLoading = false
    that.pageCount = data.paginate.pageCount //総ページ情報を更新
    that.paginate = data.paginate //現在ページ情報を更新
  })
},
            }

ページネーション部品

<el-pagination
  @current-change = "getModels"
  :current-page.sync="condition.page"
  :page-count="pageCount">
</el-pagination>

通化のパターン

いろいろな画面で<el-table>を使うようになってくると、必要な処理を共通化したい!と思う人もいるかも知れません。結論からいうと、共通化はcomponentよりもmixinで行うのが個人的にはおすすめです。 mixin側で、

  • APIとの通信処理
  • 取得したレコード一覧や検索条件、ページネーションを保持するためのdataオブジェクト

を共通化して持っておくと、このパターンのテーブル表示を量産する上では役に立ちます。 こんな感じでしょうか。

// 管理画面の汎用テーブルプラグイン

var dataTableMixin = {
    data:{
        getUrl: '/get', // データ取得用のAPI。必要に応じて実装側でオーバーライドする。
        models: [], // 取得されたレコード配列を保持
        // 検索条件を保持。値を変更することで、レコード取得APIにリクエストクエリとして渡される
        condition:{
            page: 1, // ページ情報も検索条件の一つとして保持する
        },
        pageCount: 1, // APIから返却された総ページ数の値を保持
        isLoading: false // ローディング状態を保持
    },
    mounted:function(){
        this.getModels()
    },
    methods:{
        // ページネーション切り替え
        changeCurrentPage: function(page){
           this.condition.page = page
           this.getModels()
        },

        // レコード取得を実施
        getModels:function(){
            var that = this
            this.isLoading = true
            $.ajax({ // jQuery ajax使ってますが他のライブラリでも対して変わらないはず
                url:this.getUrl,
                type:'GET',
                data:this.condition
            }).done(function(data){
                that.models = data.models
                that.isLoading = false
                // ページネーション関連情報をセット
                that.pageCount = data.paginate.pageCount
                that.paginate = data.paginate
                that.afterGet()
            })
        },
        // レコード取得後に独自処理を追加するためのフックメソッド
        afterGet:function(){
            return //OVERRIDE ME
        },
    }
}

いかがでしたでしょうか?ぜひ管理画面もリッチな <el-table> をご活用ください!

毎月恒例!#ProLabo(プロラボ)もくもく会を@渋谷11月25日(土)に開催しました! 

こんにちは! ITプロパートナーズ(https://itpropartners.jp/)インターン栗岡です!

普段は、Laravelで自社サービスの開発をしたり、新卒採用関係の業務をやっています。

今回は、11月25日に弊社渋谷オフィスで開催されたもくもく会をレポートします!

続きを読む

【Laravel】コマンドアプリケーションで行うデータ移行

さなぽんです。社内ではマッチングサービスを中心とした受託案件のお仕事をしています。
Twitterは例のサングラススパムに乗っ取られて凍結されてしまいました。。。とほほ。


お仕事はCakePHP2や3を中心に、最近はLaravelも使い始めました。
弊社サービス「ITプロパートナーズ」に登録いただいたエンジニアの方とチームで動きディレクション中心に行ったり
自分ひとりであのフレームワークは…こっちだと…などと手を動かしたりもしています。


お客様からシステムのリプレイス案件のお声掛けをいただくことも多々あります。
本当にありがたい限りです。

リプレイスするにあたり、サーバーや言語のバージョンアップ、フレームワークを変更して再コーディングを行う以外に
データベースの再設計を検討することもよくあるお話です。


再設計をして、いざ、データ移行!となるのですが、これが思いの外面倒な作業となる事が多々あります。
SQLを用意し作業をしていると、条件分岐やループはPL/SQLだと便利なのにな、、、なんて思ってしまうこともありますね。


そこで今日紹介するのは、コマンドライン処理を使ってデータ移行を行うやり方です。
この仕組みもITプロパートナーズに登録いただいたエンジニアさんが作っていただいたものになります。


まずはクラスを作成します。以下のコマンドを実行してみましよう。

$ php artisan make:command Migrate

実行後、app/Console/Commands配下に以下のクラスが作成されているはずです。

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

class Migrate extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'command:name';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Command description';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        //
    }
}

$signatureには実行時のコマンド名、$descriptionにはコマンドの説明をそれぞれ設定します。
例えば以下のように設定をします。

    protected $signature = 'migrate:exec';
    protected $description = 'データ移行実行';

その後、artisan listを実行すると、、、

$ php artisan list

Laravel Framework 5.6.38

Usage:
  command [options] [arguments]

… 略

 migrate
  migrate:exec           データ移行実行

表示されました!
これで php artisan migrate:exec とコマンドを叩くとMigrateクラスが実行されることになります。


引き続き、処理を書いていきましょう!
処理は handle() に記述していきます。

<?php

namespace App\Console\Commands;

use Carbon\Carbon;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;

… 略

public function handle()
{
    DB::transaction(function () {
        $this->migrate();
        $this->seed();
    });
    return true;
}

private function migrate()
{
    $this->progress('dropTables');
    $this->progress('callMigrate');
}

private function progress($func, $message = null)
{
    $this->_bar->setMessage($message ?? snake_case($func, ' '));
    $this->$func();
    $this->_bar->advance();
}

private function dropTables()
{
    foreach (\DB::select('SHOW TABLES') as $table) {
        $column_name = 'Tables_in_' . \DB::connection('')->getDatabaseName();
        \DB::statement('DROP TABLE IF EXISTS `' . $table->$column_name . '`');
    }
}

private function callMigrate()
{
    \Artisan::call('migrate');
}

private function seed()
{
    foreach ($this->getSeedFunc() as $item) {
        $this->progress($item);
    }
}

private function getSeedFunc()
{
    return [
        'seedCompany',
    ];
}

private function seedCompany()
{
    foreach (DB::connection('old_db')->table('company')->select()->cursor() as $item) {
        DB::table('companies')->insert([
            'id'                 => $item->id,
            'name'           => $item->name,
            'zipcode'       => $item->zipcode,
            'address'       => $item->address,
            'tel'                 => $item->tel,
        ]);
    }
}

一気に書いてしまいました笑
旧DBのcompanyテーブルから新DBのcompaniesテーブルにデータを移行します。
この中でif文などの制御はもちろん、複雑な処理も行う事ができます。

また、処理の中で旧DBからデータを取得しますので、 config/database.php ファイルに旧DBの情報も記述します。

'old_db' => [
    'driver' => 'mysql',
    'host' => env('DB_OLD_HOST', '127.0.0.1'),
    'port' => env('DB_OLD_PORT', '3306'),
    'database' => env('DB_OLD_DATABASE', 'forge'),
    'username' => env('DB_OLDP_USERNAME', 'forge'),
    'password' => env('DB_OLD_PASSWORD', ''),
    'unix_socket' => env('DB_OLD_SOCKET', ''),
    'charset' => 'utf8mb4',
    'collation' => 'utf8mb4_unicode_ci',
    'prefix' => '',
    'strict' => true,
    'engine' => null,
],

DB_OLD_xxx の内容は .env ファイルにて設定します。

これでひとまず動くかと思いますので、是非試してみてください。


ここからは宣伝です。
12月1日(土)に「起業家」と「ITプロフェッショナル」の出会いを創出する
ビジネスコンテスト『HATCH』を行います。
観覧者を大募集していますので、興味のある方は是非お越しください!

itpro.connpass.com


12月18日(火)にSIerやSESからWEBエンジニアへのキャリアチェンジをテーマにしたイベントを開催します。
ワタクシが司会をする予定です。こちらもよろしくお願いします。

itpropartners.connpass.com