アプリ関連ニュース

Nodejsの始め方

NodeJSは、サーバーサイドのWebアプリケーションを開発するためのオープンソースでクロスプラットフォームな実行環境です。今回は、NodeJSをNode Package Module(NPM)を使って、ステップバイステップで基本的な実装と解説を学びます。

NodeJSは、イベント駆動型のノンブロッキングI/Oモデルを採用しているため、軽量で効率的です。

NodeJSとNPMのインストールは、NodeJSの公式ホームページから入手できるインストーラーパッケージを使用することで簡単に行うことができます。

Nodejs

  • NodeJS WebSiteからインストーラーをダウンロードします。
  • インストーラーを実行します。
  • インストーラーの手順に従って、使用許諾契約に同意し、「次へ」ボタンをクリックします。
  • システム/マシンを再起動します。

以下のコマンドで、nodejsのバージョンを確認します。

node --version

コマンドでnpmのバージョンをテストします。

npm --version

test.js ファイルを作成します。

/*test.js file*/
console.log("Node is working");

test.jsは、コマンドプロンプトからNodeコマンド > node test.jsで実行することができます。これでインストールは終了です。

Node Package Module

NPMは、JavaScript開発者が効率的に依存関係をロードするのを助けるパッケージモジュールです。依存関係をロードするには、コマンドプロンプトでコマンドを実行する必要があります。

npm install

このコマンドは、ルートディレクトリにあるpackage.jsonという名前のjsonファイルを見つけて、そのファイルに定義されているすべての依存関係をインストールするものです。

Package.json

Package.jsonはこんな感じです。

{
  "name": "ApplicationName",
  "version": "0.0.1",
  "description": "Application Description",
  "main": "server.js",
  "scripts": {
    "start": "node server.js"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/npm/npm.git"
  },
  "dependencies": {
    "express": "~3.0.1",
    "angular": "latest",
    "angular-ui-router": "~0.2.11",
  }
}

package.jsonで最も重要なのは、名前とバージョンです。これらは実際に必須であり、これがないとパッケージはインストールされません。

Repository

{
  "repository": {
    "type": "git",
    "url": "https://github.com/npm/npm.git"
  }
}

コードが存在する場所を指定します。もしgitリポジトリがGitHubでない場合は、npm docsコマンドで見つけることができます。

Scripts

{
 "scripts": {
    "start": "node server.js"
  }
}

NPMは、npm install、npm start、npm stopなど、便利なスクリプトを多数提供しています。

パッケージのルートにserver.jsファイルがある場合、npmはデフォルトでnode server.jsを開始コマンドとして使用します。

Dependencies

{
   "dependencies": {
     "express": "~3.0.1",
     "angular":"latest",
     "angular-ui-router": "~0.2.11",
  }
}

依存関係は、パッケージ名とバージョン範囲を対応させたシンプルなオブジェクトで指定します。

Example:

/*server.js*/

const http = require('http');

const hostname = '127.0.0.1';
const port = 3000;

const server = http.createServer(function(req, res) {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello World\n');
});

server.listen(port, hostname, function() {
  console.log('Server running at http://'+ hostname + ':' + port + '/');
});

require(‘http’) を使って http サーバを作成し、それを http という変数に渡しています。ここでは、localHost(127.0.0.1)とポート番号3000を使用し、これをそれぞれ変数hostnameとportに代入しています。createServerメソッドを使用して、httpサーバーを作成します。

次に、server.jsファイルをnodeでコマンドを使って実行します。

node server

ブラウザを開き、URL http://127.0.0.1:3000/ を入力してください。ブラウザが画面にHello Worldのメッセージを表示します。

これで、サンプルのnodejsスクリプトを作成し、正常に実行できるようになりました。

By Tsuki



Laravelのフォームリクエスト: prepareForValidation

今回は、Laravelで検証を行う前にリクエストデータを操作することについて話したいと思います。

フォームのリクエスト例

まず、記事の投稿を保存するためのフォームリクエストの例から見てみましょう。入力に適用されるルールに注目してください。

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class StoreRequest extends FormRequest
{
    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'title' => 'required|max:200',
            'body' => 'required',
            'tags' => 'required|array|max:10',
            'is_published' => 'required|boolean',
            'author_name' => 'required',
        ];
    }
}

ここで、ユーザーが投稿を作成するためにフォームを送信し、次のような入力データを渡したと仮定します。

[
    'title' => 'My  articles post',
    'body' => 'This is the <script>alert('Alert!')</script> articles body.',
    'tags' => 'laravel,code,updates',
    'is_published' => 'true',
    'author_name' => 'Ami',
]

tagsはカンマ区切りの値のリストとしてフロントエンドから送信され、is_publishedの入力は文字列として解釈されます。どちらも、コンテンツの観点からは正しいにもかかわらず、形式が正しくないだけで検証は失敗します。

さらに、titleにタイプミスがあり、本文に悪意のあるコードが含まれているように見えます。技術的にはこれらはバリデーションの問題ではないと言えますが、ユーザーを自分自身から救い、アプリケーションを保護する手助けをすることは可能です。

prepareForValidation

このメソッドはprepareForValidationという適切な名前で、デフォルトのアクションを持ちません。つまり、オーバーライドするためだけに置かれたものです。

protected function prepareForValidation()
{
    // no default action
}

ベースとなる FormRequest クラスは Request クラスを継承しているので、 merge ヘルパーメソッドにアクセスし、必要な入力値だけを更新することができます。また、入力値そのものにクラスのプロパティのようにアクセスすることもできます。

protected function prepareForValidation()
    {
        $this->merge([
            'title' => fix_typos($this->title),
            'body' => filter_malicious_content($this->body),
            'tags' => convert_comma_separated_values_to_array($this->tags),
            'is_published' => (bool) $this->is_published,
        ]);
    }

値はリクエスト自体で更新されるので、バリデーションを行った後にコントローラでどのようにアクセスしても、操作された値が戻ってくることになります。

[
    'title' => 'My blog post',                         // 誤字を修正しました!
    'body' => 'This is the post body.',         //悪質なコンテンツは削除されました!
    'tags' => ['laravel', 'code', 'updates'],   // 配列になりました!
    'is_published' => true,                     // 今はブール値です!
    'author_name' => 'Ami',    // 相変わらずです。

今回はということで終わります。

By Ami



Vue.jsの実用的なヒント

開発時にトリックを使用できれば、開発はよりスマートになり、時間を短縮できます。この記事では、Vuejsの最高のトリックを共有するつもりです。

1つのcomponentを複数のルートで使用する

複数のルートが同じVue componentに解決されることは、開発者が遭遇するかなり一般的な状況です。

しかし、問題は、Vueがアプリを最適化し、新しいコンポーネントを作成する代わりに、既存のコンポーネントを再利用することです。そのため、同じコンポーネントを使用するルート間で切り替えようとしても、何も変わりません。

router.js

const routes = [
  {
    path: "/a",
    component: ArticleComponent,
  },
  {
    path: "/b",
    component: ArticleComponent,
  },
];

これを修正するには、要素に:keyプロパティを追加する必要があります。これはApp.vueファイルにある可能性があります。これは、ページが異なる場合に routerが認識するのに役立ちます。

App.vue

<router-view :key='$route.path' />

これで、アプリは既存のコンポーネントを再利用せず、ルートを切り替えるときにコンテンツを更新します。

小道具をタイプのリストに制限する

プロップ定義で「バリデーター」オプションを使用すると、プロップを特定の値のセットに制限できます。

export default {
  name: 'Image',
  props: {
    src: {
      type: String,
    },
    style: {
      type: String,
      validator: s => ['square', 'rounded'].includes(s)
    }
  }
};

この「validator」関数は小道具を受け取り、小道具が有効かどうかにかかわらず、trueまたはfalseのいずれかを返します。

single スコープスロットの省略形

スコープスロットはとても楽しいですが、それらを使用するには、多くの template タグも使用する必要があります。

幸いなことに、それを取り除くための速記がありますが、それは単一のスコープスロットを使用している場合に限られます。

<DataTable>
  <template #header="tableAttributes">
    <TableHeader v-bind="tableAttributes" />
  </template>
</DataTable>

次のように書き直すことができます。

<DataTable #header="tableAttributes">
  <TableHeader v-bind="tableAttributes" />
</DataTable>

シンプルでわかりやすく、すばらしい。

すべての小道具を子コンポーネントに渡す

小道具と言えば、親 componentからその子の1つにすべての小道具を渡す方法を知っておくと便利です。

簡単です。instanceのプロパティを覚えておく必要があります。

<child-comp v-bind="$props"></child-comp>

local スタイルと global スタイルを組み合わせる

通常、スタイルを操作するときは、スタイルを単一の component にスコープする必要があります。

<style scoped>
  .component {
    background: green;
  }
</style>

ただし、ピンチでは、スコープのないスタイルブロックを追加して、必要に応じてグローバルスタイルを追加することもできます。

<style>
  /* Applied globally */
  .component p {
    margin-bottom: 16px;
  }
</style>

<style scoped>
  /* Scoped to this specific component */
  .component {
    background: green;
  }
</style>

v-forでの破壊

v-forで分解できることをご存知ですか?

<li
  v-for="{ name, id } in users"
  :key="id"
>
  {{ name }}
</li>

次のようなタプルを使用することで、v-forからインデックスを取得できることがより広く知られています。

<li v-for="(movie, index) in [
  'Lion King',
  'Frozen',
  'The Princess Bride'
]">
  {{ index + 1 }} - {{ movie }}
</li>

オブジェクトを使用するときは、キーを取得することもできます。

<li v-for="(value, key) in {
  name: 'Lion King',
  released: 2019,
  director: 'Jon Favreau',
}">
  {{ key }}: {{ value }}
</li>

また、この2つの方法を組み合わせて、キーだけでなく、プロパティのインデックスも取得することが可能です。

<li v-for="(value, key, index) in {
  name: 'Lion King',
  released: 2019,
  director: 'Jon Favreau',
}">
  #{{ index + 1 }}. {{ key }}: {{ value }}
</li>

カスタムV-model

デフォルトでは、v-model は “@input” イベントリスナーと “:value” プロップに対する構文糖の機能です。実は、どのイベントと値のプロップを使うかを指定できることをご存知でしょうか?Vueコンポーネントにmodelプロパティを指定することで、簡単に指定することができます。

export default{
  model: {
     event: 'change',
     prop: 'checked'
  }
}

複数のv-ifを使用しないでください

条件付きで複数の要素をレンダリングする必要がある場合もありますが、多くの場合、次のようなものを記述します。

<div v-if="condition">content</div>
<div v-if="condition">content</div>
<div v-if="condition">content</div>

もっとエレガントに書けるから不要なんです。

<template v-if="condition">
  <div>content</div>
  <div>content</div>
  <div>content</div>
</template>

Arraysとobjectsを見る

ウォッチャーを使う上で一番厄介なのは、うまくトリガーできないことがあることです。

通常は、ArrayやObjectをウォッチしようとしているのに、deepをtrueに設定していないことが原因です。

export default {
  name: 'ColourChange',
  props: {
    colours: {
      type: Array,
      required: true,
    },
  },
  watch: {
    // Use the object syntax instead of just a method
    colours: {
      // This will let Vue know to look inside the array
      deep: true,

      // We have to move our method to a handler field
      handler()
        console.log('The list of colours has changed!');
      }
    }
  }
}

Vue 3の反応性APIを使用すると、次のようになります。

watch(
  colours,
  () => {
    console.log('The list of colours has changed!');
  },
  {
    deep: true,
  }
);

以上が、vuejsの開発における最高のトリックです。次回は、さらに多くのトリックを紹介する予定です。

By Tsuki



DataTablesを使用したテーブル生成とサーバーサイド連携(5)

DataTablesを使用したテーブル生成方法とサーバーサイド連携方法をシェアしたいと思います。
今回はサーバーサイド側の処理でデータベースから取得したレコードをDataTables表示に反映させる部分を説明いたします。

データベースから取得したレコードをDataTables表示に反映

以下のようにレコード内容がa,b,c,d,e固定になっていた部分をテーブルから取得した
実際のレコードに書き換えます。

function user_datatables(Request $request) {

    $rec_data = [];
    //テーブルから取得した実際のレコードに書き換え
    $query = Member::query();
    $member_list = $query->get();
    foreach($member_list as $member){
        $row_data = [
            'item1' => $member->id,
            'item2' => $member->sei.$member->mei,
            'item3' => $member->sei_kana.$member->mei_kana,
            'item4' => $member->mail,
            'item5' => $member->created_at->format('Y-m-d H:i'),
        ];
        $rec_data[] = $row_data;
    }

    $draw = $request->draw;

    $res_json = array(
        'draw' => $draw,
        'recordsTotal' => '57', 
        'recordsFiltered' => '57', 
        'data' => $rec_data, 
    );

    return response()->json($res_json);
}

以下のようにテーブルから取得したレコードがDataTablesに反映されていることが確認できました。

ページング処理の追加

次にページング処理の作成方法を説明いたします。

サーバーサイドでページング処理を実装するために
・1ページあたりの表示件数
・何件目から表示するか
のデータが必要になりますが、これらのデータはDataTablesがpostしてくれます。
以下のように取得できます。

//1ページあたりの表示件数
$length = $request->length;

//何件目から表示するか
$start = $request->start;

Laravelでレコードの抽出処理をおこなう際に、それぞれの数値をlimitおよびoffsetに設定します。

$query->offset($start);
$query->limit($length);

またフロント側でページ番号の表示処理をおこなうためにサーバーサイドからレコードの全件件数を
返す必要がありますが、これはLaravelの以下のメソッドで取得できます。

//全件件数の取得
$total_cnt = $query->count();

次回は上記の設定をおこなったページネーションのサーバーサイド処理の説明をおこないたいと思います。

木曜日担当:nishida



Windows用の Direct Storage API がリリースされました

XBOX series X では既に利用されていますが、
約1年程遅れてWindowsでも利用可能になるようです。

続きを読む

アプリ関連ニュース

お問い合わせはこちら

お問い合わせ・ご相談はお電話、またはお問い合わせフォームよりお受け付けいたしております。

tel. 06-6454-8833(平日 10:00~17:00)

お問い合わせフォーム