- 投稿日:2020-01-26T21:41:08+09:00
Laravel6.x On Xserver(X10) with Queue/Job
XserverにLaravelアプリケーションをデプロイして動かしたメモ わりと簡単だった
概要
基本的には、https://readouble.com/laravel/6.x/ja/installation.html に記載されているシステム要件を満たすように準備していけばいいはず。アセットのコンパイルでnpm、デプロイはgitサーバーからpullしたいので、
- php7.2以上
- composer
- node/npm
- git
が入っていれば概ね良さそう。更に、job/queue を使いたいのでキューワーカーのプロセスをデーモン化する
- supervisor
がほしい。上記環境を整えた後、Laravelアプリケーションを公開するセッティングを進める。
事前調査(超やっつけ)
Linuxディストリビューション
よくはわからんがyumがあったのでRedHat系っぽい。が、root権限は無いのでyumは使えなそう(当たり前か)PHP
コンパネから7.3に変更しても、CLIのバージョンは5.4.16となっていた。
/usr/bin/php を指してる。git
入ってる(version 1.8.3.1)node
入ってないcomposer
入ってる(version 1.9.1)supervisor
入ってない。root権限が無いのでyumでインストールすることもできない。困りそう。cronは使えるので、1分間隔でcronにキューワーカのプロセスを起動させる、くらいで行けるかな?
→ググったら全く同じことをやろうとしてるのを見つけたので、なんとか大丈夫そう前提
Laravelバージョンは6.x、XServerのプランはX10
SSH設定/エックスサーバー
→SSH接続成功してるPHPのバージョンについて/エックスサーバー
→PHP7.3に切り替え実施済みMySQLの設定/エックスサーバー
→Mysqlデータベース作成、接続ユーザー設定済み無料独自SSL設定/エックスサーバー
→SSL設定済み環境構築
CLIのPHPバージョン変更
参考URL
XSERVER(エックスサーバー)にLaravelアプリを構築する方法/2018.12.10
XSERVER の cli(ssh接続) で PHP7 を使用する
手順
デフォルトのバージョンは5.4.16のようなので、webサーバ側に合わせる(今回は7.3)
mkdir $HOME/bin ln -s /usr/bin/php7.3 $HOME/bin/php vi $HOME/.bash_profile.bash_profile を修正
- PATH=$PATH:$HOME/.local/bin:$HOME/bin + PATH=$HOME/bin:$PATH:$HOME/.local/bin修正したら保存して、反映
source $HOME/.bash_profileNode.js インストール
参考URL
レンタルサーバ「XSERVER」にNode.jsをインストールする
概要
nodebrew経由で入れるのが楽っぽい
手順
nodebrew インストール
wget git.io/nodebrew perl nodebrew setup vi $HOME/.bash_profileまたパスを追加
- PATH=$HOME/bin:$PATH:$HOME/.local/bin + PATH=$HOME/bin:$HOME/.nodebrew/current/bin:$PATH:$HOME/.local/bin修正したら保存して反映、バージョン表示されればOK
source $HOME/.bash_profile nodebrew -vnode/npm のインストール
# stableを入れる nodebrew install-binary stable # 入ったバージョンを確認 nodebrew list # 確認したバージョンをuse nodebrew use v12.14.1 # node/npmのバージョン確認 node -v npm -vキューワーカー設定
キューワーカーをデーモンプロセスにしたいがsupervisorはインストールできないっぽい。crontabに一定間隔で叩かせればいけそう。
参考URL
https://chinotsubo.com/laravel-queue-on-shared-hosting/
Karnel.php にスケジュール設定
参考URLとオプションを少し変えて、1分間隔でキューワーカー起動、JOBがなければ勝手に落ちるようにしてる。アプリケーションの運用上Jobがたまり続けることもそんなになさそうなので、restartも要らないかなー、運用しながら様子みるかなー、って感じで
/** * Define the application's command schedule. * @param \Illuminate\Console\Scheduling\Schedule $schedule * @return void */ protected function schedule(Schedule $schedule) { //supervisorが使えない環境用の代替運用:1分間隔でキューワーカーを起動。 $schedule->command('queue:work --tries=1 --stop-when-empty') ->everyMinute() ->withoutOverlapping(); }crontabにLaravelのタスクスケジューラを登録
いつもの。Xserverのコンパネから設定すればOK
https://readouble.com/laravel/6.x/ja/scheduling.html
アプリケーションのセットアップ
ソースコードのデプロイ
gitリポジトリ上にLaravelプロジェクトが置いてある前提、とりあえずlaravelというディレクトリを作って放り込む
cd ~/<example.com> git clone <repo url> laravel cd laravel依存パッケージのインストール
いつもの。
composer install.envファイルの作成と編集
いつも通り。
cp .env.example .env php artisan key:generate vi .envいつも通り。コンパネで作成したMysqlデータベースを指すように、設定を適宜修正。
- DB_HOST= - DB_DATABASE= - DB_USERNAME= - DB_PASSWORD= + DB_HOST=<コンパネで確認> + DB_DATABASE=<コンパネで作成したDB名> + DB_USERNAME=<コンパネで作成、設定したユーザ> + DB_PASSWORD=<コンパネで設定したパスワード>他にも必要な項目があれば適宜実施。とりあえず動かして動作確認するところまで行けば良いので、開発環境と同じような感じで設定しておくと良いでしょう。(メールはログに吐いたり、とりあえずRedisを使わない設定にしておいたり、Queueをsyncにしたり、とか)
DB接続の確認
上記編集を完了して、DBに接続できるかをチェック
php artisan tinkertinker内で下記実行し、日時が正しく取れればDB接続OK
DB::select("select now()");webサーバー周りの設定
ドキュメントルートをいじったりはできなそう(調べてない)ので、.htaccessを編集しリダイレクトを設定(全部 public へ)
vi ~/example.com/public_html/.htaccess+ <IfModule mod_rewrite.c> + RewriteEngine On + RewriteRule ^(.*)$ public/$1 [QSA,L] + </IfModule>※webサーバがnginxでも.htaccessを書けばいいらしい。謎
.htaccessに書いたリダイレクト先のpublic がLaravel/publicを指すようにシンボリックリンク作成
ln -s /home/<USERNAME>/<example.com>/laravel/public ./public
- 投稿日:2020-01-26T17:44:54+09:00
Laravelのサービスコンテナのバインドと解決の仕組みが知りたい!
はじめに
Laravelについて勉強しているなか、自分はふと
「Laravelでは、bindとかmakeを使って手軽にインスタンスの受け渡しやインスタンスの利用ができて便利だけど、その仕組みはどうなっているんだろ?」
と感じました。
そこで、実際にbindなどのバインドの仕組みとmakeなどの解決の仕組みについてLaravelのコードを見て調べてみました!(個人的な事情によりLaravel5.5のコードを見て調べました。)本題
バインドと解決の大まかな仕組み(というかこの記事の結論)
バインド(というかbindメソッド)の大まかな仕組みは、
bindメソッドの第一引数をキーとして、第二引数をクラスのインスタンスやクロージャとなるキーの値としてLravelであらかじめ用意された配列にセットするというものです。
そして解決(というかmakeメソッド)の大まかな仕組みは、
bindメソッドでセットした配列のキーと同じ値がmakeメソッドの第一引数にセットされたとき、そのキーに対応するインスタンスやクロージャを返すというものです。
今度は実際のLaravelのコードを見て、バインドの仕組みについてみていきたいと思います。バインドの仕組みについて
実際のbindメソッドのコードはこのようになっています。ちなみにbindメソッドは、Laravelのサービスコンテナの実態であるApplication.phpの親クラスであるContainer.phpにあります。
bindメソッド
Container.phppublic function bind($abstract, $concrete = null, $shared = false) { $this->dropStaleInstances($abstract); //.....(1) if (is_null($concrete)) { $concrete = $abstract; } if (! $concrete instanceof Closure) { $concrete = $this->getClosure($abstract, $concrete); } //.....(2) $this->bindings[$abstract] = compact('concrete', 'shared'); //.....(3) if ($this->resolved($abstract)) { $this->rebound($abstract); } //.....(4) }ポイントを(1)~(4)に分けて説明します。
(1)では、bindメソッドの第一引数が、同クラス内のinstanceメソッドやaliasメソッドなどによりセットされた配列のキーとして含まれていた場合、そのキーの要素を消去します。
(2)では、もし
$concreteの値がクロージャでなかった場合(クラスである場合)、同クラス内のgetClousureメソッドによりその値はインスタンス化されます。(getClousureメソッドはメソッド内のbuildメソッドやmakeメソッドによりクラスをインスタンス化していますが、これらのメソッドについては後程取り上げるので説明は省略)(3)がこのbindメソッドでやる最も重要なことかなと思います。なぜなら、このひとつ前の章(バインドと解決の大まかな仕組み)で言っていた、
あらかじめ用意された配列とは$this->bindingsのことだからです。
この配列にbindメソッドの$abstractの値をキーとして、$concreteの値をインスタンスやクロージャとしてセットします。
($sharedはデフォルトではfalseとなり特に何の効果も生みませんが、singletonメソッドでバインドされた際はtrueとなり、ある効果を生み出しますが記事が長くなる本筋と離れるので詳しい説明は省きます。また、PHPのマジックメソッドであるcompactメソッドは変数名をキー、値をそのキーの値として配列を作ります。詳しくはこちら。)(4)では、もし
$this->bindingsのキーに対応するインスタンス又はクロージャが解決済みの場合(resolveメソッドにより解決済みかどうかが判断できる)、同クラス内のrebindingメソッドによりセットされた配列の同名のキーの値である関数が行われる。
(いつrebindingメソッドが行われるか、なぜこのメソッドが必要なのかわかっていません。わかる方、コメントで教えてください!)解決(makeメソッド)の仕組みについて
解決の流れはLaravelのサービスコンテナの実態であるApplication.phpのmakeメソッドを経て親クラスのContainer.phpのmakeメソッドが実行されますが、Application.phpのmakeメソッドについて説明すると
面倒くさい本筋と離れるのでこの記事ではContainer.phpの方だけを取り扱います。makeメソッド
Container.phppublic function make($abstract, array $parameters = []) { return $this->resolve($abstract, $parameters); }makeメソッドの第一引数に解決したい値、第二引数にその値のメソッドの引数(なければnull)を入れ、それらの引数を基に同クラス内のresolveメソッドが動きます。
単純な作りで良いですね。resolveメソッド
解決の機能の大部分を担っているのがresolveメソッドです。
Container.phpprotected function resolve($abstract, $parameters = []) { $abstract = $this->getAlias($abstract); //.....(1) $needsContextualBuild = ! empty($parameters) || ! is_null( $this->getContextualConcrete($abstract) //.....(2) ); if (isset($this->instances[$abstract]) && ! $needsContextualBuild) { return $this->instances[$abstract]; } //.....(3) $this->with[] = $parameters; //.....(4) $concrete = $this->getConcrete($abstract); //.....(5) if ($this->isBuildable($concrete, $abstract)) { $object = $this->build($concrete); } else { $object = $this->make($concrete); } //.....(6) foreach ($this->getExtenders($abstract) as $extender) { $object = $extender($object, $this); } //.....(7) if ($this->isShared($abstract) && ! $needsContextualBuild) { $this->instances[$abstract] = $object; } //.....(8) $this->fireResolvingCallbacks($abstract, $object); //.....(9) $this->resolved[$abstract] = true; //.....(10) array_pop($this->with); return $object; }resolveメソッドの機能は、このメソッドの第一引数である
$abstractの値とbindメソッドで作成した$this->bindingsのキーの値が同じとき、そのキーに対応したインスタンスやクロージャが返される、というものです。でもこれを言うだけじゃ全コード載せた意味がないので、(1)~(10)に分けてもう少し細かく見ていきます。(1)では、
$abstractの値がaliasメソッドなどでセットされる$this->alaiasesという配列のキーに含まれていない場合、$abstractの値はそのままです。もし含まれていた場合はエラーを吐きます。(2)では、
$parametersの値が空かつ$abstractの値が同クラス内のaddContextualBindingメソッドでセットされる$this->contextualのキーとしてセットされていない場合以外は$needsContextualBuildの値はtrueになります。(たいていはfalseになります。というかなぜ$this->contextualが存在するのか自分では理解していません。わかる方はぜひ教えてほしいです。)(3)についてですが、ここの機能はsingletonメソッドを使用する際に使われるですので今回は説明を省きます。
(4)では、
$parametersの値が$this->withという配列にセットします。this->withはbuildメソッドで使います。そしてresolveメソッドの最後に$this->withの値はリセットされます。(5)では、
$concreteに同クラス内のgetConcreteメソッドの結果をセットします。getConcreteメソッドの機能は、resolveメソッド内の$abstractの値と同じ$this->bindingsのキーのインスタンス化クロージャを返す、というものです。また、それができなければgetConcreteメソッドの引数(ここでは$abstract)の値をそのまま返します。(6)では、まず同クラス内のisBuildableメソッドによって処理の分岐が行われます。isBuildableでは、もし
$abstractと$concreteの値が同じか$concreteの値がクロージャであった場合、tureを返しそうでない場合はfalseを返します。
もしtrueであった場合は$objectの値がbuildメソッドの結果となります(buildメソッドについては後程取り上げます)。
もしfalseであった場合は第一引数を$concreteの値にしてresolveメソッド(makeメソッドはresolveメソッドを引き起こしているだけ)を行います。これにより今度は$abstractの値と$concreteの値が同じになり、trueの場合と同じことが行われます。(7)では、もし同クラス内のextendメソッドによりセットされた
$this->extendersの配列のキーと$abstractの値が同じ場合は、そのキーに対応したクロージャを$objectの値にセットします(extendメソッドの使われ方は理解できていません。わかる方教えてください)。(8)は、singletonメソッドに関係するところなので、説明を省きます。
(9)では、同クラス内のresolvingメソッドで
$this->globalResolvingCallbacksにクロージャがセットされていたらそのクロージャを実行します。セットされていなければ何もしません。(10)では、
$this->resolvedの配列の$abstractの値がキーとなっている値にtureをセットします。これにより、$abstractの値を解決しようとしたときにすでにその値が解決済みかどうかがわかります。最後に
$this->bindings[$abstract]に対応したインスタンスかクロージャを返します。buildメソッド
buildメソッドはbindメソッドでセットした
$this->bindingのキーに対するクロージャやインスタンスを用意してくれる、サービスコンテナの中で重要な役割を担うメソッドです。
これがなければ解決どころかバインドすらも成立しません。Container.phppublic function build($concrete) { if ($concrete instanceof Closure) { return $concrete($this, $this->getLastParameterOverride()); } //.....(1) $reflector = new ReflectionClass($concrete); //.....(2) if (! $reflector->isInstantiable()) { return $this->notInstantiable($concrete); } //.....(3) $this->buildStack[] = $concrete; //.....(4) $constructor = $reflector->getConstructor(); //.....(5) if (is_null($constructor)) { array_pop($this->buildStack); return new $concrete; } //.....(6) $dependencies = $constructor->getParameters(); //.....(7) $instances = $this->resolveDependencies( $dependencies ); //.....(8) array_pop($this->buildStack); return $reflector->newInstanceArgs($instances); //.....(9) }buildメソッドは渡される引数によって中で起こることが変わります。
(1)は、もしbuildメソッドに渡された引数がクロージャである行われます。というかクロージャの場合は(1)で終了です。クロージャが返されるときに引数にとる
$this->getLastParameterOverride()の値はmakeメソッドやresolveメソッドの第二引数であるarray $parametersの値となります。なお、返り値のクロージャの第一引数は絶対$this(Applicationクラスをインスタンスにとるオブジェクト。大抵は$app)となるので、もしクロージャに値を受け渡したいときは、bindメソッドでセットするクロージャの第二引数に受け渡したい値をセットしましょう。(2)の
ReflectionClassはPHP5以降からPHPにあらかじめセットされたクラスで、使用したいクラスにuse ReflectionClass;と入力することで使えるようになります(詳しくはこちら)。
ReflectionClassに組み込まれているメソッドを使うことで、引数に指定されているクラスの様々な情報が分かったり、そのクラスの数値を取り出すこともできます。(3)では
ReflectionClassの引数のクラス(これからは$concrete)がインスタンス化できるものかを調べ、できなければエラーを吐きます。(4)の
$this->buildStackは、buildメソッドが行われている間$concreteの値を他のメソッドに受け渡す際に使われます。buildメソッドの終了時に$this->buildStackの値はリセットされます。(同クラス内のfindInContextualBindingsメソッドなどで使いますが、このメソッドがある意味をよく理解していないため、$this->buildStackの重要性もいまいち理解できていません。)(5)では、もし
$concreteがコンストラクトメソッドを含む場合に、それを取得します。(詳しく言うと、$constructにReflectionMethodのインスタンスをセットします。ReflectionMethodはReflectionClassと同じようにPHP5以降から元からセットされたクラスで、$concreteのメソッドについて調べます。詳しくはこちら。)(6)ではもし
$concreteにコンストラクトメソッドがなければ、$concreteをインスタンスとして返します。(7)では、
$concreteのコンストラクトメソッドの引数の値を$dependenciesにセットします。
(ここでも詳しく言うと、ここでは$dependenciesにReflectionParameterのインスタンスをセットします。ReflectionParameterはReflectionClassと同じように以下略。$concreteのメソッドの引数について調べます。詳しくはこちら。)(8)では、同クラス内のresolveDependenciesメソッドを使用し、もし調べる対象の
$concreteのメソッドに値入りの引数があればその値を、タイプヒント付きの引数があればタイプヒントに表記されたクラスのインスタンスを$instancesにセットします。(9)では
$concreteにコンストラクトメソッドに入る引数(なければ空)をセットし、$concreteのインスタンスを返します。
(newInstanceArgsメソッドはReflectionClassに組み込まれたメソッドです。詳しくはこちら。)実際に作って動かしてみよう!
まず作ろう
ここまで調べてくると、今まで調べたクラス、メソッドをコピペし、うまく組み合わせればフレームワーク要らずでバインドと解決の機能を再現できるんじゃね、と思い作ってみました。
実際に(コピペして)作ったコードがこちらApplication.php<?php namespace App; //ここはどうでも良いよ use ReflectionClass; use Closure; use ReflectionParameter; /** * */ class Application { protected $bindings = []; protected $instances = []; protected $resolved = []; protected $abstractAliases = []; protected $contextual = []; protected $buildStack = []; protected $with; public function bind($abstract, $concrete = null, $shared = false) { if (is_null($concrete)) { $concrete = $abstract; } if (! $concrete instanceof Closure) { $concrete = $this->getClosure($abstract, $concrete); } $this->bindings[$abstract] = compact('concrete', 'shared'); } protected function getClosure($abstract, $concrete) { return function ($container, $parameters = []) use ($abstract, $concrete) { if ($abstract == $concrete) { return $container->build($concrete); } return $container->make($concrete, $parameters); }; } public function make($abstract, array $parameters = []) { return $this->resolve($abstract, $parameters); } public function resolve($abstract, $parameters = []) { $needsContextualBuild = ! empty($parameters); if (isset($this->instances[$abstract]) && ! $needsContextualBuild) { return $this->instances[$abstract]; } $this->with[] = $parameters; $concrete = $this->getConcrete($abstract); if ($this->isBuildable($concrete, $abstract)) { $object = $this->build($concrete); } else { $object = $this->make($concrete); } if ($this->isShared($abstract) && ! $needsContextualBuild) { $this->instances[$abstract] = $object; } $this->resolved[$abstract] = true; array_pop($this->with); return $object; } public function build($concrete) { if ($concrete instanceof Closure) { return $concrete($this, $this->getLastParameterOverride()); } $reflector = new ReflectionClass($concrete); if (! $reflector->isInstantiable()) { //return $this->notInstantiable(); echo "Error"; } $this->buildStack[] = $concrete; $constructor = $reflector->getConstructor(); if (is_null($constructor)) { array_pop($this->buildStack); return new $concrete; } $dependencies = $constructor->getParameters(); $instances = $this->resolveDependencies( $dependencies ); array_pop($this->buildStack); return $reflector->newInstanceArgs($instances); } protected function getConcrete($abstract) { if (isset($this->bindings[$abstract])) { return $this->bindings[$abstract]['concrete']; } return $abstract; } protected function isBuildable($concrete, $abstract) { return $concrete === $abstract || $concrete instanceof Closure; } public function isShared($abstract) { return isset($this->instances[$abstract]) || (isset($this->bindings[$abstract]['shared']) && $this->bindings[$abstract]['shared'] === true); } protected function getLastParameterOverride() { return count($this->with) ? end($this->with) : []; } protected function notInstantiable() { $message = 'Error!! This Class is not instantiable.'; throw new Exception($message); } protected function resolveDependencies(array $dependencies) { $results = []; foreach ($dependencies as $dependency) { if ($this->hasParameterOverride($dependency)) { $results[] = $this->getParameterOverride($dependency); continue; } $results[] = is_null($dependency->getClass()) ? $this->resolvePrimitive($dependency) : $this->resolveClass($dependency); } return $results; } protected function hasParameterOverride($dependency) { return array_key_exists( $dependency->name, $this->getLastParameterOverride() ); } protected function resolvePrimitive(ReflectionParameter $parameter) { if ($parameter->isDefaultValueAvailable()) { return $parameter->getDefaultValue(); } $this->unresolvablePrimitive($parameter); } protected function unresolvablePrimitive(ReflectionParameter $parameter) { $message = "Unresolvable dependency resolving [$parameter] in class {$parameter->getDeclaringClass()->getName()}"; echo $message; } protected function resolveClass(ReflectionParameter $parameter) { return $this->make($parameter->getClass()->name); } } ?>Laravelで実際に書かれているコードと比べるとだいぶ少ない分量でいけました。
動かそう
次に今回のように調べる&コピペで作ったオートローダ(その時の記事はこちら)と共に動かしていきます。
動作の結果は、ブラウザ上で確認します。
ちなみにファイルの構造はこんな感じ(白丸は黒丸の中にあるファイル)<アプリケーション内>
- app
- Application.php(バインドと解決)
- Model(このフォルダは実行したいクラスが入る)
- First.php
- Second.php
- Third.php
- app.php(Laravelのbootstrap\app.phpのポジション)
- index.php(Laravelのpublic\index.phpのポジション。こいつの表示を見て動いているかどうかを見る。)
- autoload_real.php(これ以下のファイルはオートロードの機能を担うがオートロードは今回の本筋ではないため紹介しない)
- autoload_static.php
- autoloas.php
- ClassLoader.php
実行するクラス
First.php<?php namespace Model; /** * */ class First { public function copy() { echo "耳コピでしゅか?".nl2br("\n"); //nl2br()はブラウザ上で文字を改行するため } public function pai() { echo "じゃあだれが一体パイを焼くんだい?"; } } ?>Second.php<?php namespace Model; /** * */ class Second extends First { public function __construct() { $this->comment = "キャー、のび太さんの".nl2br("\n"); } public function comment() { echo $this->comment."エッジのきいたカッティングリフー!".nl2br("\n"); } } ?>Third.php<?php namespace Model; /** * */ class Third { public function __construct(First $first) { $this->first = $first; } public function end() { $this->first->pai(); } } ?>ひたすらバインドを行うクラス
app.php<?php $app = new App\Application(); $app->bind('Teacher', function () { echo "コピーよろしく".nl2br("\n"); }); $app->bind('Nobita', Model\First::class); $app->bind('Shizuka', Model\Second::class); $app->bind('End', Model\Third::class); return $app; ?>結果をブラウザに写すクラス(解決を行うクラス)
index.php<?php require 'autoload.php'; //自作のコピペオートローダの読み込み $app = require_once __DIR__.'/app.php'; //自作のコピペサービスコンテナの読み込み $app->make('Teacher'); $answer = $app->make('Nobita'); $answer->copy(); $comment = $app->make('Shizuka'); $comment->comment(); $ending = $app->make('End'); $ending->end(); ?>結果
コピーよろしく
耳コピでしゅか?
キャー、のび太さんの
エッジのきいたカッティングリフー!
じゃあだれが一体パイを焼くんだい?終わりに
他の人に自分の調べたことを伝えることよりも自分の調べたことを言葉でまとめることに意識がいってしまい、わかりにくいところが多い記事になっていると思います。読んでくれた方ありがとうございます、そしてすいません。
フレームワークについて調べると、そのフレームワークの理解が深まるだけではなく、言語自体の理解も深まることもあり、面白かったです。singletonメソッドなどまだまとめきれなかった項目が残っているので、今後これらも取り上げられたら良いなと思っています。
- 投稿日:2020-01-26T14:28:55+09:00
Laravelでとりあえず画像を表示する
※自分用メモ
Laravelで画像を表示します。
1.resources/viewsにindex.blade.phpを作成し、以下を挿入
<img src= {{asset('/img/piyopiyo.png')}} >asset~部分が環境下でURLに置き換わるそうです。
※bladeにしないと(=index.phpで作ると)波括弧の構文が機能しない
俺はこれで三時間潰しました2.piyopiyo.pngをpublic/imgに入れる
フォルダを作成して突っ込みます。
3.routesのweb.phpに以下のコードを入れる
Route::get('/index/', function () { return view('index'); });終わり!!!
- 投稿日:2020-01-26T00:45:34+09:00
Laradocを使ってLaravel6の開発環境をインストールする
はじめに
こちらの記事はTechpitに販売されている教材を進めるにあたって、教材を参考(ほぼ丸写し)にさせてもらって作成しています。
参考箇所はプレビュー部分なので、誰でも見ることができます。
URLも貼っておきます → Laravelで飲食店検索LINE Botを作ろう!
開発者はコチラの方です → やんばるさん(@shonansurvivors)前提
Dockerをインストールしていること。
今回は略しますが、開発者のプレビューでもインストールの方法を丁寧に解説されていますので、よければご覧ください。ユーザライブラリフォルダの直下にフォルダを作成
今回はユーザライブラリフォルダの直下にlaravel-projectフォルダを作成します。
下記のコマンドを叩けばユーザライブラリフォルダの直下にlaravel-projectフォルダを作成できます。
さらにlaravel-projectフォルダに移動。$ cd $ pwd /Users/Macでのユーザー名 $ mkdir laravel-project $ cd laravel-projectLaradocのインストール
GitHubからlaradockのファイルをコピーします。
$ git clone https://github.com/Laradock/laradock.git Cloning into 'laradock'... remote: Enumerating objects: 10007, done. remote: Total 10007 (delta 0), reused 0 (delta 0), pack-reused 10007 Receiving objects: 100% (10007/10007), 8.99 MiB | 1.61 MiB/s, done. Resolving deltas: 100% (5432/5432), done.もし下記のようなメッセージ(XcodeとiOSのライセンスの同意)が出たらリンク先を参考にしてみてください。
Agreeing to the Xcode/iOS license requires admin privileges, please run “sudo xcodebuild -license” and then retry this command.Gitコマンド実行時に、XcodeとiOSのライセンス同意を求められた場合の解決法
しばらく時間がかかりますが、完了すると、laravel-projectにlaradockフォルダが作成されます。
$ ls laradocklaradockの.envファイルを作成
laradockフォルダに移動します。cpコマンドでlaradockにあるenv-exampleファイルをコピーし、.envファイルを作成します。
$ cd laradock $ cp env-example .envこれでenv-exampleファイルをもとに.envファイルが作成できました。
laradockの.envファイルを編集する
テキストエディタでlaladockフォルダの.envファイルを開き下記のように変更。
APP_CODE_PATH_HOST=../laravel DATA_PATH_HOST=../dataDockerを使って開発環境を起動する
引用させていただきます。
次にDockerを使って開発環境を起動します。
Docker上で動く各サービスの単位をコンテナと呼びます。
ここでは、以下3つのコンテナを起動します。
・workspace
・php-fpm
・nginxlaradocディレクトリにいることを確認し、下記のコードを実行する。
$ docker-compose up -d workspace php-fpm nginxdocker-composeは、複数のコンテナを同時に取り扱うDocker Composeという機能を使うためのコマンドです
upは、Docker Composeでコンテナを起動するときに使うコマンドです
-dは、コンテナを起動した後に、ターミナルの操作に戻るためのオプションです結構時間かかります。
Creating laradock_docker-in-docker_1 ... done Creating laradock_workspace_1 ... done Creating laradock_php-fpm_1 ... done Creating laradock_nginx_1 ... done上記のメッセージが表示されたらコンテナの起動が成功している。
Dockerコンテナの起動確認
ブラウザを起動し、 localhost とだけ入力。「404 Not Found」のエラーが出れば、Dockerが起動しているのでひとまずはOK。
Laravelのインストール
laradocフォルダにいることを確認した後、Laravelをインストールします。
$ docker-compose exec workspace composer create-project --prefer-dist laravel/laravel . "6.2.*" Installing laravel/laravel (v6.2.0) - Installing laravel/laravel (v6.2.0): Downloading (100%) Created project in . . . // 中略 . Package manifest generated successfully. > @php artisan key:generate --ansi Application key set successfully.てな感じでlaravel-project直下にlaravelのフォルダが作成される。
localhost へブラウザでアクセスしてみるとLaravelのウェルカムページが表示される。