20201012のPHPに関する記事は20件です。

【PHP】strstr() と strtr() の合わせ技で、文字列内の複数文字を置換する

こんな時に使えます

とあるDBのテーブル内で、複数の要素(例でいうと、職業とステータス)が、
ひとつの文字列に連結されてしまっている場合に、
・分離して
・区切りに使われている記号を取り除いて
・取得

ができる。

実例

$sample_text = "勇者[HP300]"

分離する

$sample_text_extract = strstr($sample_text, '[');  
// 変数の中身は、[HP300]という文字列

【解説】
strstr()
https://www.php.net/manual/ja/function.strstr.php

第一引数:対象の文字列
第二引数:検索したい文字
返り値: 検索したい文字を含んだ、文末までの文字列

区切りに使われている文字を取り除く

$replace = [
    '[' => '',
    ']' => ''
];

$sample_text_trimmed = strtr($sample_text_extract, $replace);
// 変数の中身は、HP300 という文字列


【解説】
strtr()
https://www.php.net/manual/ja/function.strtr.php

第一引数:対象の文字列
第二引数:置換before/after(※配列形式で複数指定可)

※公式ドキュメントでは、小文字を大文字に置換するやり方が紹介されています。
バイト数の大きいものが優先される等ルールがあるようです。

<?php
$trans = array("h" => "-", "hello" => "hi", "hi" => "hello");
echo strtr("hi all, I said hello", $trans);
?>

// 結果: hello all, I said hi

引数を二つだけ渡す場合は、二番目の引数を array('from' => 'to', ...) 形式の配列にしなければなりません。 返される値は文字列で、もとの文字列中にある配列のキーと同じ部分を対応する値で置換したものとなります。 一番長いキーから順に調べます。一度部分文字列の置換を行うと、 置換後の文字列がさらに置換の対象となることはありません。

筆者コメント

私は、例のように、
・文字列が記号で囲まれて
・かつ他の文字列と連結して、
・ひとつのカラムに保存されている
というデータを取り出す必要性があり、この合わせ技を使いました。
他にもいろんな使い方ができそうですので、何かのヒントになれば幸いです。

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

LaravelでMVCを利用してとりあえず表示させてみる

【概要】

1.ルーティングの設定

2.コントローラーの設定

3.ビューの設定

4.開発環境

1.ルーティングの設定

routes/web.php
Route::get('hoge', 'App\Http\Controllers\HogeController@index' );

ここで、Route::get('hoge', 'HogeController@index' );とすると、
”Target class [HogeController] does not exist”となってしまうので、最初からパスをコーディングしました。


2.コントローラーの設定

app/Http/Controllers/HogeControllers.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class HogeController extends Controller
{
    public function index() #---❶
    {
        return view('hoge.index'); #---❷
    }
}

❶:ここでindexアクションを定義しています。
❷:hogeフォルダのindex.phpファイルに返り値としてレンダリングするようにしています。


3.ビューの設定

resources/views/hoge/index.php
<html>
<head>
  <title>Hoge/Index</title>
</head>
<body>
  <h1>Index</h1>
  <p>HOGEHOGE</p>
</body>
</html>

簡単なHTML文しか書いていません。
「blade」テンプレートエンジンはまた後日説明します。

1~3を通じて下記が表記できます。
http://localhost:8000/hoge

スクリーンショット 2020-10-13 0.32.30.png

4.開発環境

PHP 7.4.10
Laravel 8.9.0
Apache 2.4.41

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

【PDO】複文禁止オプションの注意点(ATTR_EMULATE_PREPARES)

環境

OS:CentOS 7.3
PHP:7.1.21
mariadb:10.1.22

概要

PDOで PDO::ATTR_EMULATE_PREPARESfalse にすると、
(機能のひとつとして)セミコロンでつなげたSQL(複文)を禁止できるようですが、
コメント(--) の部分は複文として検知してくれないようです。

※ 以下、query() メソッド使用。

$sql .= "select * from table1;\n";
$sql .= "select * from table2;\n";

//検知してくれる OK
You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'select * from table2' at line 2

$sql .= "select * from table1;\n";
$sql .= "-- select * from table2;\n";

//検知しなかった???

$sql .= "select * from table1;\n";
$sql .= "-- select * from table2;\n";
$sql .= "select * from table3;\n";

//これは検知するけど3行目なんだ・・・
You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'select * from table3' at line 3

まとめ

複文禁止といっても「有効なSQLの複文」を禁止するみたいで、
コメント行は有効なSQLでないということなのでしょう。

コメント(--) を使ったSQLインジェクションがありますが、
PDO::ATTR_EMULATE_PREPARES の設定だけでは不十分ということですね。

コメント使用の攻撃に対しては、
プリペアドステートメントを併用して防ぎましょう。

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

Moodle 3.9 マニュアル - コースカテゴリ

原文

コースカテゴリーは、すべてのMoodleサイト参加者のためのコースを編成します。新しいMoodleサイトのデフォルトのコースカテゴリは「その他」です(これは名前を変更できます)。コースの作成者管理者、またはマネージャは、すべてのコースをその他のカテゴリに入れることができます。ただし、教師と生徒は、説明的なカテゴリに分類されていると、クラスを見つけやすくなります。

カテゴリ内のコースのリストには、デフォルトで教師と各コースの概要が表示されます。カテゴリ内のコース数が9(10以上)を超える場合、教師と要約のない短いリストが表示されます。

内容

1 カテゴリの追加
2 カテゴリの編集または移動
3 サブカテゴリの追加
4 カテゴリを非表示
5 カテゴリの並べ替え
6 カテゴリの深さの設定
7 コースカテゴリでのユーザーの役割の割り当て
8 関連項目
8.1 スクリーンキャスト

1 カテゴリの追加

ほとんどの人は、学部や大学ごと、またはトピックごとにコースを編成しています。後でコースを移動する時間を節約するために、多数のコースに入る前に、必ず少数のユーザーで組織スキームをテストしてください。

カテゴリの追加は非常に簡単です。

・[管理]> [サイト管理]> [コース]> [カテゴリの追加]に移動します
・必要な詳細を入力し、[カテゴリの作成]をクリックします。
・または、[管理]> [サイト管理]> [コース]> [コースとカテゴリの管理]に移動し、[新しいカテゴリの作成]リンクをクリックすることもできます。
・カテゴリページを表示している場合(またはコースカテゴリレベルで管理者権限しかない場合)は、ページの右上にある[コースの管理]ボタンをクリックしてから、[新しいカテゴリの作成]リンクをクリックします。

Addcategory.png
Addcategory.png

カテゴリが表示されている場合、ユーザーがカテゴリに入ると、コースのリストの上にコースカテゴリの説明が表示されます。

2 カテゴリの編集または移動

・コースカテゴリの詳細は、[管理]> [サイト管理]> [コース]> [コースとカテゴリの管理]で名前の横にあるアクションアイコンをクリックして編集できます。 「編集」を選択します。
・移動するカテゴリの横にある上/下矢印をクリックすると、カテゴリを上下に移動できます。名前の左側にあるチェックボックスをオンにしてから、ドロップダウンから[選択したカテゴリを移動する]を選択すると、カテゴリを一括移動できます。

Editmovecategories.png
Editmovecategories.png

3 サブカテゴリの追加

・コースのサブカテゴリがあると便利な場合があります。たとえば、カテゴリ「科学」があり、サブカテゴリ「生物学」、「化学」、「物理学」が必要な場合があります。
・名前の左側にあるチェックボックスをオンにして、ドロップダウンメニューから[選択したカテゴリを移動する]を選択すると、あるカテゴリを別のカテゴリのサブカテゴリにすることができます。次のアクションアイコンをクリックすると、新しい空のサブカテゴリを作成できます。 [管理]> [サイト管理]> [コース]> [コースとカテゴリの管理]でその名前に変更します。 [新しいサブカテゴリを作成する]を選択します。

4 カテゴリを非表示にする

・カテゴリは、[管理]> [サイト管理]> [コース]> [コースとカテゴリの管理]を選択し、非表示にするカテゴリの「目」アイコンをクリックすると、簡単に非表示または表示できます。非表示のカテゴリは、サイト管理者または「非表示のコースを表示する」機能を持つ管理者にのみ表示されます。

5 カテゴリの並べ替え

カテゴリは、[管理]> [サイト管理]> [コース]> [コースとカテゴリの管理]から、名前またはID番号の昇順/降順で並べ替えることができます。

300px-categorysort.png
カテゴリの並べ替え

カテゴリ内のコースも並べ替えることができます。新しいコースの追加を参照してください。

6 カテゴリの深さを設定する

[管理]> [サイト管理]> [フロントページ]> [フロントページの設定]から、フロントページの[カテゴリのリスト]または[コンボリスト]に表示されるカテゴリの数を制限できます。より深いレベルのカテゴリがリンクとして表示され、ユーザーはそれらを展開できます。

7 コースカテゴリでのユーザーの役割の割り当て

カテゴリレベルでマネージャを割り当てるには、カテゴリレベルでマネージャの役割を割り当てるを参照してください。

カテゴリ全体で教師または生徒の役割を登録するには、カテゴリの登録を参照してください。

8 関連項目

8.1 スクリーンキャスト

コースとカテゴリーの管理

Moodleフォーラムディスカッションの使用:

コースの概要が表示されない場合がある
教師がコースをカテゴリに分類できるようにする

カテゴリコース

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

【Laravel】いろいろ見たけどリポジトリパターンの実装ができなかった初心者のためにとりあえず実装するまでをシンプルに書く

3行で

  • UserのModelに紐づいたリポジトリパターンを実装する
  • コントローラではModelにタッチしないということを意識する
  • 5つのファイルをいじる

リポジトリファイルを作る

ディレクトリ /app の中に Repositories というディレクトリを作り、さらにその中に User というディレクトリを作り、この中にファイルを2つ作ります(この辺の構成は正直自由ですが)。

  • /app/Repositories/User/UserRepository.php(実装ファイル)
  • /app/Repositories/User/UserRepositoryInterface.php(インターフェイス)

この2つのファイルでModelを経由してDBにアクセスして、データを持ってきたりcreateしたりupdateしたりします。
今回はUser Modelに紐づくリポジトリパターンを作ります。つまりこれらを使ってUserのデータを持ってきたり更新したりします。コントローラではなく、これらのファイルで行うことになります。

1. 実装クラス

UserRepository.php
<?php

// Modelに紐づく2つのメソッド以外はコピペのような感覚で書いちゃって構わないです

namespace App\Repositories\User;

// Modelにアクセスする旨を書く
use App\User;

class UserRepository implements UserRepositoryInterface
{
  protected $user;

    /**
    * @param object $user
    */

  public function __construct(User $user)
  {
      $this->user = $user;
  }

  // 名前に紐づくUserのデータを1件持ってくる
  public function getUser($name)
  {
    return $this->user->where('name', $name)->first();
  }

  // 後述のコントローラから $request を受け取って、中に入った名前とメールアドレスでユーザーを作る
  public function createUser($request)
  {
    return $this->user->create([
      'name' => $request['name'],
      'email' => $request['email'],
    ]);
  }
}

その他のメソッドは上記を応用して書いてみてください!

2. インターフェース

UserRepositoryInterface.php
<?php

// 上の実装クラスに書いた、Modelに紐づく2つのメソッドを書いて使えるようにします

namespace App\Repositories\User;

interface UserRepositoryInterface
{
  public function getUser($name);

  public function createUser($request);
}

ServiceProviderに登録する

AppServiceProvider.php を編集する。
ここにリポジトリのファイルを使うために登録するイメージです。
もしエラーが出たら以下の記事も見てみてください。

【Laravel】リポジトリパターン実装におけるエラー Target [App\Repositories\UserRepositoryInterface] is not instantiable while building

AppServiceProvider.php
<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */

    /**
     * Bootstrap any application services.
     *
     * @return void
     */

    public function boot()
    {
        //
    }

    // インターフェースと実装クラスを登録
    public function register()
    {
        // 本記事ではタッチしませんが記事用のリポジトリも登録しておきます
        $this->app->bind(
            \App\Repositories\Article\ArticleRepositoryInterface::class,
            \App\Repositories\Article\ArticleRepository::class
        );
        $this->app->bind(
            \App\Repositories\User\UserRepositoryInterface::class,
            \App\Repositories\User\UserRepository::class
        );
    }
}

コントローラでリポジトリを呼び出す

UserController.php
<?php

namespace App\Http\Controllers;

// リポジトリを使うと宣言
use App\Repositories\User\UserRepositoryInterface;

// コントローラではModelにタッチしない
// use App\Models\User;

use Illuminate\Http\Request;

class UserController extends Controller
{
    // リポジトリ
    protected $UserRepository;

    public function __construct(
      // リポジトリ
        UserRepositoryInterface $userRepository
    )
    {
      // リポジトリ
        $this->UserRepository = $userRepository;
    }

    // 中略

    public function show($name)
    {
        // リポジトリのメソッドに引数を渡して呼び出す
        $user = $this->UserRepository->getUser($name);

        return view('users.show', [
            'user' => $user,
        ]);
    }

    public function store($request)
    {
        // フォームから受け取った $request をリポジトリのメソッドに渡し、Userデータを作る
        $this->UserRepository->createUser($request);

        return redirect()->route('home');
    }
}

以上です。
データが渡っているかがわからない、うまくいかない場合は dd($request) などを使って検証してください!

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

クラスの関係をひと目で確認 PhpStormクラス図

[Something went wrong]()
私は仕事でPHP・Laravelを使用していますが、古くからある大規模システムなど、
ベリーファットなコントローラや無数のメソッドがあったり、追うのが大変なことがあります。
そのときにPhpStormの機能、UMLクラス図作成を使用すると便利です。

どんな図?

継承元のクラスが青い実線で表示され、破線は依存関係(use 宣言)を示しています。
各クラスごとのメソッドをpublic, protectedに分けて表示してくれます。
Screen Shot 2020-10-02 at 21.11.39.png

2次元の図で表現することは、その情報を記憶しやすくする効果があります。人間の頭はイメージのほうが覚えやすいため、「形」で表現してあると、「2つのクラスの上に描かれていたスーパークラスがあったけど名前は何だっけ」というように、イメージの位置関係とあわせて内容が記憶しやすくなります。

平澤 章. オブジェクト指向でなぜつくるのか 第2版 (Japanese Edition) (Kindle Locations 3425-3429). Kindle Edition.

HOW

まず、UMLプラグインが入っているか確認しましょう。
Screen Shot 2020-10-02 at 22.24.55.png

参照したいクラスを右クリックし、Diagrams > Show Diagramsを選択すると生成されます!
Screen Shot 2020-10-02 at 21.56.05.png

公式ページ

https://pleiades.io/help/phpstorm/class-diagram.html

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

yps並走備忘録 Task4 WordPress環境構築

更新を大分サボってたので大分時間が経ってしまいましたが、Task 4の備忘録を思い出しつつ書いてみます。
ypsはLaravelでの開発がメインですが、今回はちょっと寄り道的なタスクでWordPressの構築を行います。

事前準備

wgetがインストールされていない場合はインストールしましょう
sudo yum install wget -y

WordPressのセットアップ

※記事執筆時(2020/10/12)の最新版は5.5

tmpディレクトリに最新版のWPをダウンロードして解凍
1. cd /tmp 1
2. wget https://ja.wordpress.org/latest-ja.zip
3. unzip ./latest-ja.zip

ディレクトリを移動
4. mv wordpress '任意のディレクトリ名' ※任意の名前に変更(なるべく一般的な名前は避ける)
5. mv '任意のディレクトリ名' /var/www/html/

MySQLにWP用のデータベースを作成
6. mysql -u root -p でMySQLにログイン

以下MySQL Cliでの操作
7. create database '任意のDB名'; ※データベース名はなるべく複雑なものの方がベター
8. grant all on ypswpdb.* to '任意のuser名'@localhost identified by '任意のパスワード'; データベースの権限を委譲しています
※ここで設定したユーザー名とパスワードを忘れてしまうと後々面倒なのでどこかにメモるなりしておく
9.設定し終わったら exit;

WP設定ファイルの更新
cd /var/www/html/yps-wp/
cp -p wp-config-sample.php wp-config.php

まずは下記を変更します。

define( 'DB_NAME', ' #7で設定したDB名' );
define( 'DB_USER', '#8で設定したuser名' );
define( 'DB_PASSWORD', '#8で設定したパスワード' );

続いて下記を更新します。

更新時にはコメントにあるようにhttps://api.wordpress.org/secret-key/1.1/salt/ にアクセスすると自動でシークレットキーを生成してくれるので便利です(アクセスする度に新しいキーが生成されます)。

define( 'AUTH_KEY',         'put your unique phrase here' );
define( 'SECURE_AUTH_KEY',  'put your unique phrase here' );
define( 'LOGGED_IN_KEY',    'put your unique phrase here' );
define( 'NONCE_KEY',        'put your unique phrase here' );
define( 'AUTH_SALT',        'put your unique phrase here' );
define( 'SECURE_AUTH_SALT', 'put your unique phrase here' );
define( 'LOGGED_IN_SALT',   'put your unique phrase here' );
define( 'NONCE_SALT',       'put your unique phrase here' );

最後に下記を更新します

$table_prefix = '任意の文字列_';

:wqで保存したら一先ずWPの設定は完了

ファイルとディレクトリのオーナー権限を変更
cd /var/www/html
sudo chown -R centos:nginx /var/www/html/wwpp/
sudo find /var/www/html/wwpp/ -type f -exec chmod 664 {} \;
sudo find /var/www/html/wwpp/ -type d -exec chmod 775 {} \;

次にnginxの設定を変更してLaravelからWPへルートディレクトリを変更します
sudo vi /etc/nginx/conf.d/default.conf

編集内容は以下の通り

root /var/www/html/yps/public;
#↓に変更
root   /var/www/html/wwpp;

#追記
location /wp-config.php {
  deny all;
}

:wqで設定を保存したらphp-fpmとnginxを再起動します
sudo systemctl restart php-fpm && sudo systemctl restart nginx

※WPとLaravelを同時に動かしたい場合は下記のリンクを参照

参考:LaravelとWordPressの共存

ドメインネーム(設定してない場合はインスタンスのpublic IP)でブラウザからアクセス
WPのインストール画面が出ていれば成功です。
ただし、このままだとテーマやプラグインのインストールができないので少し設定をいじります。

cd wp-content/plugins/
wget https://downloads.wordpress.org/plugin/ssh-sftp-updater-support.0.8.2.zip
unzip ./ssh-sftp-updater-support.0.8.2.zip
rm http://ssh-sftp-updater-support.0.8.2.zip
sudo chown -R centos:nginx ./ssh-sftp-updater-support/

正常にプラグインがインストールされていればテーマをインストールできるようになっているはずです。
念のため下記の参考リンクを使ってできる範囲でのセキュリティ対策もしておきましょう

参考リンク:簡単にできるWordPressのセキュリティ対策x12

以上でWPの構築は終了です。


  1. /tmpは再起動時にディレクトリが消えるので、wgetでインストールするときなどに便利 

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

Moodle 3.9 マニュアル - コースをリセットする

原文

内容

1 概要
2 リセット方法-ステップバイステップ
3 一般的なリセットオプション
3.1 コース開始日
4 ロールリセットオプション
5 成績表リセットオプション
6 グループリセットオプション
7 アクティビティリセットオプション

1 概要

これにより、アクティビティやその他の設定を保持したまま、一連のユーザーデータを空にすることができます。アイテムを選択するときは、選択したユーザーデータをこのコースから完全に削除することに注意してください。

一般、役割、成績表、グループ、アクティビティデータのカテゴリで、削除するユーザーデータを詳細なレベルで選択できます。

注:コースをリセットできるのは、コースのリセットのケーパビリティを持つユーザー(デフォルトではマネージャーと教師)のみです。

2 リセットする方法-ステップバイステップ

  1. ログインして、リセットするコースエリアに移動します
  2. 特定のアクティビティをリセットすることは元に戻せないため、ユーザーデータを含むエリアのバックアップを作成したことを確認してください。これはスナップショットであり、必要に応じて復元できます。
  3. お住まいの地域の管理ブロックで、[リセット]をクリックします
  4. [詳細を表示]ボタンをクリックして、そのカテゴリのすべてのオプションを表示します
  5. オプションに基づいて選択を行います(これらの詳細については、以下を参照してください)
  6. [リセット]ボタンをクリックします
  7. お住まいの地域に戻り、物事が希望どおりであることを確認してください。

3 一般的なリセットオプション

(リセットする前に)リセットする前に、コース内にある情報を必ずバックアップする必要があります。コースをバックアップするときは、必ずユーザー情報を使用してバックアップしてください。そうすれば、別のグループまたは部門にリセットする前に、コースを受講したもののバックアップデータを取得できます。

3.1 コース開始日

新しくリセットされたコースの新しいコース開始日を設定し、すべてのカレンダーイベント、コメント、コースとアクティビティの完了データ、およびコースに添付されているユーザーメモを削除できます。コースログは削除されないことに注意してください(MDL-43274を参照)

注:新しいコース開始日を設定すると、すべてのコース日付が同じ量だけシフトされます。

4 ロールリセットオプション

これらのロールリセットオプションを使用すると、コース内の特定のロールを持つすべてのユーザー(学生など)の登録を解除したり、コースに固有のすべてのロールオーバーライドとロール割り当てを削除したりできます。これは、コースのコンテキスト外でのユーザーロールの割り当てには影響しません。

5 成績表のリセットオプション

成績表のリセットオプションを使用すると、すべての成績表の項目とカテゴリを削除したり、コース内のすべての記録された成績を削除したりできます。成績表のリセットには2つのオプションがあります。

すべての成績を削除-コース内に手動で追加されたすべての成績アイテムを、上書き、除外、非表示、およびロックされた成績に関する成績とデータとともに削除します。このオプションでは、アクティビティグレードのアイテムは削除されないことに注意してください。

すべてのアイテムとカテゴリを削除する-オーバーライド、除外、非表示、ロックされたグレードのグレードとデータとともに、すべてのカテゴリと関連する手動で追加されたグレードアイテムを削除します。このオプションでは、アクティビティグレードのアイテムは削除されないことに注意してください。

これらの成績は引き続きユーザーのアカウントに対して記録されることに注意してください。

6 グループリセットオプション

グループリセットオプションを使用すると、コースで作成されたすべてのグループを削除したり、コース内のグループからすべてのユーザーを削除したりできます。

コースで作成されたすべてのグループを削除したり、コース内のグループからすべてのユーザーを削除したりすることもできます。

7 アクティビティリセットオプション

コース内で使用されるアクティビティに応じて、これらの学習オブジェクトに関連付けられているユーザーデータを削除するオプションが提供されます。これには、選択肢への回答、クイズの試行、フィードバックの回答、フォーラムの投稿(選択したフォーラムの種類から)、用語集のエントリなどが含まれます。

クイズの場合、次のことができます。

すべての試行を削除します
ユーザーオーバーライドとグループオーバーライドを削除する
ワークショップでは、次のことができます。

すべての提出物を削除する
すべての評価を削除する
セットアップフェーズに切り替えます
Wikiの場合、次のことができます。

ページを削除する
タグとコメントを削除する

新しいコース開始日を指定することもできます。

カテゴリバックアップ

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

CodeIgniter4でTwigを使う(Composer利用)

CodeIgniter4でもtwigを使いたい

前の記事ではCI4にSmartyを組み込みましたが、近頃はTwigをテンプレートエンジンに採用しているケースも多いのではないでしょうか?
本記事ではCI4にTwigを利用する方法の解説です。

Twig for CodeIgniter4を導入する

CI4上でTwigを利用するには拙作、CodeIgniter4 for Twigを使うと手っ取り早いです。
CI4との統合は最低限の実装にとどめているので動作は軽いと思います。

例は「CodeIgniter4をインストール (Composer利用)」での導入を終えた流れでインストールをした場合です。

composerによるTwig for CodeIgniter4の導入
$ cd /home/ci4test
$ composer require sarah-systems/ci4twig

以下は、概ねREADME.mdからの抜粋です。

使い方

デフォルトでは、Twig関連のパスは自体は次のような設定で動作するようになっています。

種類 パス
テンプレート app/Views
キャッシュ writable/twig/cache

writableが正しく書き込み可能な場合、キャッシュディレクトリは自動的に生成されます。
もしエラーが起きた場合は、これらのディレクトリを作って適切なパーミッションを与えることで動作します。

もしこのパスを変更したい場合は.envファイルに次のパラメータをセットすることで、任意のパスに変更可能です。

CI4Twig.TemplateDir = /path/to/TemplateDir
CI4Twig.CacheDir = /path/to/CacheDir

これ以外にも.envでは、TwigのDebugフラグのOn/Offとデフォルトの拡張子を設定できます。

CI4Twig.Debug = 1 または 0
CI4Twig.DefaultTemplateExtension = .html.twig

view()

CI4のview関数をTwig用にCI4Twigというnamespaceで定義しています。

利用する際はappディレクトリ直下のCommon.phpに次を追記してください。

require_once ROOTPATH . "vendor/sarah-systems/ci4twig/src/Common.php";

使用法はCI4のview関数と同じですが、関数の利用時には名前空間を指定するか、事前にエイリアスを張ってください。

\CI4Twig\view('template.html.twig');

または

use function CI4Twig\view as view;
view('template.html.twig');

拡張子.html.twigCI4Twig.DefaultTemplateExtensionで設定されたものです。無指定の場合は.html.twig)は省略可能です。

\CI4Twig\view('template');

view関数の第2パラメータはTwig変数$CIにアサインされます。

$data = [ 'apple' , 'banana' , 'lemon' ];
\CI4Twig\view('template',$data);

Twigのtemplate上では

{{ CI.0 }} ← appleが表示されます。

第3引数の$optionsは無視されます。

Service

CI4のServiceが利用可能です。

use CI4Twig\Config\Services;

$time = date('Y-m-d H:i:s');
$twig = Services::twig();
$twig->Environment->addGlobal('time',$time);
$twig->Environment->display('template.html.twig');

次回はCI4のValidationの使い方について簡単に説明します。

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

hiddenの使い方

hiddenの使い方

hiddennは疑似要素として扱うことができる。

ctpファイル
echo $this->Form->hidden('isSelectArea',["id" => "isSelectArea"]);

jQueryで疑似要素にval()で値を与える。

js
$(function () {
    $(document).on("change", "#area", function () {
        $("#isSelectArea").val(true); //地域を選択したときにコントローラーで条件分岐をしてaddアクションにリダイレクトさせるためのhidden
        $("#UserConfirmForm").submit(); //一旦confirmアクションに飛ばす
    });
});


最後にコントローラで疑似要素を元にif文などで条件分岐できる

controller
if ($this->request->data["User"]["isSelectArea"]){ 
    //もしisSelectAreaというキーを持っていればここで処理
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

SQLでテーブルにデータ挿入がうまくいかない時

テーブルを作成して、実行すると以下のエラーが発生してしまいました。

エラー内容

SQLSTATE[22003]: Numeric value out of range: 1264 Out of range value for column 'phone_number'
(phone_numbeカラムに入ってる値が指定してる範囲を超えています)

phone_numberのカラムタイプに ”integer” を指定していて、それが原因でした。

$table->integer(‘phone_number');

”integer(INT)” には、最小値〜最大値まで決められた数値があり、それがこちらです。

(ENEEU).png

INTの部分を見てみると、最小値が2〜最大値が8までとなっています。

私は、phone_numbeのカラムに “08022339999” と指定していて、最大値の8を超えた9を入れてしまっていました。
そのため、エラーが発生してしまったのです。

カラムタイプをbigintに変更すれば解決です。

参考記事
https://dev.mysql.com/doc/refman/5.6/ja/integer-types.html

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

mysql プリペアドステートメント

プリペアドステートメントとは??

sqlのコードをわかりやすくしたテンプレートのようなものです。

書き方
// SQL文の作成
$stmt = $mysqli->prepare("INSERT INTO nekosan (
name, price, better_before, modify_datetime, create_datetime
) VALUES (
?, ?, ?, ?, ?
)");
// パラメータを設定
$stmt->bind_param( 'sisss', $name, $price, $better_before, $date,
$date);

// 実行
$res = $stmt->execute();
$stmt->close();

name, price, better_before.png

‘sis’とは、$nameや$priceのデータ型を意味しています。

$nameはstring 「s」

$priceはinteger 「i」

$better_beforeはstring 「s」

?(ハテナ)には、bind_paramで指定したデータが入ってきます。

参考記事; https://gray-code.com/php/prepared-statement-by-mysqli/

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

【xampp+LibXL】libxlをxamppに導入

自分用のメモとして残します。
LibxlのLinuxへのインストールはそこそこありましたが、
Win環境+xamppへのインストール方法があまりにも少なすぎるため、メモ程度ですが残します。

■やり方

1. php_excel.dllインストール

ダウンロード

下記サイトから対応するPHPのバージョンのビルドをダウンロードする。
https://www.apachelounge.com/viewtopic.php?t=6359

php_excel.dll設置

解凍して以下のファイルをxamppに設置
\ext\php_excel.dll\xampp\php\ext直下に設置。

2. libxl.dllインストール

ダウンロード

下記サイトからLibXLをダウンロードする。
https://www.libxl.com/download.html

libxl.dll設置

解凍して以下のファイルをxamppに設置(2か所)
\libxl-3.9.2.1\bin\libxl.dll\xampp\apache\bin直下に設置。
\libxl-3.9.2.1\bin\libxl.dll\xampp\php直下に設置。

3. php.ini変更

下記をphp.iniに追記。
トライアルで使う場合は、license_name、license_keyは無くてもOK。

php.ini
[excel]
extension=php_excel.dll
excel.license_name=""
excel.license_key=""

以上

■さいごに

導入後の動作はぼちぼちググれば出てくるので、そちらを参考してください。。
また、今回はwindows上のxamppへのLibxl導入になります。
そのため、当該記事と同環境の場合はwindows用のライセンスでないとライセンスの認証が通らないようになっているため、製品版をwindowsで使用する場合はLinux用のライセンスでなく、win用のLibxlライセンスを取得して動作確認をしましょう。

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

[DDD Tips] アプリケーション層とドメイン層の区分けについて

はじめに

記事を書く時間が取れないため、単発のTipsを書くことにしました。
ドメイン駆動設計の現場で気づいたことや、自分が理解に苦しんだポイントなどを簡易的に取り上げていきたいと思います。

この記事では、ドメイン駆動設計を始めようとしている方を対象に書いています。
「DDDの書籍は沢山読んだ!理解した気がする!」という段階の方に向いていると思います。
概念を理解したつもりでも、いざコードを書こうとすると手が止まってしまう。

今回は、アプリケーション層(ユースケース)とドメイン層の実装で判断に迷いそうな箇所を取り上げていきたいと思います。

※ 当記事はLaravelを例に書いております。

例題1

  • 記事の投稿機能を持つアプリケーション
  • 投稿された記事をユーザーに対して表示するユースケース

BAD Practice

ShowPostUseCase.php
<?php

// ユースケースのどこか
final class ShowPostUseCase
{
    private PostRepositoryInterface $postRepository;

    public function __construct(PostRepositoryInterface $postRepository)
    {
        $this->postRepository = $postRepository;
    }

    public function __invoke(Request $request): Post
    {
        $post = $this->getPostByRequest($request);

        abort_if(!$post, 404);

        $this->validatePost($post);

        return $post;
    }

    private function getPostByRequest(Request $request): ?Post
    {
        return $this->postRepository->find(
            PostId::of($request->input('id'))
        );
    }

    private function validatePost(Post $post)
    {
        // 記事をユーザーに表示しても良いかの判断
        // 公開意外のステータスや、公開期間外だったら見せない
        if (!$post->hasPublicStatus() || !$post->hasActivePeriod())
            abort(404);
    }
}
Post.php
<?php

// ドメインエンティティー
final class Post extends Entity
{
    protected PostId $id;

    protected string $title;

    protected string $content;

    protected PostStatus $status;

    protected PostPublishPeriod $period;

    public function hasPublicStatus(): bool
    {
        return $this->status->equals(PostStatus::PUBLIC);
    }

    public function hasActivePeriod(): bool
    {
        return $this->period->isActive();
    }
}

手抜き満載のコードですが、とりあえず伝われば良しとします。
上記例のvalidatePostメソッドにて、記事を一般ユーザーに見せても良いかどうかの確認を行っています。
何も問題ないように見えますが、実は必要以上のドメイン知識がユースケース層に含まれています。

NGの理由1

ずばり、ユースケース側で投稿記事のルールを知ることなるからNGです。
記事がステータスを持っていること、公開でない場合はユーザーに見せることができないということ、
公開期間が定められていること、期間外はユーザーに見せられないということなど、
ユースケースに必要以上の知識が求められます。

NGの理由2

1つの理由にあったルールは、いわゆるビジネスルールに該当するかと思います。

場合によっては、特定の権限を持つユーザーには非公開記事を見せる仕様にするかもしれないし、
記事が持つ属性によって、掲載期間が変動するかもしれない。

これらの条件(ビジネスルール)をユースケースで取り扱うとなれば、ドメインそのものの意味が薄れてしまうので、
ユースケースでは判断をせずに、ドメイン側で解決するようにしましょう。

Good Practice

ShowPostUseCase.php
<?php

final class ShowPostUseCase
{
    private PostRepositoryInterface $postRepository;

    public function __construct(PostRepositoryInterface $postRepository)
    {
        $this->postRepository = $postRepository;
    }

    public function __invoke(Request $request): ?Post
    {
        $post = $this->getPostByRequest($request);

        abort_if(!$post, 404);

        $this->validatePost($post);

        return $post;
    }

    private function getPostByRequest(Request $request): ?Post
    {
        return $this->postRepository->find(
            PostId::of($request->input('id'))
        );
    }

    private function validatePost(Post $post)
    {
        // 記事をユーザーに表示しても良いかの判断
        // 判断の中身はユースケースで知る必要がないので、ドメインに任せる
        abort_if(!$post->isVisible(), 404);
    }
}
Post.php
<?php

final class Post extends Entity
{
    protected PostId $id;

    protected string $title;

    protected string $content;

    protected PostStatus $status;

    protected PostPublishPeriod $period;

    private function hasPublicStatus(): bool
    {
        return $this->status->equals(PostStatus::PUBLIC);
    }

    private function hasActivePeriod(): bool
    {
        return $this->period->isActive();
    }

    public function isVisible(): bool
    {
        return $this->hasPublicStatus() && $this->hasActivePeriod();
    }
}

改善内容

  • ユースケースでは投稿記事の閲覧条件(判断基準)を知る必要がないので、ドメイン層に判断を任せる
  • ビジネスルールをドメインに集約したことで、ビジネスルールが増えても管理がしやすい。ユースケースによるバグが減らせる。
  • コードの再利用性が自然と上がる
  • テストが書きやすくなる(投稿エンティティーをモックして、ユースケースの振る舞いをテスト、ビジネスルールは単独でテストできるなど)

おわりに

ルールがシンプル過ぎる場合に、判断ミスがしやすい箇所だと感じましたので、
簡単なTipsとして投稿させて頂きました。ルールがシンプル過ぎるゆえに、
ビジネスロジックであることを見落としてしまうケースではないかと思います。

単なるオブジェクト指向とDDDの決定的な違いだと思ったりもします。

今回は、参考になる内容かどうかも知りたかったので、ニーズが合う場合は
また時間ができたタイミングで単発記事を書きたいと思います。

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

Moodle 3.9 マニュアル - コースをアップロードする

原文

注:このページは、テキスト(.csv)ファイルを使用したコースの作成に関するものです。コースのバックアップを.mbzまたは.tgz形式でアップロードする場合は、コースの復元を参照してください。

内容

1 コースをアップロードする
1.1 短いファイルの例
2 テキストファイルの作成
2.1 コース情報フィールド
2.1.1 登録フィールド
2.1.2 役割の名前変更
2.2 コースアクションフィールド
2.3 必須フィールド
2.4 インポートオプション
2.5 コースプロセス
2.6 デフォルトのコース値
3 速度を上げる
4 関連項目

1 コースをアップロードする

新しいコースの作成に加えて、コースのアップロード機能を使用して、コースを更新または削除したり、別のコースからコンテンツをインポートしたりすることもできます。この機能を使用してコーステンプレートを作成する方法については、新しいコースの追加を参照してください。

1つ以上のコースをアップロードするには

  1. [管理]> [サイト管理]> [コース]> [コースのアップロード]に移動します
  2. CSVファイルをドラッグアンドドロップするか、[ファイルの選択]ボタンをクリックして、ファイルピッカーでファイルを選択します
  3. 適切なインポートオプションを慎重に選択し、プレビューボタンをクリックします。

375px-26uploadcourses.png
コース管理画面のアップロード
375px-uploadcoursesresults.png
コースが正常にアップロードされました

注:コマンドラインツールadmin / tool / uploadcourse / cli /uploadcourse.phpを使用することもできます。

Webインターフェイスを使用する場合は、[プレビュー]オプションを使用して、プレビューされた行でエラーが検出されたかどうかを確認します。アップロードを続行し、コースで何か問題が検出された場合、それは無視されます。

1.1 短いファイルの例

uploadcourse.csv:

注:ショートネーム、フルネーム、およびカテゴリは必須です。

カテゴリフィールドはカテゴリのIDを取り、デフォルトのカテゴリその他はID1を持ちます。カテゴリはすでに存在している必要があります。存在しないカテゴリIDを入力すると、アップロードのプレビュー中に「IDでカテゴリを解決できませんでした」というエラーが表示され、そのカテゴリのコースは作成されません。

shortname,fullname,category,summary,enrolment_1,enrolment_1_role,enrolment_1_enrolperiod,role_student
courserestored,Course restored,1,a summary,manual,student,1 month,
courserestored2,Course restored 2,1,a summary,,,,
courserestored3,Course restored 3,1,a summary,,,,padawan
courserestored4,Course restored 4,1,"a summary, with comma",manual,student,1 month,padawan

アイテム間にスペースがないことに注意してください。

2 テキストファイルの作成

コースをアップロードするためのテキストファイルはCSVファイルである必要があります。コース情報とコースアクションの2つのカテゴリに分類される次の列を受け入れます。

2.1 コース情報フィールド

これらの設定のほとんどは、コースの設定ページで利用できます。詳細については、コース設定を参照してください。フィールド名は小文字でなければなりません。

shortname
ショートネーム
fullname
フルネーム
idnumber
コースID番号
category
これは、コースを配置するカテゴリ(カテゴリURLにあります)のデータベース識別子です。これは、category_idnumberおよびcategory_pathよりも優先されます。
category_idnumber
コースを配置するカテゴリのID番号([カテゴリの編集]ページで見つけて編集可能)。これはcategory_pathよりも優先されます。
category_path
コースを配置するカテゴリのパス。「映画」カテゴリの下にある「サイエンスフィクション」という名前のカテゴリにコースを配置する場合、提供する値は次のとおりです。

映画/サイエンスフィクション

。セパレータは
[スペース] / [スペース]

。また、カテゴリは存在する必要があり、作成されないことに注意してください。コースをトップレベルのカテゴリ「映画」に配置する場合、提供する値は次のとおりです。

映画

visible
コースが表示されている場合は1、非表示の場合は0
startdate
コースが始まる時間。この値は、タイムスタンプを生成するためにPHP関数strtotimeに渡されることに注意してください。例01.12.2014(2014年12月1日)
enddate
コースが終了する時間。 startdateと同様に、この値はタイムスタンプを生成するためにPHP関数strtotimeに渡されることに注意してください。例01.12.2014(2014年12月1日)
summary
コースの概要
format
使用するコース形式。これは有効なコース形式プラグイン名である必要があります。例えば。週、トピック。
theme
使用するテーマ
lang
使用する言語
newsitems
ニュース項目の数
showgrades
1は成績表を生徒に表示し、0は非表示にします。
showreports
1はアクティビティレポートを表示し、0は非表示にします。
legacyfiles
1はレガシーコースファイルを有効にし、0は有効にしません。
maxbytes
コースの最大アップロードサイズ(バイト単位)。サイト制限には0を使用します。
groupmode
グループなしの場合は0、個別のグループの場合は1、表示可能なグループの場合は2。
groupmodeforce
グループモードを強制する場合は1、それ以外の場合は0を入力します。
enablecompletion
1はアクティビティの完了を有効にし、0は有効にしません。
tags
コースに追加するタグのコンマ区切りリスト。既存のタグは削除されます。複数のタグを引用符で囲みます。

2.1.1 登録フィールド

一部のフィールドは、登録方法を有効にして構成するために作成できます。フィールドには、登録メソッド名としてenrolment_ [number]、プロパティとしてenrolment_ [number] _propertyという名前を付ける必要があります。

enrolment_ [number]
登録方法の名前(例:手動、ゲスト、自己)
enrolment_ [number] _delete
1に設定すると、この登録方法がコースから削除されます。他のすべてのプロパティは無視されます。
enrolment_ [number] _disable
1に設定すると、コースからこの登録方法を無効にします。他のすべてのプロパティは無視されます。
enrolment_ [number] _startdate
登録開始日。この値は、PHP関数strtotime()に渡されます。
enrolment_ [number] _enddate
登録終了日。この値は、PHP関数strtotime()に渡されます。
enrolment_ [number] _enrolperiod
秒数、または「4日」などのstrtotime()によって理解される値でない場合。
enrolment_ [number] _role
役割の短縮名
enrolment_ [number] _ [property]
指定された登録方法によってプロパティが理解される場合
enrolment_ [number] _password
コース登録キー

注:アップロードコースは、まだすべての登録方法(MDL-43127)と互換性があるわけではありません。

enrolment_1:manual
enrolment_1_role:student
enrolment_1_enrolperiod:month

enrolment_2:self
enrolment_2_startdate:2013-01-30

2.1.2 役割の名前変更

次のパターンを使用して、一部の役割の名前を変更します。

role_ [shortname]
ロールの新しい名前[shortname]。

role_student:見習い
role_teacher:マスター
role_mycustomrole:ジェダイ

教師の役割の短縮名はeditingteacherであり、非編集教師の短縮名はteacherであることに注意してください。

2.2 コースアクションフィールド

これらの設定は、コースプロセスパラメータよりも優先されます。

delete
コースを削除するには1
rename
コースの名前を変更するショートネーム
backupfile
コースにインポートするバックアップファイル(.mbz)への絶対パス。

(これは、コースへのフルパスを意味します(例:/home/yourmoodle/public_html/moodle27/transfert/backup.mbz)。これがわからない場合は、[サイト管理]> [サーバー]> [PHP情報]のinclude_pathを確認してください。)

templatecourse
コンテンツをインポートするコースの短縮名
reset
コースをリセットするには1

2.3 必須フィールド

shortname
このフィールドは、新しいコースの作成を除いて、すべての操作で必須です。詳細については、コースプロセスパラメータのショートネームテンプレートの詳細を参照してください。
fullname
新しいコースを作成するときに必要です。
category、category_idnumber、category_path
コースを作成するときに、これらの1つが必要です。

2.4 インポートオプション

予期しない動作を防ぐには、ツールで実行できるようにすることを指定する必要があります。

Upload mode
これにより、コースを作成および/または更新できるかどうかを指定できます。
Update mode
コースの更新を許可する場合は、コースを何で更新するかをツールに指示する必要もあります。
Allow deletes
削除フィールドが受け入れられるかどうか
Allow renames
名前変更フィールドが受け入れられるかどうか
Allow resets
リセットフィールドが受け入れられるかどうか

2.5 コースプロセス

これにより、アップロードされたすべてのコースに対して実行するアクションを指定できます。

Shortname template
ショートネームなしでコースを作成している場合は、このフィールドを使用してショートネームを自動的に生成できます。このフィールドは、ID番号の%iと要約の%fの2つのプレースホルダーを受け入れます。
Restore file
作成/更新後にコースにインポートするバックアップファイル(.mbz)。
Restore from course
作成/更新後にコンテンツをインポートするコースの短縮名。
Reset after upload
コースを作成/更新した後にコースをリセットするかどうか。

2.6 デフォルトのコース値

これらは、CSVファイルで指定されていないすべてのフィールドのWebインターフェイスで設定できる値です。これらはコースの作成時に常に使用されますが、更新時に指定された場合にのみ使用されることに注意してください(更新モードを参照)。

3 速度を上げる

バックアップファイルまたは別のコースのコンテンツをインポートするときは、keeptempdirectoriesonbackupの設定を有効にすることをお勧めします。これにより、同じソースから複数回インポートする場合、アップロードのプロセスが大幅にスピードアップします。

4 関連項目

デモのスクリーンキャスト:コースの一括作成
ユーザーをアップロードする
MaryCoochによるMoodle2.6ブログ投稿でのコーステンプレートの作成

カテゴリーコース

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

curl で unable to load client key: -8178 エラーが出た

要件

ルート証明書を使用して、とあるホストにアクセスする用事があった。
ゴールは、PHP の cURL 関数でアクセスできること。

環境

  • CentOS 7
  • php7.3
    • cURL 関数を使用

事象

php の cURL 関数でエラーが発生

証明書のパスを指定して cURL 関数を実行してみたところ、
以下のようなエラーが出てしまった。

# オプション定義(抜粋)
$ch = curl_init( "https://xxxx" );
curl_setopt( $ch, CURLOPT_SSLCERT, "./aaa.pem" );
curl_exec( $ch );

# 実行結果
cURL の戻り値:58
curl_error のメッセージ:
  unable to load client key: -8178 (SEC_ERROR_BAD_KEY)

調査

CUI の curl でアクセスしてみる

では、同じ URL に対して CUI の curl で試したらどうなるか確認。

# コマンド
curl -v https://xxxx --cacert ./aaa.pem

# 結果
< HTTP/1.1 200 OK
~省略~
*   CAfile: ./aaa.pem
  CApath: none
~省略~
curl: (58) unable to load client key: -8178 (SEC_ERROR_BAD_KEY)

同じエラーが出てしまった。

エラーメッセージを見てみる

curl のエラーの中に
CApath: none
という文言があった。

一つ上にある CAfile には引数の --cacert の値が入っているので、
別の引数で指定しないといけない?

調べてみると、--capath という引数で
CApath に証明書のディレクトリを指定できるらしい。
早速試してみる。

解決編

curl に capath オプションを指定してみる

# コマンド
curl -v https://xxxx --capath <aaa.pem が存在するディレクトリのパス>

# 結果
< HTTP/1.1 200 OK
~省略~
*   CAfile: /etc/...省略.../ca-bundle.crt
  CApath: <aaa.pem が存在するディレクトリのパス>
~省略~
URL のデータ

取得成功!
ちなみに、ディレクトリは絶対パスでも相対パスでも指定可。

PHP の cURL 関数でも試してみる

PHP の cURL 関数では CURLOPT_CAPATH というオプションで
証明書のパスを指定できるらしい。

# オプション定義
curl_setopt( $ch, CURLOPT_CAPATH, "<aaa.pem が存在するディレクトリのパス>" );

# 実行結果
成功(CUI と同じ)

ファイル名ではなくディレクトリの指定が必要だったんですね。

追記

OS の証明書ストアに登録する方法

独自の証明書をOSの証明書ストアに登録すれば、
CApath の指定が無くても読み込んでくれます。
 ※この方法が普通みたいですね;

# cp aaa.pem /usr/share/pki/ca-trust-source/anchors/
# update-ca-trust

ただし、この場合は独自証明書が OS 全体に適用されてしまうため、
ユースケースによっては、前述の様に証明書パスを指定した方が良いかもしれません。

ユースケースの例としては・・・

  • 独自証明書をサービス固有で定義したい場合
    • サービス毎にディレクトリを作っており、
      他のサービスに影響を与えたくない場合など
    • OS 自体にインストールしないので、
      Ansible などでの配布時に OS にほぼ影響を及ぼさない
  • 証明書を cron などで自動的に取得 & 配置 している場合
    • 外部サービスの証明書が頻繁に更新される場合、
      証明書ストアを更新するよりも自動化の手間が省ける

証明書ファイルを明示的に指定

CURLOPT_CAPATH を指定していれば、証明書ファイル名を指定しなくても
ディレクトリ内にあるファイルから自動的?に証明書を見つけてくれますが、
CURLOPT_CAINFO で明示的に証明書パスを指定することもできるようです。
 ※その場合でも CURLOPT_CAPATH は指定必須

# オプション例
curl_setopt( $ch, CURLOPT_CAINFO , "./aaa.pem" );
curl_setopt( $ch, CURLOPT_CAPATH, "<aaa.pem が存在するディレクトリのパス>" );

業務で長く使っていて色々なサーバの証明書が混在していたり、
有効期限切れのものが混ざっていたりしたら
この方が安全かもしれません。

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

composerでメモリ制限エラーがでた話

エラー内容

Fatal error: Allowed memory size of 1610612736 bytes exhausted (tried to allocate 4096 bytes) in phar:///usr/bin/composer/src/Composer/DependencyResolver/RuleWatchGraph.php on line 52
Check https://getcomposer.org/doc/articles/troubleshooting.md#memory-limit-errors for more info on how to handle out of memory errors.

メモリーが足りないよ!ってエラーが帰ってきた

なので下記コマンドでメモリーの許可されている容量を調べると

php -r 'phpinfo();' | grep memory_limit
memory_limit => 128M => 128M

128Mじゃそりゃ足りないわな,,,,

ので下記コマンドを実行

tarminal
COMPOSER_MEMORY_LIMIT=-1 composer 〇〇(インストールorアップデートしたいパッケージ)

COMPOSER_MEMORY_LIMIT=-1は一時的にメモリを使いたい分一時的に使えるようにするよ!って意味
それと一緒にインストールしたいパッケージを記述し実行

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

Laravel 8 を体系的に学べる公式チュートリアル和訳

この記事について

  • この記事は、Laravel 8 のGetting Startedを和訳したものです。

  • 公式のチュートリアルなので、安心して、かつ効率的に学習することができます。

  • Laravelのインストールとその設定、各種ツールの説明まで網羅されているので、初学者がLaravel 8 に初めて触れたり、中級者が基礎を振り返るのに最適です。

  • 読者に誤解を与えない部分は、読みやすさを重視して適宜意訳しています。

  • 英語の記事へのリンクを日本語の記事へのリンクに変更したり、新しくリンクを追加している部分があります。

  • DeepL等を使用して推敲は行っていますが、間違っているところやより良い表現があれば、どんどん編集リクエストをお願いいたします。

  • 文頭にある:mag:は、原文のリンクになっています。

翻訳元

laravel / docs : https://github.com/laravel/docs/tree/8.x

ライセンス : MIT

 

インストール

サーバに必要なもの

:mag: Laravelを使用するためには、いくつか必要なものがあります。Laravel Homesteadという仮想マシンを使用すれば必要なものは全て揃うので、Homesteadを使用してLaravelのローカル開発環境を構築することを強くおすすめします。

Homesteadを使用しない場合、サーバは以下の条件を満たす必要があります。

  • PHP >= 7.3
  • BCMath PHP拡張
  • Ctype PHP拡張
  • Fileinfo PHP拡張
  • JSON PHP拡張
  • Mbstring PHP拡張
  • OpenSSL PHP拡張
  • PDO PHP拡張
  • Tokenizer PHP拡張
  • XML PHP拡張

 

Laravelをインストールする

:mag: Laravelは、依存関係の管理にComposerを利用しています。なので、Laravelをインストールする前に、Composerがインストールされていることを確かめてください。

和訳者メモ

Macをご利用の場合は、HomeBrewでインストールできます。

brew install composer

 

Laravelインストーラを使用する方法

まず、Composerを使用して、Laravelインストーラをダウンロードします。

composer global require laravel/installer

Laravelの実行ファイルにパスを通すために、Composerのvendor binディレクトリが$PATHに含まれていることを確認してください。vendor binディレクトリのある場所は、OSによって異なりますが、多くの場合は以下の場所に配置されています。

  • macOS: $HOME/.composer/vendor/bin

  • Windows: %USERPROFILE%\AppData\Roaming\Composer\vendor\bin

  • GNU / Linuxディストリビューション: $HOME/.config/composer/vendor/binもしくは、 $HOME/.composer/vendor/bin

Composerのグローバルインストールのパスは、composer global aboutを実行して確認できます。

インストールが終わったら、laravel newコマンドを実行して、指定したディレクトリに新しいLaravelプロジェクトを作成できます。例えば、laravel new blogコマンドは、blogという名前のディレクトリを作成し、その中にLaravelの依存関係がすでにインストールされた状態のプロジェクトを配置します。

laravel new blog

ヒント

ログインや登録などの機能を備えたLaravelプロジェクトを作りたいなら、Laravel Jetstreamをチェックしてみてください。

 

Composer Create-Projectを使用する方法

Laravelインストーラを使用する代わりに、Composerのcreate-projectコマンドでも、Laravelをインストールできます。

composer create-project --prefer-dist laravel/laravel blog

 

開発用ローカルサーバ

PHPがすでにローカルにインストールされていて、PHPに組み込まれている開発用サーバでアプリケーションを公開したい場合、Artisanのserveコマンドを使用してください。このコマンドを実行すると、http://localhost:8000で開発用サーバが起動します。

php artisan serve

ローカル開発環境を強化したい場合は、HomesteadValetを利用してください。

 

設定

公開ディレクトリ

:mag: Laravelをインストールすると、WebサーバのドキュメントとWebルートがpublicディレクトリに設定されます。publicディレクトリにあるindex.phpは、アプリケーションへ入る全てのHTTPリクエストのフロントコントローラとして機能します。

 

設定ファイル

Laravelの設定ファイルは、全てconfigディレクトリに保存されています。それぞれのオプションはドキュメント化されているので、目を通しておいてください。

 

ディレクトリのパーミッション

Laravelをインストールしたら、いくつかパーミッションの設定が必要です。storage内のディレクトリとbootstrap/cacheディレクトリは、Webサーバによって書き込みができる必要があり、そうでなければLaravelは起動できません。Homesteadを使用している場合、これらのパーミッションはすでに設定されています。

 

アプリケーションキー

Laravelをインストールした後にしておかなければならないのが、アプリケーションキーにランダムな文字列を設定することです。ComposerかLaravelインストーラを使ってLaravelをインストールした場合は、このキーは既にphp artisan key:generateコマンドによって設定されています。

通常、この文字列は32文字の必要があります。また、キーは.envという環境ファイルで設定できます。.env.exampleファイルを.envという名前でコピーしていない場合は、コピーしてください。アプリケーションキーがセットされていない場合、ユーザーセッションやその他の暗号化されたデータは安全ではありません。

 

追加設定

Laravelはこれ以上設定を必要とせず、すぐに使い始められます。ただし、config/app.phpファイルとそのドキュメントには目を通しておいてください。このファイルには、timezonelocaleのような、アプリケーションに応じて変更するべきオプションがいくつか含まれています。

以下のような追加コンポーネントを構成することもできます。

 

Webサーバ設定

ディレクトリ設定

:mag: Laravelは、常にWebサーバに構成された「Webディレクトリ」のルートから配信される必要があります。Laravelアプリケーションを「Webディレクトリ」のサブディレクトリから配信しないでください。アプリケーション内の機密ファイルを公開してしまう恐れがあります。

 

URLの設定

Apache

:mag: Laravelにはpublic/.htaccessファイルが含まれており、これがあることで、パスにフロントコントローラであるindex.phpを含まないURLを提供できます。ApacheでLaravelを配信する前に、必ずmod_rewriteモジュールを有効化して、サーバが.htaccessファイルを使用するように設定してください。

Laravelに含まれる.htaccessがApache上でうまく動作しない場合は、以下の代替案を試してみてください。

Options +FollowSymLinks -Indexes
RewriteEngine On

RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]

 

Nginx

Nginxを使用している場合は、サイト設定に以下のディレクティブを記述して、全てのリクエストがフロントコントローラであるindex.phpに流れるようにしてください。

location / {
    try_files $uri $uri/ /index.php?$query_string;
}

HomesteadValetを使用している場合、URLの設定は自動で行われます。

 

設定

はじめに

:mag: Laravelの設定ファイルは、全てconfigディレクトリに保存されています。それぞれのオプションはドキュメント化されているので、目を通しておいてください。

 

環境設定

:mag: アプリケーションが実行されている環境ごとに、別々の設定値を使用すると、便利なことがよくあります。例えば、本番環境と異なるキャッシュドライバをローカルで使用する場合などです。

これを簡単にできるようにするため、Laravelでは、PHPライブラリのDotEnvを利用しています。新しく作成したLaravelプロジェクトには、アプリケーションのルートディレクトリに.env.exampleファイルがあります。ComposerでLaravelをインストールした場合、このファイルは自動的に.envとしてコピーされます。それ以外の場合では、自分でファイルをコピーする必要があります。

.envファイルをアプリケーションのソース管理リポジトリにコミットするべきではありません。なぜかというと、アプリケーションを使用する開発者やサーバによって、必要とする環境設定は異なるからです。もっというと、機密情報が公開されるので、悪意のある侵入者がソース管理リポジトリにアクセスした場合、セキュリティリスクになります。

チームで開発している場合、.env.exampleファイルはアプリケーションに残しておいたほうがいいかもしれません。サンプルの設定ファイルにプレースホルダの値を入れておくことで、チーム内の他の開発者が、どの環境変数がアプリケーションの実行に必要なのかよく分かるからです。また、.env.testingファイルを作成することもできます。このファイルは、PHPUnitのテストを実行したり、--env=testingオプションを付けてArtisanコマンドを実行した場合に、.envファイルをオーバーライドします。

.envファイル内の任意の変数は、サーバレベルやシステムレベルの外部にある環境変数でオーバーライドすることができます。

 

環境変数の種類

:mag: .envファイル内の変数は全て文字列としてパースされるので、env()関数によっていろいろな型を返せるように、いくつか予約語が用意されています。

.env の値 env() の値
true (bool) true
(true) (bool) true
false (bool) false
(false) (bool) false
empty (string) ''
(empty) (string) ''
null (null) null
(null) (null) null

スペースが含まれた値を環境変数として定義したい場合は、値をダブルクォーテーションで囲ってください。

APP_NAME="My Application"

 

環境変数の取得

このファイルに記載された全ての変数は、アプリケーションがリクエストを受け取ったときに、PHPのスーパーグローバル変数である$_ENVに読み込まれます。ただし、設定ファイル内の変数を取得するには、envというヘルパー関数を使用します。実際にLaravelの設定ファイルを見てみると、いくつかのオプションでこのヘルパー関数が使用されているのが分かります。

'debug' => env('APP_DEBUG', false),

env関数に渡されている第二引数はデフォルト値です。与えられたキーに対応する環境変数が存在しなかった場合、この値が使用されます。

 

現在の環境を把握する

:mag: アプリケーションの現在の環境は、.envファイルのAPP_ENV変数で決定されます。この値にアクセスするには、Appファサードenvironmentメソッドを使用します。

$environment = App::environment();

また、現在の環境が指定された値であるかどうかを確かめるために、environmentメソッドに引数を渡すこともできます。現在の環境が指定された値のいずれかに当てはまる場合、このメソッドはtrueを返します。

if (App::environment('local')) {
    // 環境がlocalである
}

if (App::environment(['local', 'staging'])) {
    // 環境がlocalかstagingのいずれかである
}

アプリケーションの環境は、サーバレベルの環境変数APP_ENVで上書きできます。これを応用すると、別々の環境でアプリケーションを共有できます。

 

デバッグページから環境変数を秘匿する

:mag: 例外がキャッチされず、かつ環境変数APP_DEBUGtrueの場合、デバッグページに全ての環境変数とその内容が表示されます。設定ファイルconfig/app.php内のdebug_hideオプションを使用すると、特定の変数を隠すことができます。

いくつかの変数は、環境変数とサーバ/リクエストデータの両方で使用されます。そのため、$_ENV$_SERVERの両方に指定しなければいけない場合もあります。

return [

    // ...

    'debug_hide' => [
        '_ENV' => [
            'APP_KEY',
            'DB_PASSWORD',
        ],

        '_SERVER' => [
            'APP_KEY',
            'DB_PASSWORD',
        ],

        '_POST' => [
            'password',
        ],
    ],
];

 

設定値へのアクセス

:mag: グローバルヘルパー関数のconfigを使用することで、アプリケーションのどこからでも設定値にアクセスすることができます。設定値にアクセスするには、アクセスしたいファイル名とオプション名を含んだドット記法を使用します。デフォルト値を指定することもでき、設定オプションが存在しなかった場合に返される値を指定できます。

$value = config('app.timezone');

// 設定値が存在しない場合、デフォルト値が使用される
$value = config('app.timezone', 'Asia/Seoul');

実行時に設定値をセットする場合、ヘルパー関数configに配列を渡します。

config(['app.timezone' => 'America/Chicago']);

和訳者メモ

3通りの方法で環境の値が取得できるということになります。

>>> config('app.env')
=> "local"
>>> App::environment()
=> "local"
>>> env('APP_ENV')
=> "local"

 

設定のキャッシュ

:mag: アプリケーションの速度を上げるためには、Artisanコマンドのconfig:cacheを使用して、全ての設定ファイルを一つのファイルにキャッシュする必要があります。これにより、アプリケーションの全ての設定オプションは一つのファイルにまとめられ、フレームワークが素早く読み込めるようになります。

通常、本番環境へのデプロイのルーティンとしてphp artisan config:cacheコマンドは実行するべきです。アプリケーションの開発中は、頻繁に設定オプションを変更するので、このコマンドを実行するべきではありません。

注意

デプロイ処理中にconfig:cacheコマンドを実行する場合、設定ファイル内からのみenv関数が呼び出されていることを確認してください。設定がキャッシュされると、.envファイルは読み込まれず、env関数はnullを返すようになります。

 

メンテナンスモード

:mag: アプリケーションをメンテナンスモードにすると、アプリケーションへの全てのリクエストに対して、カスタムビューが表示されます。これによって、アップデート中やメンテナンス中にアプリケーションを簡単に「無効化」させることができます。メンテナンスモードのチェックは、アプリケーションの標準ミドルウェア内で行われています。アプリケーションがメンテナンスモードになると、ステータスコード503のMaintenanceModeExceptionが投げられます。

メンテナンスモードを有効にするには、Artisanコマンドのdownを実行してください。

php artisan down

また、downコマンドにretryオプションを与えると、HTTPヘッダにRetry-Afterの値としてセットされます。

php artisan down --retry=60

 

メンテナンスモードの迂回

メンテナンスモード中でも、secretオプションを使用して、メンテナンスモードを迂回するためのトークンを指定することができます。

php artisan down --secret="1630542a-246b-4b66-afa1-dd72a4c43515"

アプリケーションをメンテナンスモードにした後、このトークンを指定したアプリケーションのURLを開くと、Laravelはブラウザにメンテナンスモードを迂回するためのCookieを発行します。

https://example.com/1630542a-246b-4b66-afa1-dd72a4c43515

この隠されたルートにアクセスすると、アプリケーションのルート/にリダイレクトされます。一度ブラウザにCookieが発行されると、メンテナンスモードが無効のときと同じように、アプリケーションをブラウズできます。

 

メンテナンス画面のプリレンダリング

デプロイ時にphp artisan downコマンドを利用した場合、Composerの依存関係やその他のインフラコンポーネントが更新されている間、ユーザがアプリケーションにアクセスするとエラーが発生する場合があります。なぜそんなことが起こるかというと、アプリケーションがメンテナンスモードであることを判定し、テンプレートエンジンを使用してメンテナンス画面を描画するためには、Laravelの大部分を起動する必要があるからです。

そのため、リクエストサイクルの最初に返されるメンテナンスモード画面を事前にレンダリングできます。この画面は、アプリケーションの依存関係が読み込まれる前にレンダリングされます。プリレンダリングには、downコマンドのrenderオプションで指定したテンプレートが使用されます。

php artisan down --render="errors::503"

 

メンテナンスモードへのリクエストをリダイレクトする

メンテナンスモードの間、ユーザがアクセスを試みた全てのアプリケーションURLにメンテナンス画面が表示されます。必要に応じて、全てのリクエストを指定したURLにリダイレクトできます。これには、redirectオプションを使用します。全てのリクエストを/というURIにリダイレクトさせる例は以下の通りです。

php artisan down --redirect=/

 

メンテナンスモードを終了する

メンテナンスモードを終了するには、upコマンドを使用します。

php artisan up

ヒント

メンテナンスモードのテンプレートは、resources/views/errors/503.blade.phpに独自のテンプレートを定義することでカスタマイズできます。

 

メンテナンスモードとキュー

アプリケーションがメンテナンスモードの間、キュージョブは処理されません。アプリケーションがメンテナンスモードから抜けると、ジョブは通常どおり処理されます。

 

メンテナンスモードの代替案

メンテナンスモードを使用すると、アプリケーションに数秒のダウンタイムが発生するので、Laravelでダウンタイムの無いデプロイを実現したい場合は、Envoyerのような代替案を検討してください。

 

ディレクトリ構造

はじめに

:mag: デフォルトのLaravelのアプリケーション構造は、大規模なアプリケーションから小規模なアプリケーションまで、優れたスタートポイントを提供することを目的としています。しかし、アプリケーションを好きなように構成することもできます。Laravelは、Composerがクラスをオートロードできる限り、クラスの配置にほとんど制限を設けていません。

 

ルートディレクトリ

appディレクトリ

:mag: appディレクトリには、アプリケーションのコアとなるコードが含まれています。このディレクトリに関しては後でもう少し掘り下げて説明しますが、アプリケーションのクラスのほとんどは、このディレクトリの中にあります。

 

bootstrapディレクトリ

:mag: bootstrapディレクトリには、フレームワークを起動するapp.phpファイルが含まれています。また、cacheディレクトリも含まれており、パフォーマンスの最適化のためにフレームワークが生成したrouteやservicesのキャッシュファイルなどが含まれています。

 

configディレクトリ

:mag: configディレクトリには、アプリケーションの設定ファイルが全て含まれています。全てのファイルに目を通し、利用可能なオプションを理解することをおすすめします。

 

databaseディレクトリ

:mag: databaseディレクトリには、データベースのマイグレーション、モデルファクトリー、シードが含まれています。必要に応じて、このディレクトリにSQLiteデータベースを保持することもできます。

 

publicディレクトリ

:mag: publicディレクトリには、index.phpファイルが含まれています。このindex.phpファイルは、アプリケーションへの全てのリクエストのエントリーポイントであり、オートロードの構成も行います。また、このディレクトリには、画像、JavaScript、CSSなどのアセットも入っています。

 

resourcesディレクトリ

:mag: resourcesディレクトリには、ビューだけでなく、LESS、SASS、JavaScriptのような、コンパイル前の生のアセットが含まれます。また、このディレクトリには、全ての言語ファイルも入っています。

 

routesディレクトリ

:mag: routesディレクトリには、アプリケーションのルート定義が含まれています。デフォルトでは、web.phpapi.phpconsole.phpchannels.phpというルートファイルが入っています。

web.phpファイルには、RouteServiceProviderwebというミドルウェアのグループに配置するルートが含まれており、セッションの状態、CSRFの保護、Cookieの暗号化を提供します。アプリケーションがステートレスなRESTful APIを提供しない場合、ルートは全てweb.phpファイルで定義される可能性が高いです。

api.phpファイルには、RouteServiceProviderapiというミドルウェアのグループに配置するルートが含まれており、レートリミットを提供します。このファイル内で定義されるルートはステートレスであることを意図しているので、これらのルートを経由してアプリケーションへと入るリクエストはトークンで認証され、セッションの状態(ステート)にアクセスすることはありません。

console.phpファイルには、クロージャベースのコンソールコマンドを定義できます。各クロージャは、コマンドインスタンスにバインドされており、各コマンドのIOメソッドと相互に通信することを可能にします。このファイルには、HTTPのルートではなく、アプリケーションへのコンソールベースのエントリーポイント(ルート)が定義されています。

channels.phpファイルには、アプリケーションがサポートしている全てのイベントブロードキャストチャネルを登録できます。

和訳者メモ

console.phpinspireが定義されているので、以下のコマンドを実行すると、英語の格言が表示されます。

php artisan inspire

:hatched_chick:

 

storageディレクトリ

:mag: storageディレクトリには、コンパイルされたBladeテンプレート、ファイルベースのセッション、ファイルキャッシュなど、フレームワークによって生成されたファイルが含まれています。このディレクトリは、appframeworklogsディレクトリに分けられています。appディレクトリには、アプリケーションが生成したファイルが保存されます。frameworkディレクトリには、フレームワークが生成したファイルと、キャッシュが保存されます。最後に、logsディレクトリには、アプリケーションのログファイルが格納されます。

storage/app/publicディレクトリは、プロフィールアバターのような、一般に公開される必要がある、ユーザが生成したファイルを保存する場所です。このディレクトリを指すシンボリックリンクをpublic/storageに作成してください。このリンクは、php artisan storage:linkコマンドを使用して作成できます。

 

testsディレクトリ

:mag: testsディレクトリには、自動化されたテストが含まれています。Laravelプロジェクトを作成すると、最初からPHPUnitテストの例が用意されています。それぞれのテストクラスには、Testという接尾語が付けられている必要があります。テストを実行するには、phpunitコマンドか php vendor/bin/phpunitコマンドを使用します。

 

vendorディレクトリ

:mag: vendorディレクトリには、Composerの依存関係が含まれています。

 

Appディレクトリ

:mag: アプリケーションの大部分は、appディレクトリに格納されます。このディレクトリは、デフォルトでApp下に名前空間があり、PSR-4標準オートロードを使用してComposerにオートロードされます。

appディレクトリには、ConsoleHttpsProvidersなどの様々な追加ディレクトリが含まれています。ConsoleHttpディレクトリは、アプリケーションのコアにAPIを提供しているものと考えてください。HTTPプロトコルとCLIは、どちらもアプリケーションと通信するための仕組みですが、アプリケーションのロジックを一切含みません。言い換えると、これらはアプリケーションにコマンドを発行する2通りの方法です。Consoleディレクトリには、全てのArtisanコマンドが格納され、一方のHttpディレクトリには、コントローラ、ミドルウェア、およびリクエストが格納されます。

Artisanコマンドのmakeを使用してクラスを生成すると、appディレクトリ内に様々なディレクトリが生成されます。そのため、例えばArtisanコマンドのmake:jobを実行してjobクラスを生成するまで、app/Jobsというディレクトリは存在しません。

ヒント

appディレクトリ内のクラスの多くは、コマンドを介してArtisanによって生成することができます。利用可能なコマンドを確認するには、ターミナルでphp artisan list makeを実行してください。

 

Broadcastingディレクトリ

:mag: Broadcastingディレクトリには、アプリケーションの全てのブロードキャストチャネルクラスが含まれています。これらのクラスは、make:channelコマンドを使用して生成できます。このディレクトリはデフォルトでは存在しませんが、最初にチャネルを作成したときに作成されます。チャネルについての詳細は、ブロードキャスティングのドキュメントを参照してください。

 

Consoleディレクトリ

:mag: Consoleディレクトリには、アプリケーションの全てのカスタムArtisanコマンドが含まれています。これらのコマンドは、make:commandコマンドを使用して生成できます。また、このディレクトリには、カスタムArtisanコマンドをスケジューリングタスクに設定できるコンソールカーネルも入っています。

 

Eventsディレクトリ

:mag: このディレクトリはデフォルトでは存在しませんが、Artisanコマンドのevent:generatemake:eventによって作成されます。Eventsディレクトリには、イベントクラスが格納されます。イベントは、与えられたアクションが発生したことをアプリケーションの他の部分を通知するのに使用され、非常に大きな柔軟性と分離性を提供します。

 

Exceptionディレクトリ

:mag: Exceptionsディレクトリには、アプリケーションの例外ハンドラが含まれ、アプリケーションによって投げられた例外を配置するのに適しています。例外をログに記録したり描画する方法を変更する場合は、このディレクトリ内のHandlerクラスを編集してください。

 

Httpディレクトリ

:mag: Httpディレクトリには、コントローラ、ミドルウェア、フォームリクエストが含まれています。アプリケーションに入るリクエストを処理するほとんどのロジックは、このディレクトリ内にあります。

 

Jobsディレクトリ

:mag: このディレクトリはデフォルトでは存在しませんが、Artisanコマンドのmake:jobを実行すると作成されます。Jobsディレクトリには、アプリケーションのためのキュージョブが格納されます。ジョブは、アプリケーションによってキューに入れられるか、現在のリクエストのライフサイクルと同期して実行されます。現在のリクエストに同期して実行されるジョブについては、コマンドパターンの実装であるため、「コマンド」と呼ばれることもあります。

 

Listenersディレクトリ

:mag: このディレクトリはデフォルトでは存在しませんが、Artisanコマンドのevent:generatemake:listenerを実行すると作成されます。Listenersディレクトリには、イベントを処理するクラスが含まれています。イベントリスナはイベントのインスタンスを受け取り、発生したイベントに応じてロジックを実行します。例えば、UserRegisteredイベントは、SendWelcomeEmailリスナによって処理される、という感じです。

 

Mailディレクトリ

:mag: このディレクトリはデフォルトでは存在しませんが、Artisanコマンドのmake:mailを実行すると作成されます。Mailディレクトリには、アプリケーションから送信されるメールを表すクラスが全て含まれています。Mailオブジェクトを使用することで、メールを構築する全てのロジックを1つのシンプルなクラスでカプセル化することができ、Mail::sendメソッドを用いて送信することができます。

 

Modelsディレクトリ

:mag: Modelsディレクトリには、全てのEloquentモデルクラスが含まれています。Laravelに入っているEloquent ORMは、データベースを操作するための美しくシンプルなActiveRecord実装を提供します。各データベーステーブルは対応する「モデル」があり、そのテーブルを操作するために使用できます。モデルを使用すると、テーブルのデータに対してクエリを発行したり、テーブルに新たなレコードを挿入したりできます。

 

Notificationsディレクトリ

:mag: このディレクトリはデフォルトでは存在しませんが、Artisanコマンドのmake:notificationを実行すると作成されます。Notificationsディレクトリには、アプリケーション内で発生したイベントに関する通知など、アプリケーションから送信される「トランザクション」の通知が全て含まれています。Laravelの通知機能を使用することで、様々なドライバを介して、メールやSlack、SMSで通知を送信したり、データベースに保存したりすることを抽象化できます。

 

Policiesディレクトリ

:mag: このディレクトリはデフォルトでは存在しませんが、Artisanコマンドのmake:policyを実行すると作成されます。Policiesディレクトリには、アプリケーションの認可ポリシークラスが含まれています。ポリシーは、ユーザがリソースに対して特定のアクションを実行できるかどうかを判断するのに使用されます。詳細については、認可についてのドキュメントを参照してください。

 

Providersディレクトリ

:mag: Providersディレクトリには、アプリケーションの全てのサービスプロバイダが含まれています。サービスプロバイダは、サービスコンテナ内のサービスをバインドしたり、イベントを登録したり、リクエストに対してアプリケーションを準備するために他のタスクを実行したりすることで、アプリケーションを起動します。

新規作成したLaravelアプリケーションの場合、このディレクトリにはすでにいくつかプロバイダが入っています。必要に応じて、独自のプロバイダをこのディレクトリに追加することができます。

 

Rulesディレクトリ

:mag: このディレクトリはデフォルトでは存在しませんが、Artisanコマンドのmake:ruleを実行することで作成されます。Rulesディレクトリには、アプリケーションのカスタムバリデーションルールオブジェクトが含まれます。ルールは、複雑なバリデーションロジックをシンプルなオブジェクトへカプセル化するために使用されます。詳細については、バリデーションについてのドキュメントを参照してください。

 

Homestead

はじめに

:mag: Laravelは、ローカルでの開発を含めたPHP開発体験全体をより楽しくすることに努めてきました。Vagrantを使えば、仮想マシンの管理とプロビジョニングをシンプルかつ洗練された方法で行えます。

Laravel Homesteadは、ローカルマシンにPHPやWebサーバなどのサーバソフトウェアを必要とせず、素晴らしい開発環境を提供してくれる、パッケージがインストールされた状態の公式Vagrant Boxです。これを使えば、もうOSが散らかる心配はありません。Vagrant Boxは使い捨てです。何か問題が起きても、数分でBoxを破棄して作り直すことができます。

Homesteadは、Windows / Mac / Linux上で動作し、Nginx / PHP / MySQL / PostgresSQL / Redis / Memcached / Nodeなど、Laravelアプリケーションを開発するのに必要なものが全て含まれています。

注意

Windowsを使用している場合、ハードウェアの仮想化 (VT-x) を有効にする必要があります。これは通常、BIOSで有効化できます。
UEFIシステムでHyper-Vを使用している場合、VT-xにアクセスするためにHyper-Vを無効化する必要があります。

 

含まれているソフトウェア

  • Ubuntu 18.04
  • Git
  • PHP 7.4
  • PHP 7.3
  • PHP 7.2
  • PHP 7.1
  • PHP 7.0
  • PHP 5.6
  • Nginx
  • MySQL
  • lmm for MySQL or MariaDB database snapshots
  • Sqlite3
  • PostgreSQL (9.6, 10, 11, 12)
  • Composer
  • Node (With Yarn, Bower, Grunt, and Gulp)
  • Redis
  • Memcached
  • Beanstalkd
  • Mailhog
  • avahi
  • ngrok
  • Xdebug
  • XHProf / Tideways / XHGui
  • wp-cli

 

オプションのソフトウェア

  • Apache
  • Blackfire
  • Cassandra
  • Chronograf
  • CouchDB
  • Crystal & Lucky Framework
  • Docker
  • Elasticsearch
  • Gearman
  • Go
  • Grafana
  • InfluxDB
  • MariaDB
  • MinIO
  • MongoDB
  • MySQL 8
  • Neo4j
  • Oh My Zsh
  • Open Resty
  • PM2
  • Python
  • RabbitMQ
  • Solr
  • Webdriver & Laravel Dusk Utilities

 

インストール&セットアップ

最初にすること

:mag: Homestead環境を立ち上げる前に、Vagrantと合わせて、VirtualBox 6.xVMWareParallelsまたは、Hyper-Vをインストールする必要があります。これらのソフトウェアパッケージは、一般的なOSに対応した使いやすいビジュアルインストーラです。

VMwareプロバイダを使用する場合、VMware Fusion / WorkstationとVMware Vagrantプラグインを購入する必要があります。無料ではありませんが、VMwareを使用すると、共有フォルダのパフォーマンスを高速化することができます。

Parallelsプロバイダを使用する場合、Parallels Vagrantプラグインをインストールする必要があります。これは無料です。

Vagrantには制限があるので、Hyper-Vプロバイダは全てのネットワーク設定を無視します。

和訳者メモ

VagrantをHomebrewでインストールするには、以下のコマンドを実行します。

brew cask install vagrant

Parallels Vagrantプラグインの概要とインストール方法については以下の日本語記事を参考にしてください。

https://qiita.com/Michinosuke/items/eae539a1880f223d239e

 

Homestead Vagrant Boxのインストール

VirtualBox / VMwareとVagrantをインストールしたら、ターミナルで以下のコマンドを実行して、laravel/homestead BoxをVagrantに追加する必要があります。インターネットの通信スピードによりますが、Boxのダウンロードには数分かかります。

vagrant box add laravel/homestead

コマンドの実行に失敗した場合、Vagrantが最新であるか確認してみてください。

注意

Homesteadは、テストのために"alpha" / "beta" Boxを定期的に発行しますが、それがvagrant box addコマンドに支障をきたす場合があります。vagrant box addの実行で問題が発生した場合は、vagrant upコマンドを実行することで、Vagrantが仮想マシンの起動をしようとしたときに、正しいBoxをダウンロードすることができます。

 

Homesteadのインストール

ホストマシンにレポジトリをクローンして、Homesteadをインストールしてください。Homestead Boxは、全てのLaravelプロジェクトのホストとして機能するため、ホームディレクトリのHomesteadフォルダ内にレポジトリをクローンすることをおすすめします。

git clone https://github.com/laravel/homestead.git ~/Homestead

masterブランチがいつも安定版というわけではないので、タグ付けされたバージョンのHomesteadを確認してください。最新の安定版は、GitHubのリリースページで確認できます。

代わりに、常に最新の安定版がリリースされているreleaseブランチにチェックアウトするという方法もあります。

cd ~/Homestead

git checkout release

Homesteadリポジトリをクローンしたら、Homesteadディレクトリでbash init.shコマンドを実行し、Homestead.yamlという設定ファイルを生成してください。Homestead.yamlファイルは、Homesteadディレクトリに配置されます。

// Mac / Linuxの場合
bash init.sh

// Windowsの場合
init.bat

 

Homesteadの設定

プロバイダを起動する

:mag: Homestead.yamlファイルのproviderキーには、どのVagrantプロバイダを使用するかを指定します( virtualbox, vmware_fusion, vmware_workstation, parallels もしくはhypervのいずれか)。任意のプロバイダを設定してください。

provider: virtualbox

 

共有フォルダの設定

Homestead.yamlファイルのfoldersプロパティには、Homestead環境と共有したいフォルダを列挙します。これらのフォルダに含まれるファイルが変更されると、ローカルマシンとHomestead環境の間で同期されます。共有フォルダは、必要な数だけ設定できます。

folders:
    - map: ~/code/project1
      to: /home/vagrant/project1

Windowsをご利用の方は、~/のようなパスの書き方はせず、代わりにC:\Users\user\Code\project1のようなプロジェクトへのフルパスを使用してください。

全てを~/codeフォルダにマッピングするのではなく、個々のプロジェクトは独自のフォルダにマッピングするようにしてください。フォルダをマッピングしたとき、仮想マシンはフォルダ内の全てのファイルの全てのディスクIOを追跡します。すると、フォルダ内に多数のファイルがあるとき、パフォーマンスに影響を与えます。

folders:
    - map: ~/code/project1
      to: /home/vagrant/project1

    - map: ~/code/project2
      to: /home/vagrant/project2

注意

Homesteadを使用して.(カレントディレクトリ)をマウントするのは絶対にやめてください。Vagrantがカレントディレクトリを/vagrantにマッピングせず、オプションの機能が壊れたり、プロビジョニング中に予期せぬ事態が起きることがあります。

NFSを有効化するには、同期フォルダの設定にフラグを追加してください。

folders:
    - map: ~/code/project1
      to: /home/vagrant/project1
      type: "nfs"

WindowsでNFSを使用する場合は、vagrant-winnfsdプラグインのインストールを検討してください。このプラグインを使用すると、Homestead Box内のファイルとディレクトリに適切なユーザ/グループ権限を与えることができます。

また、optionsキーに列挙することで、VagrantのSynced Foldersがサポートするオプションを渡すこともできます。

folders:
    - map: ~/code/project1
      to: /home/vagrant/project1
      type: "rsync"
      options:
          rsync__args: ["--verbose", "--archive", "--delete", "-zz"]
          rsync__exclude: ["node_modules"]

 

Nginxサイトの設定

Nginxについて詳しく知らなくても問題ありません。sitesプロパティを使えば、簡単に「ドメイン」とHomestead環境のフォルダをマッピングできます。サイト設定の例は、Homestead.yamlファイルに含まれています。これにおいても、必要なだけサイトをHomesteadに追加することができます。Homesteadは、作業を行う全てのLaravelプロジェクトに、便利で視認性の高い環境を提供します。

sites:
    - map: homestead.test
      to: /home/vagrant/project1/public

Homestead Boxをプロビジョニングした後にsitesプロパティを変更した場合、仮想マシン上のNginx設定を更新するために、もう一度vagrant reload --provisionコマンドを実行する必要があります。

Homesteadのスクリプトは、可能な限り問題が発生しないように設計されています。それでもプロビジョニング中に問題が発生した場合は、vagrant destroy && vagrant upコマンドを使用して、マシンの破棄と再構築を行ってください。

 

サービスの有効化 / 無効化

Homesteadはデフォルトでいくつかサービスを起動します。しかし、プロビジョニングの間、どのサービスを有効化し、どのサービスを無効化するのかをカスタマイズすることができます。以下の例では、PostgresSQLを有効化し、MySQLを無効化しています。

services:
    - enabled:
        - "postgresql@12-main"
    - disabled:
        - "mysql"

指定したサービスは、enableddisabledディレクティブに基づいて、起動または停止が行われます。

 

ホスト名の解決

Homesteadは、自動的にホスト名を解決できるように、mDNSを使用してホスト名を公開します。Homestead.yamlhostname: homesteadをセットすると、homestead.localでホストを利用できるようになります。macOS、iOS、Linuxデスクトップディストリビューションは、mDNSをデフォルトでサポートしていますが、Windowsの場合は、Bonjour Print Services for Windowsのインストールが必要になります。

自動で解決されるホスト名が便利なのは、Homesteadをプロジェクトごとにインストールした場合です。一つのHomesteadインスタンス上で複数のサイトをホスティングした場合、Webサイトの「ドメイン」をマシンのhostsファイルに追加する必要があります。hostsファイルは、HomesteadサイトへのリクエストをHomesteadマシンへリダイレクトします。MacとLinuxでは、このファイルは/etc/hostsに配置され、Windowsでは、C:\Windows\System32\drivers\etc\hostsに配置されます。このファイルには、以下のような行を追加します。

192.168.10.10  homestead.test

Homestead.yamlファイルで設定されているものと同じIPアドレスを書き込む必要があります。hostsファイルにドメインを追加して、Vagrant Boxを起動したら、ウェブブラウザを介してサイトにアクセスできるようになります。

http://homestead.test

 

Vagrant Boxの起動

:mag: Homestead.yamlを好きなように編集したら、Homesteadディレクトリでvagrant upコマンドを実行します。すると、Vagrantは仮想マシンを起動し、共有フォルダとNginxサイトを自動的に構成します。

仮想マシンを破棄するには、vagrant destroy --forceコマンドを使用します。

 

プロジェクト単位のインストール

:mag: Homesteadをグローバルにインストールし、同じHomestead Boxを全てのプロジェクトで共有するのではなく、管理しているプロジェクトごとにHomesteadインスタンスを構成できます。プロジェクト単位でHomesteadをインストールすると、Vagrantfileをプロジェクトに同梱して、別の人がそのプロジェクト上でvagrant upできるようになります。

プロジェクトに直接Homesteadをインストールするには、Composerを使用する必要があります。

composer require laravel/homestead --dev

Homesteadをインストールしたら、makeコマンドでVagrantfileHomestead.yamlファイルをプロジェクトルートに作成してください。makeコマンドは、Homestead.yamlファイル内のsitesfoldersディレクティブを自動で設定します。

Mac / Linux :

php vendor/bin/homestead make

Windows :

vendor\\bin\\homestead make

次に、ターミナルでvagrant upコマンドを実行してから、ブラウザでhttp://homestead.testを開いてプロジェクトにアクセスしてください。覚えておいていただきたいのは、自動的なホスト名の解決を使用していない場合、homestead.testまたは任意のドメインを/etc/hostsファイルに追加する必要があります。

 

オプション機能のインストール

:mag: オプションのソフトウェアは、Homesteadの設定ファイルの「feature」設定を用いてインストールされます。ほとんどの機能は、論理値で有効か無効かを設定しますが、一部の機能では、複数の設定オプションが利用できます。

features:
    - blackfire:
        server_id: "server_id"
        server_token: "server_value"
        client_id: "client_id"
        client_token: "client_value"
    - cassandra: true
    - chronograf: true
    - couchdb: true
    - crystal: true
    - docker: true
    - elasticsearch:
        version: 7.9.0
    - gearman: true
    - golang: true
    - grafana: true
    - influxdb: true
    - mariadb: true
    - minio: true
    - mongodb: true
    - mysql8: true
    - neo4j: true
    - ohmyzsh: true
    - openresty: true
    - pm2: true
    - python: true
    - rabbitmq: true
    - solr: true
    - webdriver: true

 

MariaDB

MariaDBを有効化すると、MySQLは削除され、MariaDBがインストールされます。MariaDBはMySQLの完全な互換なので、アプリケーションデータベースの設定では、mysqlというデータベースドライバを引き続き使用できます。

 

MongoDB

デフォルトのMongoDBでは、データベースのユーザ名はhomestead、対応するパスワードはsecretに設定されています。

 

Elasticsearch

Elasticsearchのバージョンは、メジャーバージョンを指定するか、正確なバージョン番号(メジャー.マイナー.パッチ の形式)で指定できます。デフォルトのインストールでは、「homestead」という名前のクラスタを作成します。ElasticsearchにOSのメモリの半分以上を使わせるべきではないので、Homesteadマシンのメモリの過半数をElasticsearchアプリケーションに割り当てないでください。

設定をカスタマイズする方法については、Elasticsearchドキュメントを参照してください。

 

Neo4j

デフォルトでインストールしたNeo4jは、データベースのユーザ名にhomesteadが設定され、対応するパスワードはsecretになっています。Neo4jブラウザにアクセスするには、Webブラウザでhttp://homestead.test:7474を開いてください。Neo4jクライアントのために、7687 (Bolt)、7474 (HTTP)、7473 (HTTPS)のポートが用意されています。

 

エイリアス

:mag: Homesteadディレクトリのaliasesファイルを編集して、HomesteadマシンへのBashエイリアスを追加しましょう。

alias c='clear'
alias ..='cd ..'

aliasesファイルをアップデートしたら、vagrant reload --provisionコマンドでHomesteadマシンを再度プロビジョニングする必要があります。これによって、新しいエイリアスがマシン上で利用できるようになります。

 

よくある使い方

Homesteadへのグローバルアクセス

:mag: ファイルシステムのどこからでも vagrant upコマンドでHomesteadマシンを起動したいと思うかもしれません。Mac / Linuxをご利用の場合は、Bash関数をBash profileに追加することで実現できます。Windowsをご利用の場合は、PATHにバッチファイルを追加することで同様に実現可能です。これらのスクリプトは、システムのどこからでもVagrantコマンドを実行できるようにし、そのコマンドを自動でHomesteadのインストール先に渡してくれます。

 

Mac / Linux
function homestead() {
    ( cd ~/Homestead && vagrant $* )
}

関数内の~/Homesteadパスは、実際にHomesteadがインストールされている場所に合わせて書き換えてください。関数をインストールしたら、システムのどこからでもhomestead uphomestead sshのようにコマンドを実行できます。

和訳者メモ

macOS「Catalina」では、デフォルトシェルがbashからzshに変更されているのでご注意ください。特にこだわりがなければ、bashをご利用の場合は~/.bash_profileに、zshをご利用の場合は~/.zprofileに上述のスクリプトを書き込んでください。

 

Windows

どこにでもいいのでhomestead.batというバッチファイルを作成し、以下の内容を書き込んでください。

@echo off

set cwd=%cd%
set homesteadVagrant=C:\Homestead

cd /d %homesteadVagrant% && vagrant %*
cd /d %cwd%

set cwd=
set homesteadVagrant=

スクリプト内で例としてあげたC:\Homesteadパスは、実際にHomesteadがインストールされている場所に合わせて書き換えてください。ファイルを作成した後、ファイルがある場所をPATHに追加してください。そうすれば、システムのどこからでもhomestead uphomestead sshのようなコマンドが実行できるようになります。

 

SSHを用いた接続

:mag: Homesteadディレクトリでvagrant sshコマンドを実行すると、SSHで仮想マシンにアクセスできます。

ただし、HomesteadマシンへのSSHアクセスは頻繁に利用するので、前の項でご紹介した関数を追加した方が、Homestead Boxに素早くSSHでアクセスできておすすめです。

 

データベースへの接続

:mag: homesteadのデータベースでは、MySQLとPostgreSQLが最初から使えるようになっています。ホストマシンのデータベースクライアントからMySQLかPostgreSQLデータベースにアクセスするには、127.0.0.133060番ポート(MySQL)または54320番ポート(PostgreSQL)に接続してください。どちらのデータベースでも、ユーザ名とパスワードは、homestead / secretです。

ホストマシンからデータベースに接続するときには、このように一般的ではないポートのみを使用してください。Laravelは仮想マシン内で動いているので、標準的な3306と5432ポートをLaravelのデータベース設定に使用します。

和訳者メモ

私の環境では、ホストマシンからHomesteadのMySQLに接続しようとすると、以下のようなエラーが発生しました。

$ mysql -h 127.0.0.1 -P 33060 -u homestead -psecret
ERROR 2007 (HY000): Protocol mismatch; server version = 11, client version = 10

ホストマシンのMySQLデーモンが33060番ポートをバインドしていることが原因のようだったので、ホストマシン上のMySQLデーモンを停止させた状態でHomesteadを起動し、解決しました。

$ brew services stop mysql
$ homestead reload --provision
$ mysql -h 127.0.0.1 -P 33060 -u homestead -psecret
mysql>

 

データベースのバックアップ

:mag: Homesteadには、Vagrant Boxが破棄されたときに、自動的にデータベースのバックアップを作成する機能があります。この機能を利用するには、Vagrantのバージョン2.1.0以上を使用している必要があります。古いバージョンのVagrantを使用している場合には、vagrant-triggersというプラグインをインストールしてください。Homestead.yamlファイルに以下の行を追加することで、データベースの自動バックアップを有効化できます。

backup: true

設定した後、vagrant destroyコマンドを実行すると、Homesteadは、データベースをmysql_backuppostgres_backupディレクトリに出力します。これらのディレクトリは、クローンしたHomesteadディレクトリにありますが、プロジェクト単位のインストールを使用した場合は、プロジェクトのルートディレクトリにあります。

 

データベースのスナップショット

:mag: Homesteadでは、MySQLロジカルマネージャを利用することで、MySQLとMariaDBの状態の凍結とブランチが可能です。例えば、数ギガバイトのデータベースを持つサイトで作業していても、データベースをインポートして、スナップショットをとることができます。それから必要な作業をして、ローカルにテストコンテンツを作成した後、すぐに元の状態に戻せます。

内部では、コピーオンライトをサポートしたLVMの薄いスナップショット機能をLMMが利用しています。つまり、テーブルの一つの行を書き換えるということは、書き込んだ変更がただディスクに移されるというだけなので、大幅に時間を短縮し、リストア中のディスク容量を節約できます。

lmmコマンドはLVMの操作に使用するので、rootで実行する必要があります。実行可能な全てのコマンドを確認するには、Vagrant Box内でsudo lmmコマンドを実行してください。一般的な流れは、以下のようになります。

  1. デフォルトのlmmのmasterブランチにデータベースをインポートする。
  2. sudo lmm branch prod-YYYY-MM-DDコマンドを使用して、変更前のデータベースのスナップショットを保存する。
  3. データベースを編集する。
  4. sudo lmm merge prod-YYYY-MM-DDコマンドを実行して、全ての変更をなかったことにする。
  5. sudo lmm delete <branch>コマンドを実行して、必要なくなったブランチを削除する。

 

サイトの追加

Homestead環境をプロビジョニングして実行したあとに、Laravelアプリケーションに新しいNginxサイトを追加したいことがあります。一つのHomestead環境で、何個でもLaravelは実行できます。サイトを追加するには、Homestead.yamlファイルにサイトを追加してください。

sites:
    - map: homestead.test
      to: /home/vagrant/project1/public
    - map: another.test
      to: /home/vagrant/project2/public

Vagrantがhostsファイルを自動管理していない場合は、hostsファイルにも新しいサイトを追加する必要があります。

192.168.10.10  homestead.test
192.168.10.10  another.test

サイトを追加できたら、Homesteadディレクトリでvagrant reload --provisionコマンドを実行してください。

 

サイトの種類

Homesteadでは、Laravelベースではないプロジェクトを簡単に実行できるようにするため、数種類のサイトがサポートされています。例えば、symfony2というサイトタイプを使用すると、SymfonyアプリケーションをHomesteadに簡単に追加できます。

sites:
    - map: symfony2.test
      to: /home/vagrant/my-symfony-project/web
      type: "symfony2"

利用可能なサイトのタイプは次の通りです:apache, apigility, expressive, laravel (デフォルト), proxy, silverstripe, statamic, symfony2, symfony4, zf

 

サイトパラメータ

paramsというサイトディレクティブを使用して、Nginxのfastcgi_param値をサイトに追加できます。例えば、以下ではBARという値を持ったFOOパラメータを追加しています。

sites:
    - map: homestead.test
      to: /home/vagrant/project1/public
      params:
          - key: FOO
            value: BAR

 

環境変数

:mag: Homestead.yamlに書き加えることで、グローバル環境変数を設定できます。

variables:
    - key: APP_ENV
      value: local
    - key: FOO
      value: bar

Homestead.yamlを編集したら、必ずvagrant reload --provisionコマンドを実行して、再度マシンをプロビジョニングしてください。インストールしている全PHPバージョンのPHP-FPMの設定がアップデートされ、vagrantユーザの環境もアップデートされます。

 

ワイルドカードSSL

Homesteadでは、Homestead.yamlファイルのsites:セクションに定義したサイトそれぞれに、自己署名付きのSSL証明書が設定されます。サイトのワイルドカードSSL証明書を生成したい場合は、サイト設定にwildcardオプションを追加してください。サイトは、特定ドメインの証明書ではなく、ワイルドカード証明書を使用するようになります。

- map: foo.domain.test
  to: /home/vagrant/domain
  wildcard: "yes"

use_wildcardオプションがnoになっている場合、ワイルドカード証明書は生成されますが、使用されません。

- map: foo.domain.test
  to: /home/vagrant/domain
  wildcard: "yes"
  use_wildcard: "no"

 

Cronスケジュールの設定

:mag: Laravelでは、Cronジョブのスケジュールを簡単に使えるようにするため、Artisanコマンドのschedule:runを1分ごとに実行するようスケジューリングされています。schedule:runコマンドは、App\Console\Kernelにジョブスケジュールが設定されているかどうかによって、ジョブを実行するか判断します。

サイトに対してschedule:runコマンドを実行したい場合は、サイト設定のscheduleオプションにtrueを設定してください。

sites:
    - map: homestead.test
      to: /home/vagrant/project1/public
      schedule: true

サイトのCronジョブは、仮想マシンの/etc/cron.dフォルダ内に定義されます。

 

Mailhogの設定

:mag: Mailhogを使用すると、実際にメールを受信者に送信しなくても、メールを取得できるようになります。使用するにあたって、.envファイルのメール設定を以下のように書き換えてください。

MAIL_MAILER=smtp
MAIL_HOST=localhost
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null

Mailhogの設定が終わったら、http://localhost:8025を開いて、Mailhogダッシュボードにアクセスできます。

 

Minioの設定

:mag: Minioは、Amazon S3と互換性のあるAPIを備えた、オープンソースのオブジェクトストレージサーバです。Minioをインストールするには、Homestead.yamlfeaturesセクションに以下の設定オプションを書き加えてください。

minio: true

デフォルトでは、Minioは9600番ポートで利用できます。Minioのコントロールパネルにアクセスするには、http://localhost:9600/を開いてください。デフォルトのアクセスキーはhomesteadで、シークレットキーはsecretkeyです。Minioにアクセスする際には、常にus-east-1リージョンを使用してください。

Minioを使用するために、config/filesystems.phpという設定ファイルで、S3のディスク設定を調整する必要があります。ディスク設定にuse_path_style_endpointオプションを追加し、urlキーをendpontに変更してください。

's3' => [
    'driver' => 's3',
    'key' => env('AWS_ACCESS_KEY_ID'),
    'secret' => env('AWS_SECRET_ACCESS_KEY'),
    'region' => env('AWS_DEFAULT_REGION'),
    'bucket' => env('AWS_BUCKET'),
    'endpoint' => env('AWS_URL'),
    'use_path_style_endpoint' => true,
]

最後に、.envに以下のオプションが含まれていることを確認してください。

AWS_ACCESS_KEY_ID=homestead
AWS_SECRET_ACCESS_KEY=secretkey
AWS_DEFAULT_REGION=us-east-1
AWS_URL=http://localhost:9600

バケットをプロビジョニングするには、Homesteadの設定ファイルにbucketsディレクティブを追加してください。

buckets:
    - name: your-bucket
      policy: public
    - name: your-private-bucket
      policy: none

policyの値には、none, download, upload, publicが使用できます。

 

ポート

:mag: デフォルトでは、以下のポートがHomestead環境に転送(ポートフォワーディング)されます。

  • SSH: 2222 → 22 に転送
  • ngrok UI: 4040 → 4040 に転送
  • HTTP: 8000 → 80 に転送
  • HTTPS: 44300 → 443 に転送
  • MySQL: 33060 → 3306 に転送
  • PostgreSQL: 54320 → 5432 に転送
  • MongoDB: 27017 → 27017 に転送
  • Mailhog: 8025 → 8025 に転送
  • Minio: 9600 → 9600 に転送

 

ポートフォワーディングの追加

必要なら、特定のプロトコル以外にも、追加のポートフォワーディングをVagrant Boxに設定できます。

ports:
    - send: 50000
      to: 5000
    - send: 7777
      to: 777
      protocol: udp

 

環境の共有

:mag: 今やっていることを同僚やクライアントと共有したい場合があると思います。Vagrantのvagrant shareコマンドを使用すれば、これが可能になります。ただし、Homestead.yamlファイルで複数のサイトを構成している場合には、使用できません。

この問題を解決するために、Homestead自体にもshareコマンドが搭載されています。これを使用するには、vagrant sshコマンドでHomesteadマシンにSSH接続したあと、share homestead.testコマンドを実行します。すると、設定ファイルのHomestead.yamlからhomestead.testというサイトが共有されます。他に構築しているサイトがあれば、homestead.testの代わりに使用できます。

share homestead.test

コマンドを実行すると、Ngrokの画面が表示され、そこにはアクティビティログと、共有したサイトの公開URLが含まれています。任意のリージョンやサブドメインなど、Ngrokのランタイムオプションを指定したい場合は、shareコマンドにそれらを付け加えることで実現可能です。

share homestead.test -region=eu -subdomain=laravel

注意

忘れないで欲しいのは、Vagrantは本質的に安全ではなく、shareコマンドを実行すれば、仮想マシンがインターネット上に晒されてしまうということです。

 

複数のPHPバージョン

:mag: Homestead 6から、同じ仮想マシン上で複数のバージョンのPHPがサポートされるようになりました。Homestead.yamlファイルで、サイトに使用するPHPバージョンを指定できます。利用可能なPHPバージョンは、"5.6", "7.0", "7.1", "7.2", "7.3", "7.4" (デフォルト)です。

sites:
    - map: homestead.test
      to: /home/vagrant/project1/public
      php: "7.1"

さらに、コマンドライン上では、サポートされているPHPバージョンを全て利用できます。

php5.6 artisan list
php7.0 artisan list
php7.1 artisan list
php7.2 artisan list
php7.3 artisan list
php7.4 artisan list

また、Homesteadの仮想マシン内で以下のコマンドを実行すると、デフォルトのCLIバージョンを変更できます。

php56
php70
php71
php72
php73
php74

 

Webサーバ

:mag: Homesteadでは、デフォルトでWebサーバにNginxを使用します。ただし、サイトタイプにapacheを指定すれば、Apacheをインストールすることもできます。両方のWebサーバを同時にインストールすることはできますが、同時に動かすことはできません。flipというシェルコマンドを使用すれば、Webサーバを簡単に切り替えられます。flipコマンドは、起動しているWebサーバがどちらであるかを自動的に判別して停止し、もう片方のサーバを起動します。このコマンドを使用するには、HomesteadマシンにSSHで接続し、ターミナルで以下のコマンドを実行してください。

flip

 

メール

:mag: Homesteadには、Postfixというメール転送エージェントが含まれており、デフォルトで1025番ポートを使用しています。なので、localhost1025番ポートでsmtpのメールドライバを使用するように設定してください。そして、送信されたメールは全て、Postfixによって処理され、Mailhogによって取得されます。送信したメールを確認するには、ブラウザでhttp://localhost:8025にアクセスしてください。

 

デバッグ&分析

Xdebugを用いたWebリクエストのデバッグ

:mag: Homesteadでは、Xdebugを使用したステップ実行がサポートされています。例えば、ブラウザでWebページを読み込むと、PHPはIDEに接続して、動いているコードの検査や修正を可能にします。

Xdebugはデフォルトで既に起動していて、いつでも接続できます。コマンドラインでXdebugを有効化する必要がある場合は、Vagrant Box内でsudo phpenmod xdebugコマンドを実行してください。次は、IDEの指示に従って、デバッグを有効化してください。最後に、ブックマークレットや拡張を使用して、Xdebugを起動するようにブラウザを設定してください。

注意

Xdebugを使用すると、PHPの動作は著しく遅くなります。Xdebugを無効にするには、Vagrant Box内でsudo phpdismod xdebugコマンドを実行し、FPMサービスを再起動してください。

 

CLIアプリケーションのデバッグ

:mag: PHPのCLIアプリケーションをデバッグするには、Vagrant Box内でxphpというシェルエイリアスを使用します。

xphp path/to/script

 

Xdegugの自動起動

Webサーバのリクエストを作成する機能テストをデバッグする場合、デバッグするためにカスタムヘッダやCookieを使用するように変更するより、自動起動のデバッグを使用した方が簡単です。Xdebugを自動起動にする方法は、Vagrant Box内の/etc/php/7.x/fpm/conf.d/20-xdebug.iniを編集し、以下の設定を追記してください。

; ここに記述すべきIPアドレスは、Homestead.yamlに記載されているIPアドレスです。
xdebug.remote_host = 192.168.10.1
xdebug.remote_autostart = 1

 

Blackfireを用いたアプリケーションの分析

:mag: Blackfireは、WebリクエストとCLIアプリケーションを分析し、パフォーマンスアサーションの記述ができるSaaSサービスです。分析データをコールグラフとタイムラインで表示する、インタラクティブなユーザーインターフェースを提供します。開発環境でも、ステージングでも、本番環境でも、エンドユーザに影響を与えずに使用できます。コードと設定ファイルphp.iniに対して、パフォーマンス、クオリティ、セキュリティのチェックができます。

Blackfire Playerは、分析方法を記述するためにBlackfireと共に使用できる、オープンソースのWebクローラ / Webテスト / Webスクレイピングアプリケーションです。

Blackfireを有効化するには、Homesteadの設定ファイル内の「features」設定を使用します。

features:
    - blackfire:
        server_id: "server_id"
        server_token: "server_value"
        client_id: "client_id"
        client_token: "client_value"

Blackfireサーバの資格情報とクライアントの資格情報には、ユーザアカウントが必要です。Blackfireには、アプリケーションを分析するために、コマンドラインツールとブラウザ拡張を含めた様々なオプションがあります。詳細は、Blackfireのドキュメントをご覧ください。

 

XHGuiを用いたPHPパフォーマンスの分析

XHGuiは、PHPアプリケーションのパフォーマンスを調査するためのユーザインターフェースです。XHGuiを有効化するには、サイト設定にxhgui: 'true'を加えてください。

sites:
    -
        map: your-site.test
        to: /home/vagrant/your-site/public
        type: "apache"
        xhgui: 'true'

サイトが既に存在している場合、設定を更新した後にvagrant provisionコマンドを実行してください。

Webリクエストを分析するには、リクエストのクエリパラメータにxhgui=onを追加してください。XHGuiは、レスポンスに自動でCookieを付与するので、次回のリクエストにクエリパラメータは必要ありません。また、アプリケーションの分析結果を閲覧するには、ブラウザでhttp://your-site.test/xhguiにアクセスしてください。

XHGuiを使用してCLIリクエストを分析するには、コマンドの前にXHGUI=onを付与してください。

XHGUI=on path/to/script

CLIの分析結果は、Webの分析結果と同じように閲覧できます。

分析を行うと、スクリプトの実行速度が遅くなり、実時間が実際のリクエストの約2倍になることに注意してください。したがって、実際の数字ではなく、常に改善率を比較するようにしてください。また、実行時間には、デバッガ内で一時停止される時間も含まれています。

分析を行うと、ディスクスペースの大部分を消費してしまうので、数日経つと自動的に消去されます。

 

ネットワークインターフェース

:mag: Homestead.yamlnetworksプロパティは、Homestead環境のネットワークインターフェースを構成します。インターフェースは、必要な数だけ構成できます。

networks:
    - type: "private_network"
      ip: "192.168.10.20"

ブリッジインターフェースを有効化するには、bridge設定を追加し、ネットワークタイプをpublic_networkに変更してください。

networks:
    - type: "public_network"
      ip: "192.168.10.20"
      bridge: "en1: Wi-Fi (AirPort)"

DHCPを有効化するには、設定からipオプションを削除してください。

networks:
    - type: "public_network"
      bridge: "en1: Wi-Fi (AirPort)"

 

Homesteadの拡張

:mag: Homesteadディレクトリのルートにあるafter.shを使用すると、Homesteadを拡張できます。このファイルには、仮想マシンの設定やカスタマイズのためのシェルコマンドを記述できます。

Homesteadをカスタマイズするとき、Ubuntuは、パッケージの元の設定を維持するか、新しい設定ファイルで上書きするかを確認する場合があります。これを回避するには、パッケージをインストールする際に以下のコマンドを使用して、Homesteadで以前に書かれた設定を上書きしないようにします。

sudo apt-get -y \
    -o Dpkg::Options::="--force-confdef" \
    -o Dpkg::Options::="--force-confold" \
    install your-package

 

ユーザカスタマイズ

チーム設定でHomesteadを使用する場合、個人の開発スタイルに合わせるために、Homesteadを微調整できます。Homesteadディレクトリ(Homestead.yamlがあるのと同じディレクトリ)のルートに、user-customizations.shというファイルを作成してください。このファイル内には、独自のカスタマイズを作成できます。ただし、user-customizations.shはバージョン管理しないでください。

 

Homesteadのアップデート

:mag: Homesteadをアップデートする前に、Homesteadディレクトリで以下のコマンドを実行し、現在の仮想マシンを削除する必要があります。

vagrant destroy

次に、Homesteadのソースコードをアップデートする必要があります。レポジトリをクローンしている場合、レポジトリをクローンした場所で以下のコマンドを実行してください。

git fetch

git pull origin release

これらのコマンドは、GitHubレポジトリからHomesteadの最新のコードを取得し、latestタグをフェッチしてから、latestタグのついたリリースにチェックアウトしています。最新の安定版のリリースバージョンは、GitHubリリースページで確認できます。

プロジェクトのcomposer.jsonファイルを介してHomesteadをインストールした場合、composer.jsonファイルに"laravel/homestead": "^11"が含まれていることを確認した上で、依存関係をアップデートしてください。

composer update

それから、vagrant box updateコマンドを使用して、Vagrant Boxをアップデートします。

vagrant box update

次に、追加の設定ファイルをアップデートするために、Homesteadディレクトリでbash init.shコマンドを実行します。すると、既に存在するHomestead.yamlafter.shaliasesファイルを上書きするか尋ねられます。

// Mac / Linux...
bash init.sh

// Windows...
init.bat

最後に、Homestead Boxを再構築して、最新のVagrantをインストールしてください。

vagrant up

 

プロバイダ固有の設定

VirtualBox

:mag: デフォルトで、Homesteadはnatdnshostresolveronに設定しています。これは、ホストOSのDNS設定をHomesteadが使用できるようにするものです。この設定を上書きしたい場合は、Homestead.yamlファイルに以下の行を追加してください。

provider: virtualbox
natdnshostresolver: 'off'

 

Windowsでのシンボリックリンク

Windowsマシンでシンボリックリンクがうまく動作しない場合は、以下のブロックをVagrantfileファイルに書き加える必要があります。

config.vm.provider "virtualbox" do |v|
    v.customize ["setextradata", :id, "VBoxInternal2/SharedFoldersEnableSymlinksCreate/v-root", "1"]
end

 

Valet

はじめに

:mag: Valetは、Macを使っているミニマリストのためのLaravel開発環境です。Vagrantも/etc/hostsファイルも使いません。公開しているサイトの共有も、ローカルトンネルを使用します。

Valetは、マシンを起動すると、常にNginxをバックグラウンドで起動するように設定します。そして、DnsMasqを使用すれば、Valetは*.testドメインへの全てのリクエストを、ローカルマシンにインストールしているサイトへプロキシします。

言い換えると、RAM(メモリ)を7MB程度しか使用しない爆速Laravel開発環境です。ValetはVagrantやHomesteadに完全に取って代わる存在にはなりませんが、柔軟性のある基本的な機能が欲しかったり、極端なスピードを求めていたり、RAMが限られているマシンで作業する場合には、素晴らしい代替手段になります。

Valetは最初から以下をサポートしていますが、これ以外が使用できないということではありません。

いずれにしろ、カスタムドライバを使用すればValetを拡張できます。

 

ValetかHomesteadか

:mag: ご存知の通り、Laravelはローカルの開発環境としてHomesteadも提供しています。HomesteadとValetは、対象としているユーザと、ローカル開発へのアプローチという点において異なっています。Homesteadは、自動化されたNginx設定が入ったUbuntuの仮想マシン全体を提供します。仮想化されたLinuxの開発環境が欲しい場合や、Windows / Linuxを使用している場合には、Homesteadを使うのは素晴らしい選択肢となります。

ValetはMacしかサポートしておらず、PHPとデータベースサーバをローカルマシン上に直接インストールする必要があります。PHPとデータベースサーバは、Homebrewbrew install phpbrew install mysqlというコマンドを使用すれば、簡単に入手できます。Valetは、最小限のリソース消費で爆速のローカル開発環境を構築できるので、必要なものはPHP / MySQLだけであり、完全に仮想化された開発環境が必要でない人には最適です。

ValetもHomesteadも、Laravelの開発環境を構築するとても便利なものです。どちらを使うかは、個人的な好みと、チームが必要としているものによるでしょう。

 

インストール

:mag: Valetは、macOSとHomebrewを必要とします。Valetをインストールする前に、ApacheやNginxなどの他のプログラムが、ローカルマシンの80番ポートにバインドされていないことを確認してください。

  • Homebrewをインストールするか、brew updateコマンドを使用して最新バージョンにアップデートしてください。

  • Homebrewのbrew install phpコマンドでPHP 7.4をインストールしてください。

  • Composerをインストールしてください。

  • Composerのcomposer global require laravel/valetコマンドでValetをインストールしてください。~/.composer/vendor/binディレクトリがシステムの「PATH」に含まれている必要があります。

  • valet installコマンドを実行してください。ValetとDnsMasqの構築とインストールが行われ、システム起動時に実行されるValetデーモンが登録されます。

Valetのインストールが終わったら、ping foobar.testのようなコマンドをターミナルで実行して、*.testドメインにpingを試してみてください。Valetが正常にインストールされている場合、このドメインは127.0.0.1で応答するはずです。

Valetは、マシンが起動するたびに自動でデーモンを始動させます。一度Valetをインストールしてしまえば、valet startvalet installのようなコマンドを実行する必要はありません。

 

データベース

データベースが必要な場合、コマンドラインでbrew install mysql@5.7を実行し、MySQLを試してみてください。MySQLをインストールしたら、brew services start mysql@5.7コマンドで起動できます。データベースには127.0.0.1で接続でき、ユーザ名はroot、パスワードは空文字を使用してください。

 

PHPのバージョン

Valetでは、valet use php@versionコマンドでPHPバージョンの変更が可能です。指定されたバージョンのPHPがインストールされていない場合、ValetはBrewを使用してインストールを行います。

valet use php@7.2

valet use php

注意

複数のバージョンのPHPがインストールされている場合でも、Valetでは一度に一つのバージョンしか使用できません。

 

リセット

Valetのインストールで問題が発生して正しく実行できない場合は、composer global updateコマンドの後でvalet installを実行すると、インストールしたものをリセットして、問題を解決できます。まれにValetの「ハードリセット」が必要な場合がありますが、その場合は、valet uninstall --forceコマンドの後でvalet installを実行してください。

 

アップデート

:mag: Valetをアップデートするには、ターミナルでcomposer global updateコマンドを実行します。アップデートしたあと、valet installコマンドを実行すると、設定ファイルが更新されます。

 

サイトの配信

:mag: Valetのインストールができたら、サイトを配信する準備は整っています。Valetには、parklinkというLaravelのサイトを配信するのに便利な二つのコマンドがあります。

 

Parkコマンド

  • mkdir ~/Sitesのようなコマンドを実行して、新しいディレクトリをMac上に作成します。次に、cd ~/Sitesvalet parkを実行します。すると、Valetがサイトを探すパスとして、カレントディレクトリが登録されます。

  • laravel new blogコマンドで、このディレクトリに新しいLaravelサイトを作成します。

  • ブラウザでhttp://blog.testを開きます。

:mag: これだけです。これだけで、「park」したディレクトリに作成したLaravelプロジェクトは、http://folder-name.testで配信されます。

 

Linkコマンド

:mag: linkもLaravelサイトを配信するのに使用します。このコマンドは、ディレクトリ全体ではなく、ディレクトリ内で一つのみサイトを配信する場合に便利です。

  • このコマンドを使用するには、プロジェクトを開き、ターミナルでvalet link app-nameを実行します。すると、カレントディレクトリを指すシンボリックリンクが~/.config/valet/Sitesに作成されます。

  • linkコマンドを実行したら、ブラウザでhttp://app-name.testを開いてサイトにアクセスできます。

リンクしたディレクトリの一覧は、valet linksコマンドで確認できます。valet unlink app-nameを使用すると、シンボリックリンクを破棄できます。

ヒント

valet linkを使用することで、一つのプロジェクトを複数の(サブ)ドメインで配信できます。プロジェクトにサブドメインや他のドメインを追加するには、プロジェクトフォルダでvalet link subdomain.app-nameを実行してください。

 

TLSを用いたサイトの暗号化

:mag: デフォルトでは、ValetはHTTPでサイトを配信します。しかし、HTTP/2を使用して暗号化されたTLSでサイトを配信したい場合は、secureコマンドを使用してください。例えば、laravel.testドメインでサイトを配信しているときには、以下のコマンドを実行して暗号化できます。

valet secure laravel

暗号化をやめて、HTTPでの配信に戻したい場合、unsecureコマンドを使用してください。secureコマンドと同じように、このコマンドにも暗号化をやめたいホスト名を指定します。

valet unsecure laravel

 

サイトの共有

:mag: Valetには、ローカルのサイトを全世界に共有するコマンドも含まれていて、モバイルデバイスでのテスト、チームやクライアントとの共有を簡単に行えます。Valetがインストールされていれば、追加のソフトウェアインストールは必要ありません。

 

Ngrokを用いたサイトの共有

サイトを共有するには、ターミナルでサイトのディレクトリまで移動し、valet shareコマンドを実行してください。公開URLがクリップボードにコピーされ、ブラウザに直接ペーストしたり、チームと共有することが可能です。

サイトの共有を停止するには、Control + Cでプロセスを中止してください。

valet share --region=euのように、shareコマンドには追加のパラメータを渡すこともできます。詳しくは、ngrokドキュメントを参照してください。

 

Exposeを用いたサイトの共有

Exposeをインストールしている場合、ターミナルでサイトのディレクトリに移動し、exposeコマンドを実行することで、サイトを共有できます。サポートされているコマンドラインのパラメータについては、Exposeのドキュメントを参照してください。サイトを共有すると、他のデバイスやチームメンバーと共有できるURLが表示されます。

サイトの共有を停止するには、Control + Cでプロセスを中止してください。

 

ローカルネットワーク上でのサイト共有

Valetは、デフォルトで、受け入れる通信を127.0.0.1の内部に限定しています。これによって、開発マシンがインターネットに晒されて、セキュリティリスクが生じることを防いでいます。

ローカルネットワーク内の他のデバイスから、マシンのIPアドレス(例:192.168.1.10/app-name.test)を使ってValetのサイトにアクセスさせたい場合は、Nginxの設定ファイルを編集し、80番と443番ポートのlistenディレクティブの先頭についている127.0.0.1:という部分を削除してください。

valet secureを実行していない場合、/usr/local/etc/nginx/valet/valet.confファイルを編集することで、全てのHTTPSではないサイトにネットワークアクセスを解放できます。ただし、HTTPSでプロジェクトのサイトを配信している場合(valet secureを実行している場合)は、~/.config/valet/Nginx/app-name.testファイルを編集してください。

Nginxの設定を更新したら、valet restartコマンドで、設定の変更を適用してください。

 

サイト固有の環境変数

:mag: 他のフレームワークを使用しているアプリケーションでは、サーバの環境変数に依存している場合がありますが、プロジェクト内で環境変数を設定する手段はありません。Valetを使えば、プロジェクトのルートに.valet-env.phpファイルを追加することで、サイト固有の環境変数を設定することが可能です。これらの変数は、$_SERVERというグローバル配列に追加されます。

<?php

// foo.test サイトの $_SERVER['key'] に "value" を設定する
return [
    'foo' => [
        'key' => 'value',
    ],
];

// 全てのサイトの $_SERVER['key'] に "value" を設定する
return [
    '*' => [
        'key' => 'value',
    ],
];

 

プロキシサービス

:mag: Valetのドメインを、ローカルマシン内の他のサービスにプロキシしたい場合があると思います。例えば、Dockerで別のサイトを起動している間に、Valetも起動する必要がある場合です。しかし、ValetとDockerが同時に80番ポートをバインドすることはできません。

これを解決するには、proxyコマンドを使用して、プロキシを生成します。以下は、http://elasticsearch.testへの全てのトラフィックをhttp://127.0.0.1:9200にプロキシする例です。

valet proxy elasticsearch http://127.0.0.1:9200

unproxyコマンドを使えば、プロキシを削除できます。

valet unproxy elasticsearch

proxiesコマンドを使えば、プロキシされている全てのサイト構成を一覧表示できます。

valet proxies

 

カスタムValetドライバ

:mag: 独自のValetドライバを書くことで、ValetがサポートしていないフレームワークやCMSで動いているPHPアプリケーションを配信できます。Valetをインストールすると、SampleValetDriver.phpファイルが入った~/.config/valet/Driversディレクトリが作成されます。このファイルには、カスタムドライバの書き方について説明するための、簡単なドライバが実装されています。ドライバを書くのに必要な実装は、servesisStaticFilefrontControllerPathという3つのメソッドだけです。

これら3つのメソッドは全て、引数として$sitePath$siteName$uriという値をとります。$sitePathは、/Users/Lisa/Sites/my-projectのような、現在配信しているサイトのフルパスです。$siteNameは、ドメイン(my-project)の"ホスト" / "サイト名"の部分です。$uriは、リクエストのURI(/foo/bar)です。

カスタムのValetドライバが完成したら、~/.config/valet/DriversディレクトリにFrameworkValetDriver.php形式の名前で配置してください。例えば、WordPressのためのカスタムValetドライバを書いた場合、ファイル名はWordPressValetDriver.phpとします。

それぞれのメソッドのサンプル実装を見てみましょう。

 

servesメソッド

servesメソッドは、ドライバがリクエストを処理すべきならばtrueを返します。そうでない場合は、falseを返します。なので、このメソッドの内部では、渡された$sitePathに動作させようとしている種類のプロジェクトが含まれているかを判定します。

例として、WordPressValetDriverを書いているとしましょう。servesメソッドは以下のようになります。

/**
 * ドライバをリクエストに適用するかを判定する
 *
 * @param  string  $sitePath
 * @param  string  $siteName
 * @param  string  $uri
 * @return bool
 */
public function serves($sitePath, $siteName, $uri)
{
    return is_dir($sitePath.'/wp-admin');
}

 

isStaticFileメソッド

isStaticFileは、リクエストが画像やスタイルシートのような静的なファイルに対してかを判断します。静的なファイルであった場合、静的ファイルのディスク上のフルパスを返します。静的ファイルでなかった場合、メソッドはfalseを返します。

/**
 * リクエストが静的ファイルに対してのものかを判定する
 *
 * @param  string  $sitePath
 * @param  string  $siteName
 * @param  string  $uri
 * @return string|false
 */
public function isStaticFile($sitePath, $siteName, $uri)
{
    if (file_exists($staticFilePath = $sitePath.'/public/'.$uri)) {
        return $staticFilePath;
    }

    return false;
}

注意

isStaticFileメソッドが呼び出されるのは、servesメソッドがリクエストに対してtrueを返し、かつリクエストURIが/ではなかった場合のみです。

 

frontControllerPathメソッド

frontControllerPathメソッドは、アプリケーションのフロントコントローラのフルパスを返します。多くの場合、index.phpかそれに相当するものです。

/**
 * アプリケーションのフロントコントローラのフルパスを取得する
 *
 * @param  string  $sitePath
 * @param  string  $siteName
 * @param  string  $uri
 * @return string
 */
public function frontControllerPath($sitePath, $siteName, $uri)
{
    return $sitePath.'/public/index.php';
}

 

ローカルドライバ

:mag: 単一のアプリケーションにカスタムのValetドライバを定義したい場合、アプリケーションのルートディレクトリにLocalValetDriver.phpを作成してください。カスタムドライバは、ベースとなるValetDriverクラスを継承するか、LaravelValetDriverのような既に存在するアプリケーション固有のドライバを継承します。

class LocalValetDriver extends LaravelValetDriver
{
    /**
     * ドライバをリクエストに適用するかを判定する
     *
     * @param  string  $sitePath
     * @param  string  $siteName
     * @param  string  $uri
     * @return bool
     */
    public function serves($sitePath, $siteName, $uri)
    {
        return true;
    }

    /**
     * アプリケーションのフロントコントローラのフルパスを取得する
     *
     * @param  string  $sitePath
     * @param  string  $siteName
     * @param  string  $uri
     * @return string
     */
    public function frontControllerPath($sitePath, $siteName, $uri)
    {
        return $sitePath.'/public_html/index.php';
    }
}

 

その他のValetコマンド

:mag:

コマンド 説明
valet forget parkしたディレクトリで実行することで、parkしたディレクトリのリストから削除します。
valet log Valetのサービスによって書かれたログの一覧を表示します。
valet paths 全てのparkしたパスを表示します。
valet restart Valetデーモンを再起動します。
valet start Valetデーモンを起動します。
valet stop Valetデーモンを停止します。
valet trust sudoersファイルにBrewとValetを追加して、パスワード入力なしでValetコマンドを実行できるようにします。
valet uninstall Valetをアンインストールします。手動アンインストールのための説明が表示されますが、--forceパラメータを使用することで、強制的にValetを全て削除することもできます。

 

Valetディレクトリ&ファイル

:mag: Valet環境で起きた問題をトラブルシューティングする際には、以下のディレクトリとファイルの説明が参考になります。

File / Path Description
~/.config/valet/ Valetの設定が全て入っています。このフォルダはバックアップしておくといいでしょう。
~/.config/valet/dnsmasq.d/ DNSMasqの設定が全て入っています。
~/.config/valet/Drivers/ カスタムのValetドライバが入っています。
~/.config/valet/Extensions/ カスタムのValet拡張 / コマンドが入っています。
~/.config/valet/Nginx/ Valetが生成した全てのNginxサイトの設定が入っています。installsecuretldコマンドを実行すると、これらのファイルは再生成されます。
~/.config/valet/Sites/ リンクしたプロジェクトの全てのシンボリックリンクが入っています。
~/.config/valet/config.json Valetのマスタ設定ファイルです。
~/.config/valet/valet.sock ValetのNginx設定によって使用されるPHP-FPMソケットです。PHPが正常に動作している場合のみ存在します。
~/.config/valet/Log/fpm-php.www.log PHPエラーのユーザログです。
~/.config/valet/Log/nginx-error.log Nginxエラーのユーザログです。
/usr/local/var/log/php-fpm.log PHP-FPMエラーのシステムログです。
/usr/local/var/log/nginx Nginxのアクセスログとエラーログが入っています。
/usr/local/etc/php/X.X/conf.d さまざまなPHPの構築設定のための*.iniファイルが含まれています。
/usr/local/etc/php/X.X/php-fpm.d/valet-fpm.conf PHP-FPMのプール設定ファイルです。
~/.composer/vendor/laravel/valet/cli/stubs/secure.valet.conf サイト証明書の構築に使用されるデフォルトのNginx設定ファイルです。

 

デプロイ

はじめに

:mag: Laravelアプリケーションを本番環境にデプロイする準備ができたら、アプリケーションを効率的に実行させるために、やるべきことがいくつかあります。この章では、Laravelアプリケーションが適切にデプロイするための重要なポイントを解説します。

 

サーバの設定

Nginx

:mag: Nginxが動いているサーバにアプリケーションをデプロイする場合、Webサーバの設定として、以下の設定ファイルを参考にしてください。ほとんどの場合、サーバの設定に応じてカスタマイズが必要です。サーバの管理にサポートが必要な場合は、Laravel Forgeのようなサービスの利用を検討してください。

server {
    listen 80;
    server_name example.com;
    root /srv/example.com/public;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Content-Type-Options "nosniff";

    index index.php;

    charset utf-8;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    error_page 404 /index.php;

    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }
}

 

最適化

オートローダの最適化

:mag: 本番環境へデプロイするとき、Composerのクラス・オートローダ・マップを最適化することで、Composerは指定されたクラスのファイルを素早く読み込めるようになります。

composer install --optimize-autoloader --no-dev

ヒント

オートローダの最適化に加えて、プロジェクトのソース管理リポジトリにcomposer.lockファイルを含めるようにしてください。composer.lockがある方が、プロジェクトの依存関係をより速くインストールできます。

 

設定の読み込みの最適化

:mag: アプリケーションを本番環境にデプロイするとき、デプロイの流れの中でArtisanコマンドのconfig:cacheを実行するようにしてください。

php artisan config:cache

このコマンドは、全てのLaravelの設定ファイルを一つのキャッシュファイルにまとめることで、設定値を読み込む時にフレームワークが参照しなければいけないファイル数を大幅に減らします。

注意

デプロイの流れの中でconfig:cacheコマンドを実行する場合、設定ファイル内でのみenv関数が呼び出されるようにしてください。設定がキャッシュされると、.envファイルは読み込まれなくなり、env関数は全ての呼び出しに対してnullを返します。

 

ルートの読み込みの最適化

:mag: 多くのルートを持つ大規模なアプリケーションを構築する場合、デプロイの流れの中でArtisanコマンドのroute:cacheを実行してください。

php artisan route:cache

このコマンドは、全てのルート登録をキャッシュファイル内の単一のメソッド呼び出しに集約させ、何百ものルートを登録した場合のパフォーマンスを向上させます。

 

ビューの読み込みの最適化

:mag: 本番環境にアプリをデプロイするとき、デプロイの流れの中でArtisanコマンドのview:cacheを実行する必要があります。

php artisan view:cache

このコマンドは、全てのBladeビューをプリコンパイルすることで、要求されたときにコンパイルされるのを防ぎ、ビューを返すリクエストのパフォーマンスを向上させます。

 

Forge / Vaporを使ったデプロイ

:mag: 自分でサーバの設定を管理する準備ができていなかったり、強靭なLaravelアプリケーションを実行するのに必要なさまざまなサービスを全て設定することに抵抗がある場合、Laravel Forgeは素晴らしい代替手段です。

Laravel Forgeは、DigitalOceanやLinodeやAWSなど、さまざまなインフラプロバイダ上でサーバを作成できます。加えて、Forgeは、NginxやMySQL、Redis、Memcached、Beanstalkなど、強靭なLaravelアプリケーションを構築するのに必要な全てのツールのインストールと管理を行います。

 

Laravel Vapor

完全にサーバレスで、オートスケール開発プラットフォームにチューニングされたLaravelを使用したい場合、Laravel Vaporを参照してください。Laravel Vaporは、AWSを利用した、Laravelのサーバレス開発プラットフォームです。LaravelのインフラをVaporで立ち上げ、サーバレスでシンプルにスケールできます。Laravel Vaporは、Laravelの開発者によって、フレームワークとシームレスに動作するようにチューニングされているので、今までと同じようにLaravelアプリケーションを書くことができます。

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

Carbonで何週目の何曜日の日付を取得する

日付処理を扱う上で、carbonに非常に助けられている今日この頃だが、思ったより簡単に書けない処理があり、暫定で作ったものを備忘録として残す。それもっと簡単に行けるで、という情報があれば是非教えていただければと思う。

前提

日曜始まり土曜終わりを1週として、日曜から順に0,1,2...と曜日と数字が対応している。

['sun' => 0, 'mon' => 1, 'tue' => 2, 'wed' => 3, 'thu' => 4, 'fri' => 5, 'sat' => 6,]

1週目、2週目、、、5週目とn週目とnが対応している。

['1週目' => 1, '2週目' => 2, '3週目' => 3, '4週目' => 4, '5週目' => 5, '6週目' => 6]

要件

n週目のm曜日を入力値として与えられた時に、日付を返す。

public function getDate($week_of_month, $weekday)
{
  // return '2020-10-19'
}

Carbonじゃダメなの?

Carbonにも何週目か判定するメソッドや、曜日を判定するメソッドなどなど便利なメソッドが多々あるが、何週目かの計算が、月曜始まりのものと、単純に7日づつ加算して算出するものしかなく、日曜始まりで扱いやすそうな処理が書けなかったので断念

//月曜始まりで、n週目を計算。
$carbon->weekNumberInMonth;
//7日間づつ計算
$carbon->weekOfMonth;

2020/10/12追記

@vf8974 さんより、標準関数でより簡潔にかける方法をいただいたので追記

public function getDay($params)
    {
        // DateTimeImmutableインスタンス
        $d = new \DateTimeImmutable();
        // 年(省略時は今年)
        $year = $params['year'] ?? $d->format('Y');
        // 月(省略時は今月)
        $month = $params['month'] ?? $d->format('m');
        // 対象月1日
        $firstDay = $d->setDate($year, $month, 1);
        // 対象月1日の曜日
        $firstDayOfWeek = $firstDay->format('w');
        // 対象月の最終日
        $lastDay = $firstDay->format('t');
        // 第num week曜日の日
        $day = 1 + ($params['num'] - 1) * 7 + ($params['week'] - $firstDayOfWeek) % 7;
        // $dayが当月範囲内ならYYYY-MM-DDを、範囲外ならfalseを返す
        return $day >= 1 && $day <= $lastDay ? sprintf('%04d-%02d-%02d', $year, $month, $day) : false;
    }

書いたコード

日曜始まりの簡易的なカレンダーを作成し、曜日加算するという二段構えで実装した。

     protected $month_weeks;

     public function __construct()
     {
       $this->month_weeks = $this->createWeekOfMonths($this->argument($target_month))
     }
     /**
     * @param Carbon $start_of_month
     * @return array
     */
    public function createWeekOfMonths(Carbon $start_of_month): array
    {
        //start_of_month='2020-11-01'
        $target_month_weeks = [];
        //月初の曜日取得 start_of_month_weekday=0, (ie, sunday)
        $start_of_month_weekday = $start_of_month->weekday();
        //対象月の初週の日曜日を、取得
        $target_sunday = (new Carbon())->createFromTimestamp($start_of_month->timestamp)->subDays($start_of_month_weekday);

        while ($target_sunday->lte($target_month->endOfMonth())) {
            array_push($month_weeks, (new Carbon())->createFromTimestamp($target_sunday->timestamp));
            $target_sunday->addDays(7);
        }
        return $month_weeks;
    }
//$this->createWeekOfMonths('2020-11-01');
//['2020-11-01','2020-11-08','2020-11-15','2020-11-22','2020-11-29']

こうすると配列のIndexがそのままn-1週目になっている形で取得できるので、あとはこの簡易カレンダーをもとにn週目,n曜日の条件から日付を取得する。

public function getDate($week_of_month, $weekday)
{
  $target_date = array_key_exists($week_of_month - 1, $this->month_weeks) //n週目存在チェック
                ? (new Carbon())
                    ->createFromTimestamp($this->month_weeks[$week_of_month - 1]->timestamp) //n週目の日曜日のCarbonオブジェクト取得
                    ->addDays($weekday) //m曜日のm分加算 (2020-11-01 sun(0) -> 2020-11-03 tue(2))
                : null;
  return $target_date;
}

まとめ

簡易カレンダー作成にループ使用するのが若干嫌な気がしますが、暫定版なのでひとまずこれで対応。

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

[Codewars] Duplicate Encoder

概要

Codewarsの問題 Duplicate Encoder の回答の復習とベストプラクティスをまとめる個人メモです。

問題

The goal of this exercise is to convert a string to a new string where each character in the new string is "(" if that character appears only once in the original string, or ")" if that character appears more than once in the original string. Ignore capitalization when determining if a character is a duplicate.

example

"din"      =>  "((("
"recede"   =>  "()()()"
"Success"  =>  ")())())"
"(( @"     =>  "))((" 

回答

function duplicate_encode($word){
  $count = 0;
  $result = "";
  for($i=0;$i<strlen($word);$i++){
    for($j=0;$j<strlen($word);$j++){
      if (strtolower($word[$i]) == strtolower($word[$j])){
        $count++;
      }
    }
    if($count>1){
      $result = $result . ")";
    }else{
      $result = $result . "(";
     }
    $count = 0;
  }  
  return $result;
}

$result .= ")";とまとめるべきです。

ベストプラクティス

function duplicate_encode($word){
  $word = str_split(strtolower($word));
  $str = "";
  foreach($word as $key){
    (count(array_keys($word,$key))>1) ? $str .= ")" : $str .= "(";
  } 
  return $str;      
}

反省点

毎回forでゴリ押しているので、もう少し柔軟な書き方をしていきたいです。。

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