SlideShare uma empresa Scribd logo
1 de 70
Baixar para ler offline
実践Laravel
yuuki takezawa (ytake)
istyle inc.
profile
• 竹澤 有貴 / ytake
• 株式会社アイスタイル
• twitter https://twitter.com/ex_takezawa
• facebook https://www.facebook.com/yuuki.takezawa
• github https://github.com/ytake
author
Agenda
• About Dependency Injection
• 堅実なアプリケーションにするBest Practice
Dependency Injection
Interface vs Concrete
class Process
{
protected $ls;
public function __construct()
{
$this->ls = new Ls();
}
public function execute()
{
}
}
class Ls
{
public function invoke(): string
{
return 'ls';
}
}
このProcessクラスは、
lsに依存
他のコマンドを実装する場合、
OO Processクラスをたくさん
作成しなければならない
Lsクラスの実行メソッドはinvoke他のクラ
スの実行メソッドは違うかもしれない
Interface vs Concrete
class Command
{
public function process()
{
(new Process())->execute();
(new HogeProcess())->handle();
(new FugaProcess())->dispatch();
}
} クラスによって利用方法が異なる
各コマンドによる利用方法の違いを
知っていなければ利用できない
Interface vs Concrete
interface ProcessCommandInterface
{
/**
* @return string
*/
public function command(): string;
}
コマンドを提供
このインターフェースを実装するクラスは、
このメソッドを実装しなければならない
Interface vs Concrete
class Ls implements ProcessCommandInterface
{
public function command(): string
{
return 'ls';
}
}
Interface vs Concrete
class Process
{
protected $command;
public function __construct(
ProcessCommandInterface $command
) {
$this->command = $command;
}
public function execute()
{
$this->command->command();
}
}
このインターフェースを
実装したクラスであればなんでも良い
このメソッドは必ず存在する
Interface vs Concrete
class Command
{
protected $commandClass = [
Ls::class,
Rm::class,
];
public function process()
{
foreach($this->commandClass as $class) {
(new Process(new $class()))->execute();
}
}
}
一括で操作可能
外部から渡されるクラスによって
振る舞いが変わる
設定値として外から指定することも可
Laravel Service Container
• 外から実行クラスを指定する機能を元に設計
• インターフェースと具象クラスの指定は
Service Providerに記載
• フレームワークの機能はこの手法で拡張
class Hoge
{
public $int = 1;
}
class HogeFugaPiyo
{
protected $hoge;
public function __construct(Hoge $hoge)
{
$this->hoge = $hoge;
}
}
Laravelのプロジェクト内のクラスであれば
どのクラスのコンストラクタに記述しても自動的
にインスタンスが!
型宣言をすると、
リフレクションを使って自動的に解決
インスタンスの生成方法を指定
// Hogeと書いてあったらHogeをください
$this->app->bind(Hoge::class, function () {
return new Hoge;
});
$this->app->bind(Hoge::class);
// singletonでください
$this->app->singleton(Hoge::class);
インスタンスの生成方法を指定
引数が必要な場合
class Fuga
{
private $arg;
public function __construct(int $arg)
{
$this->arg = $arg;
}
}
型宣言ではない場合
解決できないのでしょうか?
$this->app->bind(Fuga::class, function () {
return new Fuga(1);
});
無名関数を利用することで、
クラスが解決されるまで、
Fugaは生成されません
インスタンスの生成方法を指定
混合
class Piyo
{
private $hoge;
private $fuga;
public function __construct(Hoge $hoge, Fuga $fuga)
{
$this->hoge = $hoge;
$this->fuga = $fuga;
}
}
複数のクラスがある場合
$this->app->bind(Hoge::class, function () {
return new Hoge;
});
$this->app->bind(Fuga::class, function () {
return new Fuga(1);
});
// 場合によってはこんなのも
$this->app->bind(
Fuga::class,
function (Application $app) {
return new Fuga($app->make(‘nanika’));
});
bindメソッドの場合は、
フレームワーク本体が引数
クラス、またはサービス名を指定
インスタンス生成時に
特定の何かをしたい
class HogeFugaPiyo
{
private $name = ‘’;
public function __construct(Hoge $hoge)
{
$this->hoge = $hoge;
}
public function setName(string $name)
{
$this->name = $name;
}
}
$this->app->extend(
HogeFugaPiyo::class,
function (HogeFugaPiyo $hoge) {
$hoge->setName(“hoge”);
return $hoge;
});
* 他にもあります
インスタンス生成時に
特定の処理を実行させられます
特定のクラスを継承したクラスの
インスタンスが生成された時に
なにかしたい
abstract class AbstractHoge
{
private $name = ‘abstract’;
public function setName(string $name)
{
$this->name = $name;
}
}
class Hoge extends AbstractHoge
{
}
$this->app->resolving(
AbstractHoge::class,
function (AbstractHoge $abstractHoge) {
$abstractHoge->setName(‘aaaaa’);
return $abstractHoge;
});
FormRequestはこの手法でValidationを
実行します
疎結合にしたい
// constructorにinterfaceを書きましょう
$this->app->bind(HogeInterface::class, Hoge::class);
何かの条件で返却される
インスタンスを変更したい
use Illuminate¥Support¥Manager;
class StringManager extends Manager
{
protected $driver = ‘hoge’;
public function getDefaultDriver()
{
return $this->driver;
}
protected function createHogeDriver()
{
return ‘hoge dayo’;
}
protected function createFugaDriver()
{
return ‘fuga dayo’;
}
}
// constructorでManagerクラス 型宣言
$this->app->bind(
StringManager::class,
function(Application $app) {
return new StringManager($app);
});
ちょっとだけ上級者向けですが、
オブジェクト指向のデザインパターンにも
ある解決手法です
protected $manager;
public function __construct(StringManager $manager)
{
$this->manager = $manager;
}
public function __invoke($id)
{
$manager = $this->manager->driver(‘hoge’);
if($id === 1) {
$manager = $this->manager->driver(‘fuga’);
}
dd($manager);
}
Facade, helper
class HogeFugaPiyo
{
public function invoke()
{
¥App::make(‘aaa’);
app(‘bbb’);
}
}
依存解決はできますが、
このクラスそのものが何に依存しているかわか
りますか?
class HogeFugaPiyo
{
public function __construct(Application $app)
{
$this->app = $app;
}
}
ファサードやヘルパー関数は、
実態に置き換えるとこうなります
堅実なアプリケーションへの道
要件を正しく理解する
• このアプリケーションはだれのためのものか
• 価値はなにか
• 目的はなにか
サービス要件・システム要件
• ユーザーは自分のTODOを加えることができる
• 自分のTODO一覧を見ることができる
• TODO一覧は自分以外は見ることができない
• TODOリストはデータベースで管理する
• キャッシュストレージにmemcahcedを使う
サービス要件に合わせたクラスを考える
• 登場する主要なものを型として定義
-> 配列は可変のため保証されない
• チームで開発する場合は、便利さよりも
仕様の理解と、コードがサービス理解を促進すること
• 一つでなんでもできるメソッドは、複雑
データベースの戻り値を堅実に
use App¥Item;
final class IndexController extends Controller
{
public function __invoke()
{
foreach(Item::all() as $item) {
$item->item_id;
}
}
}
データベースのカラムとして
返ってきますが、
アクセス可能なプロパティは、
テーブル構造を知っている必要があります
データベースの戻り値を堅実に
trait QueryPrepared
{
/** @var string */
protected $fetchStyleClass = '';
public function fetchClass(string $class): self
{
$this->fetchStyleClass = $class;
return $this;
}
protected function prepared(PDOStatement $statement): PDOStatement
{
$statement->setFetchMode($this->fetchMode);
if (!empty($this->fetchStyleClass)) {
$statement->setFetchMode(¥PDO::FETCH_CLASS, $this->fetchStyleClass);
}
return $statement;
}
}
PDOの機能を使いこなす!
データベースの戻り値を堅実に
final class SqliteConnection extends ¥Illuminate¥Database¥SQLiteConnection
{
use QueryPrepared;
}
拡張してメソッドを上書き
データベースの戻り値を堅実に
public function register()
{
/** @var DatabaseManager $dbManager */
$dbManager = $this->app['db'];
$dbManager->extend('sqlite', function (array $config, $name) {
$connectior = new SQLiteConnector;
return new SqliteConnection($connectior->connect($config));
});
}
DatabaseManagerはdbという
サービス名で登録されている
driver名を上書きする
sqlite使用時に拡張したクラスを
利用するように変更する
単純な拡張なので影響は全くありません
データベースの戻り値を堅実に
class ItemMapper
{
private $item_id;
private $item_name;
public function getId(): string
{
return $this->item_id;
}
public function getName(): string
{
return $this->item_name;
}
}
カラム名のプロパティは
PDOが自動的にマッピング
このクラスからどうやって値に
アクセスできるかが一目瞭然
データベースの戻り値を堅実に
public function __invoke(DatabaseManager $db)
{
$connection = $db->connection();
$connection->fetchClass(ItemMapper::class);
dd($db->connection()->table('items')->get());
}
データベースの戻り値を堅実に
Collection {#180 ▼
#items: array:2 [▼
0 => ItemMapper {#182 ▼
-item_id: 1
-item_name: "item1"
-created_at: "2017-10-03 20:47:04"
}
1 => ItemMapper {#183 ▼
-item_id: 2
-item_name: "item2"
-created_at: "2017-10-03 20:47:14"
}
]
}
任意のオブジェクトとして返却
PDOの機能なので簡単!
リポジトリを抽象レイヤとして扱い堅実に
use App¥Item;
final class IndexController extends Controller
{
public function __invoke(
HogeRepository $repository
) {
$repository->all();
}
}
データベースへのアクセスを抽象化したもの
ただし返却は前述の通りカラム
リポジトリを抽象レイヤとして扱い堅実に
class HogeRepository
{
protected $item;
public function __construct(Item $item)
{
$this->item = $item;
}
public function all()
{
$result = [];
foreach($this->item->all() as $row) {
$result[] = new ItemMapper($row->item_id);
}
return $result;
}
}
Collection生成のように扱う
yieldしても良いでしょう
ビジネスロジックはクラスで表現する
class PaymentService
{
private $repository;
public function __construct(Repository $repository)
{
$this->repository = $repository;
}
public function pay(int $money)
{
$this->repository->add($money);
}
public function quantity(int $itemID)
{
// aaa
}
}
購入系ビジネスロジック?
依存が増えて複雑になりそう!
ここに処理がまとまってるから書こう!
あっという間に巨大クラス
ビジネスロジックはクラスで表現する
class MakePurchase
{
private $repository;
public function __construct(Repository $repository)
{
$this->repository = $repository;
}
public function run(int $money)
{
$this->repository->add($money);
}
}
役割をクラス名で表現
機能は一つのみ
ビジネスロジックはクラスで表現する
• バグがあっても小さい修正
• 機能拡張は比較的容易
• テストのしやすさ
• フレームワークの機能が最小限
依存関係は正しい?
class SampleController extends Controller
{
public function apply($id)
{
$validator = ¥Validator::make(¥Input::all(), ['content' => 'required']);
if ($validator->fails()) {
return redirect()->route('hoge')->withInput()->withErrors($validator);
}
try {
$result = User::find($id);
$requests = ¥Input::all();
$entry = Entry::create($requests);
¥Log::info('added entry', $requests);
return view('form')->with('user', $entry);
} catch (¥Exception $e) {
$session = ¥Session::get('from_values');
...
}
}
}
依存関係は正しい?
/**
* @param User $userModel
* @param Entry $entryModel
* @param FactoryContract $validator
* @param Request $request
* @param SessionManager $session
* @param LoggerInterface $log
* @param Redirector $redirect
*/
public function __construct(
User $userModel,
Entry $entryModel,
FactoryContract $validator,
Request $request,
SessionManager $session,
LoggerInterface $log,
Redirector $redirect
) {
$this->userModel = $userModel;
$this->entryModel = $entryModel;
$this->validator = $validator;
$this->request = $request;
$this->session = $session;
$this->log = $log;
$this->redirect = $redirect;
}
依存関係を正しく書くとこうなります
依存関係は正しい?
• Facade・ヘルパー関数は便利
• 便利だからといってあちこちで使うと・・・
複雑度が増します
• 便利なものは便利に使う
• なんでもできるクラスを作らない
ビジネスロジックか、システム都合か
class MailRegistration
{
public function run(Auth $auth)
{
app('log')->info('start!');
//---
try {
$auth->getAddress();
// なにか処理
} catch(¥RuntimeException $e) {
app('log')->info('error!');
}
app('log')->info('end!');
}
}
メール登録に認証クラスは必要か?
ビジネスロジックにログを取ってください
という要件はあるか?
フレームワーク依存
細分化
class MailRegistration
{
public function run(User $user)
{
$user->getAddress();
// なんたらかんたら
throw new RuntimeException('メール登録に失敗しました');
}
}
純粋なビジネスロジックのクラスに
フレームワークと結合する
class AppMailRegistration
{
protected $mailRegistration;
protected $logger;
public function __construct(
MailRegistration $mailRegistration,
LoggerInterface $logger
) {
$this->mailRegistration = $mailRegistration;
$this->logger = $logger;
}
public function run(User $user)
{
$this->logger->info('start');
$this->mailRegistration->run($user);
$this->logger->info('end!');
}
}
ビジネスロジックと結合
ビジネスロジックか、システム都合か
• フレームワークの機能はビジネスロジックではない!
• 細分化することでバージョンアップ、
または他のフレームワークへの乗り換えも簡単
• 不具合修正の範囲をとにかく小さく
• ユニットテスト!
best practice
バリデーションはどこで?
• 小さなアプリケーションならコントローラや、
データベースに入れる直前でもいいでしょう
• 少し大きなアプリケーションではFormRequestで
コントローラに到達する前に
• ミドルウェアでも良いですが、
何かを挟み込む処理で利用するものと思った方が吉
Queueってどう運用すれば良いの?
• supervisorでdaemonにしましょう
• console開きっぱなしはやめましょう
• 自作プロセス監視は自信があれば
本番稼働時の注意
• debugbarはrequire-devでインストールすること
内部の処理をダンプするため非常に遅い
• cookieの名前はデフォルトから必ず変えましょう!
• 本当にEloquentで大丈夫?
SQL知らなくて大丈夫?
でもLaravel遅いんでしょう?
• 普通のアプリケーションであれば1秒以内に応答
• 多くのボトルネックはDB設計
• 実は意外と気付かないフロントエンドのボトルネック
• バッチ処理?
バッチ処理が得意な言語で実装するなど、
Laravelだけでなんでもやろうとしないことも重要
Now Hiring!
@cosme及び関連会社における
各種サイトのシステムの開発・保守・運用と、
新サービスなど全社横断的なプロジェクトを支える
システム基盤の開発・保守・運用をお任せいたします。
@cosmeを知らなくても大丈夫!

Mais conteúdo relacionado

Mais procurados

サーバーサイドでの非同期処理で色々やったよ
サーバーサイドでの非同期処理で色々やったよサーバーサイドでの非同期処理で色々やったよ
サーバーサイドでの非同期処理で色々やったよkoji lin
 
ジェネリクスの基礎と応用 JJUG CCC 2012 Fall
ジェネリクスの基礎と応用 JJUG CCC 2012 Fallジェネリクスの基礎と応用 JJUG CCC 2012 Fall
ジェネリクスの基礎と応用 JJUG CCC 2012 Fallnagise
 
from old java to java8 - KanJava Edition
from old java to java8 - KanJava Editionfrom old java to java8 - KanJava Edition
from old java to java8 - KanJava Edition心 谷本
 
Scala の関数型プログラミングを支える技術
Scala の関数型プログラミングを支える技術Scala の関数型プログラミングを支える技術
Scala の関数型プログラミングを支える技術Naoki Aoyama
 
traitを使って楽したい話
traitを使って楽したい話traitを使って楽したい話
traitを使って楽したい話infinite_loop
 
Java SE 8 lambdaで変わる プログラミングスタイル
Java SE 8 lambdaで変わる プログラミングスタイルJava SE 8 lambdaで変わる プログラミングスタイル
Java SE 8 lambdaで変わる プログラミングスタイルなおき きしだ
 
Javaセキュアコーディングセミナー東京第3回演習の解説
Javaセキュアコーディングセミナー東京第3回演習の解説Javaセキュアコーディングセミナー東京第3回演習の解説
Javaセキュアコーディングセミナー東京第3回演習の解説JPCERT Coordination Center
 
Java8のstreamをダラダラまとめてみる
Java8のstreamをダラダラまとめてみるJava8のstreamをダラダラまとめてみる
Java8のstreamをダラダラまとめてみるShinya Mochida
 
Everyday Life with clojure.spec
Everyday Life with clojure.specEveryday Life with clojure.spec
Everyday Life with clojure.specKent Ohashi
 
Javaセキュアコーディングセミナー東京第4回講義
Javaセキュアコーディングセミナー東京第4回講義Javaセキュアコーディングセミナー東京第4回講義
Javaセキュアコーディングセミナー東京第4回講義JPCERT Coordination Center
 
社内Java8勉強会 ラムダ式とストリームAPI
社内Java8勉強会 ラムダ式とストリームAPI社内Java8勉強会 ラムダ式とストリームAPI
社内Java8勉強会 ラムダ式とストリームAPIAkihiro Ikezoe
 
BOF1-Scala02.pdf
BOF1-Scala02.pdfBOF1-Scala02.pdf
BOF1-Scala02.pdfHiroshi Ono
 

Mais procurados (19)

サーバーサイドでの非同期処理で色々やったよ
サーバーサイドでの非同期処理で色々やったよサーバーサイドでの非同期処理で色々やったよ
サーバーサイドでの非同期処理で色々やったよ
 
ジェネリクスの基礎と応用 JJUG CCC 2012 Fall
ジェネリクスの基礎と応用 JJUG CCC 2012 Fallジェネリクスの基礎と応用 JJUG CCC 2012 Fall
ジェネリクスの基礎と応用 JJUG CCC 2012 Fall
 
Project lambda
Project lambdaProject lambda
Project lambda
 
from old java to java8 - KanJava Edition
from old java to java8 - KanJava Editionfrom old java to java8 - KanJava Edition
from old java to java8 - KanJava Edition
 
Scala の関数型プログラミングを支える技術
Scala の関数型プログラミングを支える技術Scala の関数型プログラミングを支える技術
Scala の関数型プログラミングを支える技術
 
traitを使って楽したい話
traitを使って楽したい話traitを使って楽したい話
traitを使って楽したい話
 
Java8勉強会
Java8勉強会Java8勉強会
Java8勉強会
 
Java SE 8 lambdaで変わる プログラミングスタイル
Java SE 8 lambdaで変わる プログラミングスタイルJava SE 8 lambdaで変わる プログラミングスタイル
Java SE 8 lambdaで変わる プログラミングスタイル
 
Javaセキュアコーディングセミナー東京第3回演習の解説
Javaセキュアコーディングセミナー東京第3回演習の解説Javaセキュアコーディングセミナー東京第3回演習の解説
Javaセキュアコーディングセミナー東京第3回演習の解説
 
Java8のstreamをダラダラまとめてみる
Java8のstreamをダラダラまとめてみるJava8のstreamをダラダラまとめてみる
Java8のstreamをダラダラまとめてみる
 
Rpscala2011 0601
Rpscala2011 0601Rpscala2011 0601
Rpscala2011 0601
 
Everyday Life with clojure.spec
Everyday Life with clojure.specEveryday Life with clojure.spec
Everyday Life with clojure.spec
 
Introduction Xtend
Introduction XtendIntroduction Xtend
Introduction Xtend
 
Javaセキュアコーディングセミナー東京第4回講義
Javaセキュアコーディングセミナー東京第4回講義Javaセキュアコーディングセミナー東京第4回講義
Javaセキュアコーディングセミナー東京第4回講義
 
Entity Framework
Entity FrameworkEntity Framework
Entity Framework
 
社内Java8勉強会 ラムダ式とストリームAPI
社内Java8勉強会 ラムダ式とストリームAPI社内Java8勉強会 ラムダ式とストリームAPI
社内Java8勉強会 ラムダ式とストリームAPI
 
Haskell で CLI
Haskell で CLIHaskell で CLI
Haskell で CLI
 
BOF1-Scala02.pdf
BOF1-Scala02.pdfBOF1-Scala02.pdf
BOF1-Scala02.pdf
 
20150302 java8 第一回_ラムダ式(1)
20150302 java8 第一回_ラムダ式(1)20150302 java8 第一回_ラムダ式(1)
20150302 java8 第一回_ラムダ式(1)
 

Semelhante a Best practice laravel

ClassLoader Leak Patterns
ClassLoader Leak PatternsClassLoader Leak Patterns
ClassLoader Leak Patternsnekop
 
pi-15. カプセル化, MVCモデル, オブジェクトのマッピング
pi-15. カプセル化, MVCモデル, オブジェクトのマッピングpi-15. カプセル化, MVCモデル, オブジェクトのマッピング
pi-15. カプセル化, MVCモデル, オブジェクトのマッピングkunihikokaneko1
 
第三回ありえる社内勉強会 「いわががのLombok」
第三回ありえる社内勉強会 「いわががのLombok」第三回ありえる社内勉強会 「いわががのLombok」
第三回ありえる社内勉強会 「いわががのLombok」yoshiaki iwanaga
 
LaravelでAPI定義を管理する
LaravelでAPI定義を管理するLaravelでAPI定義を管理する
LaravelでAPI定義を管理するKenjiro Kubota
 
Java ee6 with scala
Java ee6 with scalaJava ee6 with scala
Java ee6 with scalaSatoshi Kubo
 
3時間濃縮CakePHP2.1 in PHPカンファレンス北海道2012
3時間濃縮CakePHP2.1 in PHPカンファレンス北海道20123時間濃縮CakePHP2.1 in PHPカンファレンス北海道2012
3時間濃縮CakePHP2.1 in PHPカンファレンス北海道2012Yusuke Ando
 
速くなければスマフォじゃない - インターンバージョン-
速くなければスマフォじゃない - インターンバージョン-速くなければスマフォじゃない - インターンバージョン-
速くなければスマフォじゃない - インターンバージョン-Kazunari Hara
 
[東京] JapanSharePointGroup 勉強会 #2
[東京] JapanSharePointGroup 勉強会 #2[東京] JapanSharePointGroup 勉強会 #2
[東京] JapanSharePointGroup 勉強会 #2Atsuo Yamasaki
 
<第1回>Laravelハンズオンセミナー
<第1回>Laravelハンズオンセミナー<第1回>Laravelハンズオンセミナー
<第1回>LaravelハンズオンセミナーTatsuyoshi Mashiko
 
第2回デザインパターン資料
第2回デザインパターン資料第2回デザインパターン資料
第2回デザインパターン資料gaaupp
 
10分でわかるFuelPHP @ 2011/12
10分でわかるFuelPHP @ 2011/1210分でわかるFuelPHP @ 2011/12
10分でわかるFuelPHP @ 2011/12kenjis
 
Synthesijer - HLS frineds 20190511
Synthesijer - HLS frineds 20190511Synthesijer - HLS frineds 20190511
Synthesijer - HLS frineds 20190511Takefumi MIYOSHI
 
PHP 2大 web フレームワークの徹底比較!
PHP 2大 web フレームワークの徹底比較!PHP 2大 web フレームワークの徹底比較!
PHP 2大 web フレームワークの徹底比較!Shohei Okada
 
勉強会force#4 Chatter Integration
勉強会force#4 Chatter Integration勉強会force#4 Chatter Integration
勉強会force#4 Chatter IntegrationKazuki Nakajima
 

Semelhante a Best practice laravel (20)

Scala2.8への移行
Scala2.8への移行Scala2.8への移行
Scala2.8への移行
 
ClassLoader Leak Patterns
ClassLoader Leak PatternsClassLoader Leak Patterns
ClassLoader Leak Patterns
 
pi-15. カプセル化, MVCモデル, オブジェクトのマッピング
pi-15. カプセル化, MVCモデル, オブジェクトのマッピングpi-15. カプセル化, MVCモデル, オブジェクトのマッピング
pi-15. カプセル化, MVCモデル, オブジェクトのマッピング
 
第三回ありえる社内勉強会 「いわががのLombok」
第三回ありえる社内勉強会 「いわががのLombok」第三回ありえる社内勉強会 「いわががのLombok」
第三回ありえる社内勉強会 「いわががのLombok」
 
LaravelでAPI定義を管理する
LaravelでAPI定義を管理するLaravelでAPI定義を管理する
LaravelでAPI定義を管理する
 
Java ee6 with scala
Java ee6 with scalaJava ee6 with scala
Java ee6 with scala
 
3時間濃縮CakePHP2.1 in PHPカンファレンス北海道2012
3時間濃縮CakePHP2.1 in PHPカンファレンス北海道20123時間濃縮CakePHP2.1 in PHPカンファレンス北海道2012
3時間濃縮CakePHP2.1 in PHPカンファレンス北海道2012
 
あらためてPHP5.3
あらためてPHP5.3あらためてPHP5.3
あらためてPHP5.3
 
速くなければスマフォじゃない - インターンバージョン-
速くなければスマフォじゃない - インターンバージョン-速くなければスマフォじゃない - インターンバージョン-
速くなければスマフォじゃない - インターンバージョン-
 
[東京] JapanSharePointGroup 勉強会 #2
[東京] JapanSharePointGroup 勉強会 #2[東京] JapanSharePointGroup 勉強会 #2
[東京] JapanSharePointGroup 勉強会 #2
 
test
testtest
test
 
<第1回>Laravelハンズオンセミナー
<第1回>Laravelハンズオンセミナー<第1回>Laravelハンズオンセミナー
<第1回>Laravelハンズオンセミナー
 
Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7
 
第2回デザインパターン資料
第2回デザインパターン資料第2回デザインパターン資料
第2回デザインパターン資料
 
10分でわかるFuelPHP @ 2011/12
10分でわかるFuelPHP @ 2011/1210分でわかるFuelPHP @ 2011/12
10分でわかるFuelPHP @ 2011/12
 
Synthesijer - HLS frineds 20190511
Synthesijer - HLS frineds 20190511Synthesijer - HLS frineds 20190511
Synthesijer - HLS frineds 20190511
 
Scala on Hadoop
Scala on HadoopScala on Hadoop
Scala on Hadoop
 
PHP 2大 web フレームワークの徹底比較!
PHP 2大 web フレームワークの徹底比較!PHP 2大 web フレームワークの徹底比較!
PHP 2大 web フレームワークの徹底比較!
 
勉強会force#4 Chatter Integration
勉強会force#4 Chatter Integration勉強会force#4 Chatter Integration
勉強会force#4 Chatter Integration
 
Trait in scala
Trait in scalaTrait in scala
Trait in scala
 

Best practice laravel