#laravel 5.8 named resource routes
Explore tagged Tumblr posts
laravelvuejs · 6 years ago
Text
Laravel 5.8 Tutorial From Scratch - e24 - URL Helpers - Laravel
Laravel 5.8 Tutorial From Scratch – e24 – URL Helpers – Laravel
Laravel 5.8 Tutorial From Scratch – e24 – URL Helpers – Laravel
[ad_1]
In this episode, we explore the 3 URL Helpers offered by Laravel out of the box and refactor our project to use them.
For the best experience, follow along in our interactive school at https://www.coderstape.com
Resources Course Source Code https://github.com/coderstape/laravel-58-from-scratch
Hit us up on Twitter with any…
View On WordPress
0 notes
tak4hir0 · 6 years ago
Link
はじめに 皆様こんにちは。OPTiM新卒1年目エンジニアの青木です。 前回は早押しボタンなんかを作っていました。 tech-blog.optim.co.jp 今回は、PHP フレームワークの Laravel を、PostgreSQL と Vue.js と組み合わせて作成する TODO アプリを通して紹介します。 このフレームワークらはこちらの記事でも密かに利用しています。 tech-blog.optim.co.jp OPTiMではあまり利用されていませんが、一部のアプリケーションで実利用されている箇所もございます。 PHPは昔のイメージからかなり避けられていていますが...今のPHPとそのフレームワークはすごく発展していてとても使いやすいので是非使っていただきたい!という気持ちがあります。 ですが、現状はあまり利用していただけなくて個人的には悲しい気持ちでいっぱいです。 そんなPHPですが、フレームワーク(LaravelやFuelPHPなど)を利用することにより未利用時よりも高速かつ安全に開発することができます。 そんなフレームワークの紹介を「TODOリストアプリケーション」を作りながら見ていきましょう。 PHPフレームワーク「Laravel」 今回ご紹介するのはPHPフレームワークの「Laravel」です。 Laravel - The PHP Framework For Web Artisans laravel.jp フレームワークの仕様に乗っかって開発することによりかなり安全で可用性のあるアプリケーションの開発が容易になります。 個人的にLaravelのいいところはズバリ 爆速安全開発 です。 本当に手早くWebアプリケーションが作れます。 今まで数人で作業していたものをたった一人で1週間もあればかなり強い物が作れます! 2019年8月5日現在のLaravel最新バージョンは「5.8」で「5.7」のマイナーアップデートとなっています。 Laravelは奇数バージョンがメインとなっており、中でもLTSとなっているのは「5.1」「5.5」となっています。セキュリティフィックス期限はLTSで3年間、一般的なリリースについては1年間のサポートとメンテナンスがされています。 このように、言語仕様だけではカバーできないセキュリティの担保もフレームワークが担ってくれることにより、PHP5以前の時代よりも遥かに強くなっています。 ここで、Googleトレンドより注目度を比較してみましょう。 実は代表的なWebフレームワークの「Ruby on Rails」や「Django」などよりもLaravelの注目度が上がってきています。 日本ではダントツで「Ruby on Rails」が多く見られます。 海外での「Laravel」の注目度が上がってきているようですね。 Laravelは機能がとても豊富です。ですからファイルサイズ的にも大きくなりますし、環境にも負担がかかってしまいます。 そんな時は「Lumen」を利用しましょう。ここではあまり解説しませんが、「Lumen」は「Laravel」の軽量版として開発されています。 とっても雑に説明するとNode.jsのExpressのような感じですね。 さて、前置きが長くなりましたが、本題に移りたいと思います。 今回の目標 PHPフレームワークLaravelで、DBを使用したSPA(Single Page Application)のTODOアプリを作ります。 またログイン認証によるユーザ管理も同時に行っていきます。 完成形 この記事の最後にはこのようなアプリケーションが出来上がります。 ユーザの新規登録・ログイン・ログアウト ログインユーザごとのTODOの表示・追加・更新・削除 最低限のView 使用する技術 PHP Laravel Vue.js PostgreSQL Docker 導入・環境構築 PHPの導入 LaravelでバージョンごとにPHPに対する要件が決められています。 現時点でのPHPの最新バージョンは「7.3.8」 現時点でのLaravelの最新バージョンは「5.8.17�� Laravel「5.8.*」で求められるPHPの要件は以下のとおりです。 = 7.1.3 BCMath PHP拡張 Ctype PHP拡張 JSON PHP拡張 Mbstring PHP拡張 OpenSSL PHP拡張 PDO PHP拡張 Tokenizer PHP拡張 XML PHP拡張 これに応じてPHPの導入を行いましょう。 ちなみにHomebrewでインストールした場合は「7.3.7」がインストールされました。こちらのバージョンでも要件を満たしておりますので大きな問題はありません。 ※ただしセキュリティ等の関係上最新バージョンを使うに越したことはありません。下調べは慎重にかつ念入りに行いましょう。 Composerの導入 Laravelを構築するためのパッケージマネージャが必要となります。 PHPの代表的なパッケージマネージャである「Composer」を導入しましょう。 curl -sS https://getcomposer.org/installer | php sudo mv composer.phar /usr/local/bin/composer composer config -g repositories.packagist composer https://packagist.jp HelloWorld(プロジェクトの作成) さて、いよいよプロジェクトを作成していきます。 「Laravel」では以下の1コマンドのみでプロジェクトの新規作成が行えます。 $ composer create-project laravel/laravel Techblog_sample ビルトインサーバの起動 Laravelに標準搭載されているartisanコマンドでビルトインサーバを起動してみましょう。 簡単ですね。環境構築後からはたった3コマンドしか叩いていませんが、HelloWorld同等の画面まで出せました。 データベースの導入とAuth実装 データベースの導入を行います。 今回はPostgreSQLを利用していますが、MySQLやSQLiteなども対応しています。 PostgreSQL導入 (Docker使用) LaravelとDBの接続 Auth(認証)導入 PostgreSQL導入 (Docker使用) PostgreSQLを構築します。 こちらは皆様のお好きな方法で構築していただいて構いません。 あくまで一例として記載いたします。 データベースを開発機にそのまま構築しても良いですが、比較的構築の簡単なdocker-composeを利用して構築をしたいと思います。 docker-compose.yml version: '2' services: db: image: postgres:11-alpine ports: - "15432:5432" environment: POSTGRES_USER: "postgres" POSTGRES_PASSWORD: "password" POSTGRES_DB: "techblog" 5432/tcp データベースの構築が終わりました。 LaravelとDBの接続 LaravelとDBサーバを接続します。 こちらはデフォルトで環境変数から接続情報を取得するようになっており、環境変数を変更することにより接続情報を更新できます。 また、環境変数に存在しなかった場合はディレクトリに存在する.envファイルを参照するようになっています。 .envファイルを以下のように変更してください。各自で構築された場合は構築した際の情報に都度変更してください。 .env ... DB_CONNECTION=pgsql DB_HOST=127.0.0.1 DB_PORT=15432 DB_DATABASE=techblog DB_USERNAME=postgres DB_PASSWORD=password ... 接続確認は次のAuth作成時に確認��ます。 Auth(認証)導入 LaravelにAuth(認証)を追加します。 至って簡単です。 $ php artisan make:auth Authentication scaffolding generated successfully. 以上です。 試しにビルトインサーバを立ち上げ、確認をしてみましょう。 お気づきの方が既にいらっしゃるかもしれませんが、右上にログインボタンなどが現れています。 試しにログインボタンを押してみましょう。 ログイン画面が構築されています。 たった1コマンドで ログイン画面 新規登録画面 パスワードリセット画面 が実装されます。 素晴らしいですね。 ただ、いまのままですとDBにアクセス出来ていません。 以下のコマンドを入力してマイグレーションを行いましょう。 $ php artisan migrate Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table これで新規登録などが出来るようになりました。 デフォルトではセッションでログイン情報を管理します。 コマンドライン(Tinker)でDBデータ確認 artisanコマンドによるデータ確認を行ってみたいと思います。 Laravelにはデフォルトでtinkerと呼ばれる対話型ツールが存在します。 こちらを利用することにより、ソースコードにする前に動作確認が出来ます。 また、Laravelに読み込まれるモジュール等が手動で読み込める状態になっているので、Laravelで開発する際はおすすめの動作確認方法です。 LaravelからDBにアクセスするために、��エリビルダを利用します。 作業をするそのまえに データベースにデータを入れるため、一旦画面上から新規登録を行ってみましょう。 しっかりと新規登録されていますね。 また、こういった事もデバッグとして利用できます。 false コマンドライン上でセッションも利用できるということですね。 独自で作成したサービスモジュールなんかも利用出来るので、是非デバッグなどにご利用ください。 テーブル設計 TODOアプリケーションを制作するに当たってテーブルを構築しなければいけません。 今回は1ユーザが複数のTODOを持てるように設計します。 テーブル設計は前項でも利用した Migration を利用します。 $ php artisan make:migration create_todos_table Created Migration: 2019_08_05_065824_create_todos_table database/migrations/2019_08_05_065824_create_todos_table.php <?php public function up() { Schema::create('todos', function (Blueprint $table) { $tablebigIncrements('id'); $tablestring('todo'); // この行を追加 $tableinteger('user_id'); $tabletimestamps(); }); } public function down() { Schema::dropIfExists('todos'); } 作成できたら、マイグレーションを実行してデータベースに反映させましょう。 $ php artisan migrate Migrating: 2019_08_05_065824_create_todos_table Migrated: 2019_08_05_065824_create_todos_table これで新たにテーブルが作成されました。 ここまで ここまではLaravelの導入、環境構築、Authの導入を行いました。 PHPでのコーディングをほぼ無しとしてここまで作れました。 次は、実際にルーティングやMVCなど、Laravelのメイン機能についてご紹介していきます LaravelのMVCとその他の機能 ルーティング コントローラ(C) ビュー(V) モデル(M) ミドルウェア ログイン後のリダイレクト先 実装するページ Authは自動で実装されるので割愛しています。 TODOアプリケーションはSPAで作成し、APIを叩いて操作を行います。 ルーティング いよいよ基盤が完成したので、ルーティングの説明に入ります。 Laravelのルーティングは routes ディレクトリ内に存在し、それぞれのファイルは用途によってプレフィックスが初期でつけられていたりします。 今回は web.php を編集していきましょう。 routes/web.php <?php Route::get('/todo', function () { return "このページはアプリケーションのページです"; }); このルーティングを追加すると、画像のように表示されます。 今回はSPAなのであまり使いませんが、SPAではないアプリケーションを作る場合は基本的にここに記述していきます。 また、 api.php に作成することで自動的に/api/のプレフィックスが付きます。任意のプレフィックスに変更したい場合は app/Provider/RouteServiceProvider.php を変更しましょう。 さて、このままではクロージャがどんどん膨れ上がって行ってしまいますので、次の工程でしっかりと分業してあげます。 コントローラ web.php がロジックでどんどん汚染されていくので、コントローラと呼ばれるもので分業していきましょう。 下記のコマンドでコントローラが自動生成されます。 $ php artisan make:controller TodoController Controller created successfully. TodoController.phpの中にメソッドを生やし、web.phpから読み込んでみましょう。 app/Http/Controllers/TodoController.php <?php namespace App\Http\Controllers; use Illuminate\Http\Request; class TodoController extends Controller { public function index() { return "コントローラからこんにちは"; } } routes/web.php <?php Route::get('/todo',TodoController::class . "@index"); 実装が出来たら、php artisan serveで見てみましょう。 いかがでしょうか。 コントローラに分割することによってルーティングによる画面や機能別にロジックを記述することが可能になりました。 ビュー では、ビューを表示してみましょう。 Laravelのビューは強力なbladeテンプレートエンジンを含んでいます。 コントローラから変数を渡し、bladeテンプレートエンジンにより表示してみます。 $ touch resources/views/todo.blade.php resources/views/todo.blade.php <?php @extends('layouts.app') @section('content') <div class="container" <div class="row justify-content-center" <h2TODO アプリケーション</h2 </div </div @endsection @から始まるものはbladeテンプレートエンジン特有のメソッドです。 今回は既に用意されているレイアウトデザインを利用します。 上記のファイル作成が終われば、TodoController.phpを変更していきます。 view()メソッドにbladeテンプレートのファイル名を記入すればviewが帰ります。 app/Http/Controllers/TodoController.php <?php namespace App\Http\Controllers; use Illuminate\Http\Request; class TodoController extends Controller { public function index() { return view('todo'); } } モデル Eloquent ORM と呼ばれる非常にシンプルかつ高機能なORMがLaravelでは提供されています。 ここでいうモデルとはEloquentモデルのことであり、Eloquent ORMの利点を最大限生かされたものです。 まずはじめに、モデルを作成しましょう。 $ php artisan make:model Todo 基本的にはこれで終わりです。 テーブル名が todos であれば、モデル名は Todo モデル名が Sample であれば、テーブル名は samples この方式で決定しています。 仮にテーブル名とモデル名を変更したい場合はモデルファイル(app/モデル名.php)のクラス変数に <?php protected $table = 'テーブル名'; と指定することが出来ます。 では、確認してみましょう。 Illuminate\Database\Eloquent\Collection {#2981 all: [ App\Todo {#2980 id: 2, todo: "TestTest", user_id: 1, created_at: null, updated_at: null, }, ], } insert文で追加してみました。 しっかりと反映されていますね。 モデル(リレーションの定義) モデルにリレーションを定義することが出来ます。 かなり便利なので是非使っていきたいところです。 今回のリレーション内容を再確認してみましょう。 users.id と todos.user_id が紐付いていますね。 これをユーザ側のモデルからtodosを参照出来るようにモデルに定義していきます。 app/User.php <?php class User extends Authenticatable { ... 省略 public function todos(){ return $thishasMany('App\Todo'); } } これで実装が終わりです。 Tinkerで確認してみましょう。 を利用することでユーザに紐付いたTodosテーブルのレコードを受け取ることが出来ます。 ミドルウェア ルーティングする際に、特定のページらに一定の操作を与えたい。 などのニーズに応えるのがミドルウェアです。 現状問題となっているのは、ログインしていなくても/todoにアクセス出来てしまうということです。 ログインしていないのにTodo画面へ遷移されてはとても困ります。ユーザ毎に情報を表示するのにそのユーザが誰かわからないのでエラーが出てしまいます。 かといって、毎ページ同じ動作を記述するのはとてもスマートとは言えません。 そこで、ミドルウェアの登場です。 説明よりやってみたほうが早いので、コードを記述します。 routes/web.php <?php Route::group(["middleware""auth"],function(){ Route::get('/todo',TodoController::class . "@index"); }); Route::groupの第2引数のクロージャに先程の /todo を入れてみましょう。 すると、/todoにアクセスしようとするとログイン画面へリダイレクトします。これでログイン判定が出来るのでいちいちコントローラ内部にロジックを書くことはありません。 また、ミドルウェアは自作することが出来ます。後ほどAPI作成の際にひつようになりますのでそちらで詳しく解説いたします。 ログイン後のリダイレクト先 現状、新規登録・ログイン後に /home へリダイレクトしていると思います。 これはLoginController.php などが自動的にリダイレクト処理を行っているからです。 今回は/homeを利用しませんので、削除する方法を記載します。 app/Http/Controllers/Auth/LoginController.php app/Http/Controllers/Auth/RegisterController.php app/Http/Controllers/Auth/ResetPasswordController.php app/Http/Controllers/Auth/VerificationController.php - protected $redirectTo = '/home'; + protected $redirectTo = '/todo'; resources/views/home.blade.php 削除 routes/web.php name('home'); これでログイン後は /todo へリダイレクトします。 TODOアプリケーションのメイン機能実装(サーバーサイド実装) APIの実装 まずはじめにAPIの実装を行います。 今回のAPIでの認証は、セッションで行いたいと思います。 機能一覧 TODOアプリケーションを作成するに当たって、APIの機能を洗い出します。 こちらの機能を作成していこうと思います。 機能実装 まず、コントローラに定義します。 app/Http/Controllers/TodoController.php <?php use App\Todo; use Illuminate\Support\Facades\Auth; class TodoController extends Controller { ... 省略 public function get(){ // 全件表示 } public function post(){ // 1件追加 } public function delete(){ // 1件削除 } public function update(){ // 1件更新 } } 次に、ルーターに追加していきます。api.phpになっているので注意してください。 route/api.php <?php Route::get('/todo','TodoController@get'); Route::post('/todo','TodoController@post'); Route::delete('/todo/{id}','TodoController@delete'); Route::put('/todo/{id}','TodoController@update'); 次は確認をはさみつつ、それぞれの機能を実装していきます。 全件表示 <?php public function get(){ return response()json(Auth::user()todos()get()); } モデルの説明の時に行ったものと同じです。 1件追加 <?php public function post(Request $request){ $todo = new Todo(); $todotodo = $requesttodo; $todouser_id = Auth::id(); $todosave(); return response("OK", 200); } モデルでインスタンスを生成し、それぞれに値を当てはめてから最後にセーブをすればSQLを発行して追加処理を行ってくれます。 Todo::insert()でも同じことが行なえます。 1件削除 <?php public function delete($id){ Todo::find($id)delete(); return response("OK", 200);; } Todoのインスタンスにdeleteメソッドがありますので、それを実行すれば削除できます。 1件更新 <?php public function update(Request $request,$id){ $todo = Todo::find($id); $todotodo = $requesttodo; $todosave(); return response("OK", 200); } 追加の時とほぼ同じで、findでtodoのインスタンスを持ってくるだけで出来上がります。 APIのAuth実装 このままでは誰でもAPIにアクセスできてしまいます。 しかもコード内部で Auth::を利用しているので、ログインしていないユーザがアクセスするとエラーが発生します。 ここではそのAuth(認証)をAPIからでも行えるように変更、追記していきます。 セッションを有効化 APIではデフォルトでAuthorizedTokenを利用するような設計になっています。 今回はセッションを利用するので以下のように変更します。 app/Http/Kernel.php <?php // 省略 protected $middlewareGroups = [ 'web' [ \App\Http\Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, // \Illuminate\Session\Middleware\AuthenticateSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, \App\Http\Middleware\VerifyCsrfToken::class, \Illuminate\Routing\Middleware\SubstituteBindings::class, ], 'api' [ // ここを追加 \App\Http\Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, \App\Http\Middleware\VerifyCsrfToken::class, \Illuminate\Routing\Middleware\SubstituteBindings::class, // ここまで追加 'throttle:60,1', 'bindings', ], ]; // 省略 これでセッションが有効になります。 ミドルウェアの作成 デフォルトで備わっているAuthのミドルウェアはビューに最適化されており、ログインせずにミドルウェアに到達すると /login にリダイレクトされてしまいます。 APIではリダイレクトではなく エラーメッセージ が帰ってくることを期待します。 ですのでミドルウェアを自作します。 $ php artisan make:middleware AuthApi app/Http/Middleware/AuthApi.php <?php use Illuminate\Support\Facades\Auth; // 省略 public function handle($request, Closure $next) { if (!Auth::check()) return response("",401,["Content-type: application/json"]); return $next($request); } use ...Auth の行が必要ですので注意してください。 app/Http/Kernel.php <?php // 省略 protected $routeMiddleware = [ // 省略 'auth.api' \App\Http\Middleware\AuthApi::class, ]; これでミドルウェアの実装完了です。 実装 先程作成したtodoのルーターに変更を加えていきます。 route/api.php <?php Route::group(["middleware" "auth.api"],function(){ Route::get('/todo','TodoController@get'); Route::post('/todo','TodoController@post'); Route::delete('/todo/{id}','TodoController@delete'); Route::put('/todo/{id}','TodoController@update'); }); これでログインしていないと401エラーを返すことになります。 フロントの実装 いよいよフロントの実装に入ります。 ここではVue.jsを利用したSPAで制作していきたいと思います。 VueJSの構築 LaravelはデフォルトでVueJSが導入されていて、 既にExampleファイルも構築されています。 Webpackも何も書かなくても初期導入されています。 したがって、npmインストールを行い、Viewを少し変更するだけでVueJSを導入できます。 $ npm i $ npm run dev $ npm run watch # ファイルの変更時、自動的にコンパイルが走る resources/views/todo.blade.php @extends('layouts.app') @section('content') <div class="container" <div class="row justify-content-center" <h2TODO アプリケーション</h2 <example-component</example-component </div </div @endsection を追加することでVue.jsの導入は完了です。 APIを叩くリクエストモジュールを作成 APIを叩く際、数が多くなってくるとごちゃごちゃになってくるので、APIを叩く機能は別に作成します。 resources/js/api.js "use strict" const send = (method,uri,data={} { const url = 'http://127.0.0.1:8000' + uri return new{ var xhr = new XMLHttpRequest(); xhr.open(method, url); xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8" { try{ const res_json = JSON.parse(xhr.responseText) resolve(res_json) }catch (e) { resolve(xhr.responseText) } } { console.log(xhr.status); console.log("error!"); }; xhr.send(data); }) } const api = { getTodoList(){ return send("GET","/api/todo"); }, postTodo(todo){ return send("POST","/api/todo",todo); }, updateTodo(id,todo){ return send("PUT","/api/todo/" + id,todo); }, deleteTodo(id,data){ return send("DELETE","/api/todo/" + id,data); } } export default api APIを叩くためのメソッド send を用意して、下段にAPIをリストのように記述することで新たにAPIが増えても追加しやすいようにします。 コンポーネントの実装 では、駆け足でコンポーネントを作成していきましょう。 今回はLaravelの紹介なのでフロント実装の部分は大幅にカットします。 以下のソースコードをまるごとコピーすれば動作すると思います。 resources/js/components/ExampleComponent.vue <template <div class="container" <div class="row justify-content-center" <div class="col-md-8" <div class="card" <div class="form-group" <input type="text" class="form-control" id="inputtodo" v-model="todo_form" <button type="button" class="btn btn-primary" @click="addTodo"Add</button </div </div <div class="card" v-for="todo in todos" <div class="card-header" <button type="button" class="btn btn-danger" @click="deleteTodo(todo.id)"Delete</button <button type="button" class="btn btn-info" @click="updateTodo(todo.id)"Update</button <input type="text" class="form-control" id="todo" v-model="todo.todo" </div </div </div </div </div </template <script import api from "../api.js" export default { data(){ return { active_todo: null, todo_form:"", todos:[] } }, methods:{ addTodo(){ let data = {todo:this.todo_form} data._token = document.getElementsByName('csrf-token')[0].content; api.postTodo(JSON.stringify(data)).then((){ this.getTodoList() }) }, deleteTodo(id){ let data = {} data._token = document.getElementsByName('csrf-token')[0].content; api.deleteTodo(id,JSON.stringify(data)).then((){ this.getTodoList() }) }, updateTodo(id){ let data = {todo:this.todos.filter((v){return v.id === id})[0].todo} data._token = document.getElementsByName('csrf-token')[0].content; api.updateTodo(id,JSON.stringify(data)).then((){ this.getTodoList() }) }, getTodoList(){ api.getTodoList().then((result){ this.todos = result }) } }, mounted() { this.getTodoList() console.log('Component mounted.') } } </script それぞれの機能ごとに method を用意して、dataやv-modelなどを駆使してAPIを叩きます。 APIを叩いた後はすかさずthis.getTodoListを行っていますが、これは変更を適応するためです。 完成 TODOリストが完成しました。 最後に いかがでしたでしょうか。 記事が長くなってしまいましたが、実際に記述したソースコードはほんの一部分だけです。 こちらにアプリケーションのソースコードを載せております。 GitHub - optim-corp/techblog-laravel-todo-sample Auth(認証)やAPIの作成、SPAの実装までこの量で出来てしまいます。 この記事の通りに実装を行えば上記のTodoアプリケーションが出来上がりますが、バリデーションチェック等の エラーハンドリングを全く行っておりません(特にAPI部分) ので、ご注意ください。 最後になりましたが、「Laravelを使って爆速Webアプリケーション開発を行っていこう!」という言葉を残して締めくくりたいと思います。 ありがとうございました。�� OPTiMでは様々な分野で活躍できるエンジニアを募集しております。 今回のようなWebアプリケーションも然り、機械学習やクラウド系インフラ周りまであらゆる分野で活躍出来る場があります! 興味がある方は是非弊社採用ページにてご覧ください! www.optim.co.jp また、夏季インターンシップも募集しておりますので、合わせてご覧ください。 www.optim.co.jp
0 notes