発注ラウンジにて弊社をご紹介いただきました

システム開発会社の比較・見積もりサイト「発注ナビ」が運営するオウンドメディア「発注ラウンジ」にて、弊社のインタビュー記事が掲載されました。

複数の競合サービス併用から、発注ナビ1つに絞り込んだことで、商談数、受注件数の増加、エンジニアのスキル向上、営業スタッフの育成など、多方面に結果が出ていることをお話させていただきました。
ぜひご覧ください。

発注ラウンジ

年末年始休業のお知らせ

平素は格別のご高配を賜り、誠にありがとうございます。
株式会社エイブリッジでは誠に勝手ながら、年末年始休業日を下記のとおりとさせていただきます。

【年末年始休業日】
2021年12月28日(火)~2022年1月3日(月)
※2022年1月4日(火)より、通常営業を開始致します。
※休暇中のお問い合わせにつきましては、2022年1月4日(火)以降に対応させていただきます。

ご不便をおかけいたしますが、何卒ご了承いただきますようお願い申し上げます。

PANTONE COLOR OF THE YEAR 2022が発表されました

PANTONEからカラーオブザイヤー2022が発表されました。
PANTONE COLOR OF THE YEAR 2022

2022年のトレンドカラーは「PANTONE 17-3938 Very Peri(ベリーペリ)」。
青味が強くて彩度の低い、柔らかい印象の紫色ですね。

私たちは変革の時代に生きています。PANTONE 17-3938 Very Periは、現在の世界的な時代精神と私たちが経験している移行の象徴です。
私たちが孤立の激しい時期から抜け出すにつれて、私たちの概念と基準は変化し、私たちの物理的生活とデジタル生活は新しい方法で融合しました。
デジタルデザインは、現実の限界を広げ、新しい色の可能性を探求し、創造できるダイナミックな仮想世界への扉を開くのに役立ちます。
ゲームのトレンドに伴い、デジタル空間でのメタバースと芸術コミュニティの人気の高まりPANTONE 17-3938 Very Periは、現代の生活の融合と、デジタル世界の色のトレンドが物理的な世界でどのように現れているかを示しています。

カラーデータ

HEX #6667AB
sRGB 102 103 171
LAB 45.75, 12.21, -36.75

Photoshopのカラーピッカーではこんな感じです。

PANTONE CONNECT

PANTONE CONEECTではAdobe系のカラースウォッチで使えるASEファイルがダウンロードできます。
また、Very Periを元にしたカラーパレットやシェードも用意されています。
PANTONE CONNECT(要会員登録)

Laravel8 + Vue + Pusherにてチャット構築

Laravel8 + Vueでのチャット機能を簡単にご紹介します。

開発環境

PHP v8.0.13
Laravel v8.73.2
npm v8.1.0

本記事ではPusherというサービスを使って構築していきます。
Laravel環境構築や、Pusherへの会員登録については他記事などを参考にしてみてください。

パッケージなどのインストール

$ composer require laravel/ui

Laravel UIをインストール。

$ php artisan ui vue --auth

スカフォールドを各フレームワークから選択。(今回はVue.jsを使用)

$ npm install

パッケージのインストール。

$ npm run watch

コンパイルの自動化。

$ php artisan migrate

マイグレーション実行。

Pusher連携部分の実装

App\Providers\BroadcastServiceProvider::class,

ブロードキャストを有効にするため、 config/app.php の上記コメントアウトを外す。

$ composer require pusher/pusher-php-server

Pusher用のパッケージのインストール。

$ npm install --save laravel-echo pusher-js

Laravel Echo用のパッケージをインストール。

window.Echo = new Echo({
    broadcaster: 'pusher',
    key: process.env.MIX_PUSHER_APP_KEY,
    cluster: process.env.MIX_PUSHER_APP_CLUSTER,
    forceTLS: true
});

resources/js/bootstrap.js の上記コメントアウトを外し、Laravel Echoを有効にします。

モデルの作成

php artisan make:model Message -m
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateMessagesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('messages', function (Blueprint $table) {
            $table->char('id', 36)->primary()->comment('ID');
            $table->char('user_id', 36);
            $table->text('message');
            $table->dateTime('deleted_at')->nullable()->comment('削除日時');
            $table->dateTime('created_at')->nullable()->comment('作成日時');
            $table->dateTime('updated_at')->nullable()->comment('更新日時');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('messages');
    }
}

作成されたマイグレーションファイルを上記のように修正。

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Message extends Model
{
    use HasFactory;

    protected $primaryKey = 'id';
    protected $keyType = 'string';
    public $incrementing = false;

    protected $fillable = ['user_id', 'message'];

    protected static function boot()
    {
        parent::boot();
        static::creating(function ($model) {
            $model->{$model->getKeyName()} = (string) \Str::uuid();
        });
    }

}

作成された app/Models/Message.php を上記のように修正。

public function messages()
{
    return $this->hasMany('App\Model\Message');
}

UserモデルにhasManyを追加。

$ php artisan migrate

マイグレーション実行。

Routeを追加

use App\Http\Controllers\MessageController;
...
Route::group(['middleware' => ['auth']], function () {
    Route::get('chat', [MessageController::class, 'index']);
    Route::get('messages', [MessageController::class, 'get']);
    Route::post('messages', [MessageController::class, 'send']);
});

routes/web.php に上記を追加。

Controllerを追加

$ php artisan make:controller MessageController
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Events\MessageSentEvent;
use App\Models\Message;

class MessageController extends Controller
{
    public function index()
    {
        return view('chat');
    }

    public function get()
    {
        return Message::with('user')->get();
    }

    public function send(Request $request)
    {
        $user = Auth::user();
 
        $message = $user->messages()->create([
            'message' => $request->input('message')
        ]);
 
        event(new MessageSent($user, $message));
 
        return ['status' => 'Message Success!'];
    }
}

Eventの作成

$ php artisan make:event MessageSentEvent
<?php

namespace App\Events;

use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use App\Models\Message;

class MessageSentEvent implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;
    public $message;

    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct(User $user, Message $message)
    {
        $this->user = $user;
        $this->message = $message;
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return \Illuminate\Broadcasting\Channel|array
     */
    public function broadcastOn()
    {
        return new PrivateChannel('test');
    }
}
return new PrivateChannel('test');

公開チャンネルにしたい場合、上記を Channelに変更することで対応可能。
また、 ‘test’ 部分を書き換えることで複数チャンネルにも対応可能。

Broadcast::channel('chat', function ($user) {
    return Auth::check();
});

今回はプライベートチャンネルを実装したため、 routes/channels.php にて認証チェックを行う。

Viewの作成

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
 
<head>
    <meta charset="UTF-8">
    <title>テストチャット</title>
    <link href="{{ mix('css/app.css') }}" rel="stylesheet" type="text/css">
    <meta name="csrf-token" content="{{ csrf_token() }}">
</head>
 
<body>
    <div id="app">
        <chat-component></chat-component>
    </div>
 
    <script src="{{ mix('js/app.js') }}"></script>
</body>
 
</html>

resources/views/chat.blade.php

<template>
    <div>
        <ul>
            <li v-for="(message, key) in messages" :key="key">
                <strong>{{ message.user.name }}</strong>
                {{ message.message }}
            </li>
        </ul>
        <input v-model="text" />
        <button @click="postMessage" :disabled="!textExists">Submit</button>
    </div>
</template>

<script>
export default {
    data() {
        return {
            text: '',
            messages: []
        };
    },
    computed: {
        textExists() {
            return this.text.length > 0;
        }
    },
    created() {
        this.getMessages();
        Echo.private('test').listen('MessageSentEvent', e => {
            this.messages.push({
                message: e.message.message,
                user: e.user
            });
        });
    },
    methods: {
        getMessages() {
            axios.get('/messages').then(response => {
                this.messages = response.data;
            });
        },
        postMessage(message) {
            axios.post('/messages', { message: this.text }).then(response => {
                this.text = '';
            });
        }
    }
};
</script>

resources/js/components/ChatComponent.vue

Pusherの設定

Name your app : アプリ名
Select a cluster : 日本で使用する場合、そのままでOK
Front end : Vue.js
Back end : PHP

Pusherにログイン後、「Create my app」画面から各種情報を入力して登録。

PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1

登録が完了したら「App Keys」メニューから必要情報をコピーし、 .env ファイルに追記。

ログイン後、 /chat にアクセスすることでチャットが行えます。

Laravelの知ってると便利な機能

laravel
エイブリッジでは、Web開発の際、開発言語にPHP、フレームワークによくLaravelを使用しています。
いろいろあるPHPフレームワークの中で世界でもっとも人気であると言っても良いと思います。

そこで、知っているとちょっと便利なテクニックを紹介したいと思います。
(Laravel8をベース)

■データ取得編

日付で抽出

User::whereDate('created_at', '2021-11-11')->get();

年で抽出

User::whereYear('created_at', '2021')->get();

月で抽出

User::whereMonth('created_at', '11')->get();

日で抽出

User::whereDay('created_at', '11')->get();

NULLは最後になるようにソートする

Post::orderByRaw('published_at IS NULL ASC')
->orderBy('published_at')->get();

日付で整列

// 未指定の場合はcreated_atの降順となる。
Post::latest()->get();

// カラム名を指定するとそのカラムの降順となる。
Post::latest('published_at')->get();

Modelのタイムスタンプのみを更新

User::find(1)->touch();

JSON配列を検索する

/*
+-----------------------------------------------------------------------------------------------+
| id | tags |
+-----------------------------------------------------------------------------------------------+
| 1 | ["Android","iOS","Web"] |
+-----------------------------------------------------------------------------------------------+
*/
$tag = 'Web';
$posts = Post::whereRaw("JSON_CONTAINS(tags,'["{$tag}"]')")->get();

/*
+-----------------------------------------------------------------------------------------------+
| id | tags |
+-----------------------------------------------------------------------------------------------+
| 1 | [{"id":1,"tag":"Android"},{"id":2,"tag":"iOS"},{"id":2,"tag":"Web"}] |
+-----------------------------------------------------------------------------------------------+
*/
$tag = 'Web';
$posts = Post::whereRaw("JSON_CONTAINS(tags,'{"tag":{$tag}}')")->get();

■Eloquent編

Modelの変更された項目を確認する

$user = App\Models\User::first();
$user->name = ’taro yamada’;
$user->age = 30;

$result = $user->getChanges();
logger($result);

/* 結果:
array(
"name" => "taro yamada", "age" => 30
);
*/

Modelの元の値を確認する

$user = App\Models\User::first();
logger($user->name);

// 結果:hanako yamada

$user->name = ’taro yamada’;

$result = $user->getOriginal('name');
logger('original: '.$user->name);

// 結果:hanako yamada

属性のキャスト
モデルでキャストを設定しておくと、指定した型で返却されます。
例えば、日付項目に文字列で日付を設定しても、getするときは日付型で返却されます。

class Post extends Model
{
protected $casts = [
'category_no' => 'integer'
'published_at' => 'datetime'
];
}

インクリメント/デクリメント

$user = User::find($id);

// インクリメント(+1)
$user->increment('login_count');
// デクリメント(-1)
$user->decrement('login_count');
// インクリメント(+5)
$user->increment('login_count', 5);
// デクリメント(-5)
$user->decrement('login_count', 5);

短期のお仕事!【沖縄】

今回は短期のお仕事の募集です!

期間:11月8日~2021年1月14日まで。

業務内容:入力と書類チェック業務。

時間:9:00~18:00

勤務日:平日

時給:1050円

勤務地:沖縄県うるま市州崎

交通費:支給あり

最寄り駅:無料駐車場完備

ホームページよりエントリー可能です。

A-Frameのご紹介


エイブリッジでは、AR、VRのアプリ開発を行っています。
最近ではOcculus Quest2など安価で高性能な端末が販売されるようになってきており、弊社にも開発のご相談をいただくことが多いです。
基本的にはプラットフォームを決めて、アプリを開発することが多いのですが
最近は「メタバース」というワードも流行って来ており、同じコンテンツをさまざまなプラットフォームで見れるようにしたい!という要望も増えております。

そういう時にうってつけのフレームワークが「A-Frame」というものがあります。
A-FrameはHTMLで3Dコンテンツが表示できるようになるフレームワークです。
A-Frameはブラウザで機能するので、iOS、Android、PC、VRデバイス上で動作するのでサーバーとコンテンツさえ用意すればマルチプラットフォームのアプリを開発することができます。

また、ブラウザベースということで品質が落ちるのでは?という懸念があると思いますがそんなことはありません!
VRデバイスでA-Frameで開発したサイトにアクセスすると、他のブラウザベースではない作り込まれたコンテンツと遜色ない体験ができるようになってます。

以下の手順で簡単に自分のHPに組み込むことができます。

<script src="https://aframe.io/releases/1.1.0/aframe.min.js"></script>

を組み込む。

<a-scene class="inpost" embedded>
            <a-entity light="type: directional; color: #EEE; intensity: 1" position="1 1 1"></a-entity>
            <a-entity
                geometry="primitive: box;"
                material="color: #FF0000; roughness: 0.5; metalness: 0.2;"
                position="0 1 -5"
                rotation="0 0 0"
                animation="property: rotation;
                            from: 0 360 0;
                            to: 0 0 0;
                            dir: alternate;
                            dur: 10000;
                            loop: true;
                            easing: easeInOutSine">
            </a-entity>

            <a-plane position="0 0 -5" rotation="-90 0 0" width="10" height="10" color="#CCCCCC"></a-plane>
            <a-sky color="#4444EE"></a-sky>
</a-scene>

をbodyタグ内に追加する。

——————

以下、簡単に解説させていただきます。

<a-scene class="inpost" embedded>

A-Frame用のシーンを定義するタグになります。
このタグ内にコンテンツを書き込むことになります。

<a-entity light="type: directional; color: #EEE; intensity: 1" position="1 1 1"></a-entity>

ライト用のタグになります。
ライトはコンテンツの見え方に影響してきます。
現実世界の照明と同じです。

<a-entity
                geometry="primitive: box;"
                material="color: #FF0000; roughness: 0.5; metalness: 0.2;"
                position="0 1 -5"
                rotation="0 0 0"
                animation="property: rotation;
                            from: 0 360 0;
                            to: 0 0 0;
                            dir: alternate;
                            dur: 10000;
                            loop: true;
                            easing: easeInOutSine">
</a-entity>

上記は、画面中央に表示されているBOXになります。
パラメーターの詳細などは公式サイトのリファレンスを参照してください。
今回は、アニメーションを設定しています。

サンプルを下記URLで公開しています。
https://abridge-co.jp/test/example.blade.php

——————

A-Frame公式サイト
https://aframe.io/

未経験OK!ITエンジニア希望者募集!

エイブリッジ沖縄オフィスでは、ITエンジニアを希望する方を募集しております。

未経験からITエンジニアを育成しており、コールセンターやデータ入力業務の派遣社員から、ITエンジニアへキャリアチェンジする方増えています!

今回は那覇市エリア、中部エリアで合計10名の募集です!

IT系業務で経験を積みながら、研修でスキルを積みましょう!

事例1

コールセンター → Webエンジニア 学習期間10ヵ月

データ入力業務 → 金融システム開発エンジニア 学習期間12か月

それぞれに寄り添ったキャリアサポート制度もあります。

無料説明会随時開催中!

詳しくはホームページよりお問い合わせください!

Code Bridgeを受講して3名エンジニアデビュー

10月よりCodebridgeを受講していた方々3名が新たにエンジニアデビューしました!

お仕事しながら、6ヵ月~12ヵ月の学習を行い、未経験からエンジニアデビューしました!

Web系のお仕事に従事することになりましたので、現在はWebに関する知識を習得しています。

年齢も25歳~34歳と、20代、30代の方々が続々キャリアチェンジをしております。

エンジニアを目指す方々へ、沖縄県でも30代からのエンジニアデビューは可能です!

進化する教材とIT×人材の実績豊富なエイブリッジでエンジニアを目指しませんか。

未経験から、エンジニア、プログラマ転職、プログラミング学習はエイブリッジ!

無料カウンセリング&説明会を実施中!

詳しくはホームページもしくは専用サイトよりお問い合わせください。

https://abridge-co.jp/contact.html
https://abridge-co.jp/codebridge/

学生向けオンラインインターンシップ開催!


=======
24卒以降の就職を考えている方を対象にしたインターンシップ(就業体験)を8月20日にオンラインで実施しました!
このコロナ禍でなかなか就職活動をすることが難しい学生の皆さんのためにオンラインを活用することでIT業界に興味を持って頂きたいという思いで、この度、実施いたしました。
参加者の感想は・・・
Aさん
Bさん
【参加資格】
就職を希望している沖縄県在住の学生の方
【参加費】
無料
【スケジュール】
会社概要(15分)
HTML/CSS/JavaScriptの超基礎(1時間)
ストップウォッチ作成(2時間)
休憩を含めて計4時間
現在でも募集しておりますので、この機会にITの仕事を身近に感じて頂けると、私たちは満足です!
【問い合わせ先】
株式会社エイブリッジ インターンシップ担当 
it-okinawa@abridge-co.jp
=====