20200126のlaravelに関する記事は4件です。

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_profile

Node.js インストール

参考URL

レンタルサーバ「XSERVER」にNode.jsをインストールする

nodebrewのインストールとnodeのセットアップ

概要

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 -v

node/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 tinker

tinker内で下記実行し、日時が正しく取れれば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
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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.php
public 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.php
public function make($abstract, array $parameters = [])
    {
        return $this->resolve($abstract, $parameters);
    }

makeメソッドの第一引数に解決したい値、第二引数にその値のメソッドの引数(なければnull)を入れ、それらの引数を基に同クラス内のresolveメソッドが動きます。
単純な作りで良いですね。

resolveメソッド

 解決の機能の大部分を担っているのがresolveメソッドです。

Container.php
protected 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.php
public 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がコンストラクトメソッドを含む場合に、それを取得します。(詳しく言うと、$constructReflectionMethodのインスタンスをセットします。ReflectionMethodReflectionClassと同じようにPHP5以降から元からセットされたクラスで、$concreteのメソッドについて調べます。詳しくはこちら。)

(6)ではもし$concreteにコンストラクトメソッドがなければ、$concreteをインスタンスとして返します。

(7)では、$concreteのコンストラクトメソッドの引数の値を$dependenciesにセットします。
(ここでも詳しく言うと、ここでは$dependenciesReflectionParameterのインスタンスをセットします。ReflectionParameterReflectionClassと同じように以下略。$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メソッドなどまだまとめきれなかった項目が残っているので、今後これらも取り上げられたら良いなと思っています。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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');
});

終わり!!!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laradocを使ってLaravel6の開発環境をインストールする

はじめに

こちらの記事はTechpitに販売されている教材を進めるにあたって、教材を参考(ほぼ丸写し)にさせてもらって作成しています。
参考箇所はプレビュー部分なので、誰でも見ることができます。
URLも貼っておきます → Laravelで飲食店検索LINE Botを作ろう!
開発者はコチラの方です → やんばるさん(@shonansurvivors)

前提

Dockerをインストールしていること。
今回は略しますが、開発者のプレビューでもインストールの方法を丁寧に解説されていますので、よければご覧ください。

ユーザライブラリフォルダの直下にフォルダを作成

今回はユーザライブラリフォルダの直下にlaravel-projectフォルダを作成します。
下記のコマンドを叩けばユーザライブラリフォルダの直下にlaravel-projectフォルダを作成できます。
さらにlaravel-projectフォルダに移動。

$ cd
$ pwd
/Users/Macでのユーザー名

$ mkdir laravel-project
$ cd laravel-project

Laradocのインストール

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
laradock

laradockの.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=../data

Dockerを使って開発環境を起動する

引用させていただきます。

次にDockerを使って開発環境を起動します。
Docker上で動く各サービスの単位をコンテナと呼びます。
ここでは、以下3つのコンテナを起動します。
・workspace
・php-fpm
・nginx

laradocディレクトリにいることを確認し、下記のコードを実行する。

$ docker-compose up -d workspace php-fpm nginx

docker-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のウェルカムページが表示される。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む