laravel.osaka とは
laravel.osaka は「laravelおもろいやん!!」をテーマに、Laravelを愛してやまないPHPer や
これからLaravel/PHPをはじめようする人たちで技術交流を進めていこう、という勉強会です。
ハッシュタグは #laravel_osaka
日時・場所
- 日時:4月23日(火)19:00 ~ 21:00
- 場所:大阪府大阪市北区同心1丁目11番6号(株式会社 tambourine様)
勉強会内容
[PHP] laravel.osaka #14 - connpass の勉強会の内容をまとめていきます
「Laravelでサービスを作った時にやったこと」
登壇者:@dala00さん
スライド:Laravelでサービスを作った時にやったこと - Speaker Deck
内容:
Qiitaのようなエンジニア向けWEBサービス「Crieit」を作った際のお話
※途中参加につきお話聞けず・・・すみません。。。
「index.phpの処理を追ってみた」
登壇者:@choco14tさん
スライド:index.phpの処理を追ってみた / Dive into index.php - Speaker Deck
内容:
- index.php
- この中の
$app = require_once __DIR__.'/../bootstrap/app.php';
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
$response = $kernel->handle(
$request = Illuminate\Http\Request::capture()
);
について処理を追っていく
-
bootstrap/app.php
$app = require_once __DIR__.'/../bootstrap/app.php';
-
Applicationインスタンス生成
- サービスプロバイダ
- エイリアス
- インスタンス
-
Container::singleton()
-
Container::build()
を呼んでいる
-
/**
* Register a shared binding in the container.
*
* @param string $abstract
* @param \Closure|string|null $concrete
* @return void
*/
public function singleton($abstract, $concrete = null)
{
$this->bind($abstract, $concrete, true);
}
-
shared
フラグをtrue
にしている -
Container::bind()
/**
* Register a binding with the container.
*
* @param string $abstract
* @param \Closure|string|null $concrete
* @param bool $shared
* @return void
*/
public function bind($abstract, $concrete = null, $shared = false)
{
// If no concrete type was given, we will simply set the concrete type to the
// abstract type. After that, the concrete type to be registered as shared
// without being forced to state their classes in both of the parameters.
$this->dropStaleInstances($abstract);
if (is_null($concrete)) {
$concrete = $abstract;
}
// If the factory is not a Closure, it means it is just a class name which is
// bound into this container to the abstract type and we will just wrap it
// up inside its own Closure to give us more convenience when extending.
if (! $concrete instanceof Closure) {
$concrete = $this->getClosure($abstract, $concrete);
}
$this->bindings[$abstract] = compact('concrete', 'shared');
// If the abstract type was already resolved in this container we'll fire the
// rebound listener so that any objects which have already gotten resolved
// can have their copy of the object updated via the listener callbacks.
if ($this->resolved($abstract)) {
$this->rebound($abstract);
}
}
-
Application::make()
- サービスプロバイダの遅延読み込み(あれば)
- 依存オブジェクトの解決
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
/**
* Resolve the given type from the container.
*
* (Overriding Container::make)
*
* @param string $abstract
* @param array $parameters
* @return mixed
*/
public function make($abstract, array $parameters = [])
{
$abstract = $this->getAlias($abstract);
if (isset($this->deferredServices[$abstract]) && ! isset($this->instances[$abstract])) {
$this->loadDeferredProvider($abstract);
}
return parent::make($abstract, $parameters);
}
/**
* Resolve the given type from the container.
*
* @param string $abstract
* @param array $parameters
* @return mixed
*/
public function make($abstract, array $parameters = [])
{
return $this->resolve($abstract, $parameters);
}
Container::resolve()
- 依存オブジェクトの生成
- 再帰的に依存オブジェクトを生成
-
Container::make()
を再呼び出し
-
/**
* Resolve the given type from the container.
*
* @param string $abstract
* @param array $parameters
* @return mixed
*/
protected function resolve($abstract, $parameters = [])
{
$abstract = $this->getAlias($abstract);
$needsContextualBuild = ! empty($parameters) || ! is_null(
$this->getContextualConcrete($abstract)
);
// If an instance of the type is currently being managed as a singleton we'll
// just return an existing instance instead of instantiating new instances
// so the developer can keep using the same objects instance every time.
if (isset($this->instances[$abstract]) && ! $needsContextualBuild) {
return $this->instances[$abstract];
}
$this->with[] = $parameters;
$concrete = $this->getConcrete($abstract);
// We're ready to instantiate an instance of the concrete type registered for
// the binding. This will instantiate the types, as well as resolve any of
// its "nested" dependencies recursively until all have gotten resolved.
if ($this->isBuildable($concrete, $abstract)) {
$object = $this->build($concrete);
} else {
$object = $this->make($concrete);
}
// If we defined any extenders for this type, we'll need to spin through them
// and apply them to the object being built. This allows for the extension
// of services, such as changing configuration or decorating the object.
foreach ($this->getExtenders($abstract) as $extender) {
$object = $extender($object, $this);
}
// If the requested type is registered as a singleton we'll want to cache off
// the instances in "memory" so we can return it later without creating an
// entirely new instance of an object on each subsequent request for it.
if ($this->isShared($abstract) && ! $needsContextualBuild) {
$this->instances[$abstract] = $object;
}
$this->fireResolvingCallbacks($abstract, $object);
// Before returning, we will also set the resolved flag to "true" and pop off
// the parameter overrides for this build. After those two things are done
// we will be ready to return back the fully constructed class instance.
$this->resolved[$abstract] = true;
array_pop($this->with);
return $object;
}
-
Container::build()
- インスタンスの生成
- Reflectionを使って実現
-
Http\kernal::handle()
- リクエストを受け取ってレスポンスを返す
$response = $kernel->handle(
$request = Illuminate\Http\Request::capture()
);
-
ブートストラッピング
- config
- facade
- service provider
-
対応したルーティングの処理実行
-
レスポンス返却
/**
* Handle an incoming HTTP request.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function handle($request)
{
try {
$request->enableHttpMethodParameterOverride();
$response = $this->sendRequestThroughRouter($request);
} catch (Exception $e) {
$this->reportException($e);
$response = $this->renderException($request, $e);
} catch (Throwable $e) {
$this->reportException($e = new FatalThrowableError($e));
$response = $this->renderException($request, $e);
}
$this->app['events']->dispatch(
new Events\RequestHandled($request, $response)
);
return $response;
}
- Http\Kernel.php
- \Illuminate\Foundation\Bootstrap\HandleExceptions::classが書かれている処理が少なく読みやすい
/**
* The bootstrap classes for the application.
*
* @var array
*/
protected $bootstrappers = [
\Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class,
\Illuminate\Foundation\Bootstrap\LoadConfiguration::class,
\Illuminate\Foundation\Bootstrap\HandleExceptions::class,
\Illuminate\Foundation\Bootstrap\RegisterFacades::class,
\Illuminate\Foundation\Bootstrap\RegisterProviders::class,
\Illuminate\Foundation\Bootstrap\BootProviders::class,
];
まとめ
- 実際に処理が行われるまで膨大な処理が実行されている
- Laravelのコードを読むことは可能なので読んでみましょう
「LaravelでREST API開発(ライブコーディング)」
登壇者:@_mikakaneさん
スライド:なし
内容:
-
開発環境構築について
-
$ laravel new
で環境構築できる -
$ php artisan serve
コマンドでサーバーが立ち上がる
-
-
Laravel Mixを使用する際はnpmビルドする必要がある
-
- 上からキャッシュやリクエストを確認できる
-
Factory
でサンプルのユーザーデータが簡単につくれる -
Str::random()
でランダムの文字列を生成される → Str::random() -
画面のテストは
tests\Feature
ディレクトリ内にかく- テストの際に
assertStatus(200)
を書いておくだけでもちゃんとレスポンスが返ってくるかの確認ができる - テストを実行する際は
phpunit
コマンドをたたく - パスワードを検証する際は
Hash::check()
メソッドを使用する- これで認証失敗の場合は
abort(403)
を返すようにする
- これで認証失敗の場合は
- この反対のメソッドをテストに書いておくと、正常系は
200
、認証失敗は403
を返すということを確認できる - RESTAPIを作成するときは
postメソッド
等を使用することにより内部的にリクエストを送ることができるのでこれらをつかってテストコードをかく - ヘッダを送るときは
$this->withHeader
を使う
- テストの際に
-
テストコードを書いて実装 いわゆる「テスト駆動開発」
-
@depends メソッド名
とアノテーションを書いてやるとそのテストを実行後でないと実行されない&返り値をそのメソッドの引数に渡せる -
ログインのテスト実行後、トークンを引数として渡してやると、以降のテストで認証情報を使える
まとめ
- Laravel Telescopeは便利だが画面の行き来が発生する
- ほとんどの作業がPhpStorm上で完結する(RESTAPIの開発が可能)
LT枠:20年目のPHPer、laravelと出会う
登壇者:@takujiozakiさん
スライド:なし
内容:
- 専門学校の教師をしている
- プログラマー=Javaという認識の生徒が多い
- 教え子から現場ではLaravelを使うことが多いという話を聞く
- Laravelを勉強し始めた
おわり
- 登壇者の方、主催者の方、ありがとうございました&お疲れ様でした!
- まとめのくせにまとまってないのはすみません。。
- わかる部分とわからない部分があるのでもっと勉強します