20200909のPHPに関する記事は21件です。

Laravelで更新項目をkey-valueで取得して動的にValidationを実施して更新を実施する

TL; DR

APIの開発をしていると、通常はFormRequestで更新項目を取得し、validationを実施します。

しかし、更新する項目のみをリクエストとして送信する、かつ1項目のみとする場合は、通常の実装ではこの限りとはなりません。

そのため、少しとトリッキー冗長なやり方で実装してみます。

環境

  • PHP7.4
  • Laravel7.2

通常の更新処理の実装

通常、以下の要領で更新処理のリクエストを送信します。

{
  "name": "名前",
  "mail": "test@exmaple.com",
  "gender": 1 
}

このリクエストに対応するFormRequestは、以下のとおりです。

<?php


namespace App\Http\Request\Api;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;

class UpdateRequest extends FormRequest
{
    /**
     * @return bool
     */
    public function authorize(): bool
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules(): array
    {
        return [
            'name' => ['required', 'string'],
            'mail' => ['required', 'email'],
            'gender' => ['required', Rule::in(1,2)],
        ];
    }

    /**
     * バリデーションエラーのカスタム属性の取得
     *
     * @return array
     */
    public function attributes()
    {
        return [
            'name' => '名前',
            'mail' => 'メールアドレス',
            'gender' => '性別',
        ];
    }
}

key-value形式での実装

今回は、以下の形式で更新する項目名をkeyに、更新する値をvalueに含めたリクエストを送信します。

{
  "key": "mail",
  "value": "test@exmaple.com"
}

この場合、通常通りの実装では、Validationは十分にできません。それは、keyで渡される項目をどのルールを適用してValidationの検証をすればよいかわからないからです。

そのため、Validationをする項目を動的に設定するように対応します。

<?php


namespace App\Http\Request\Api;

use App\Enum\Gender;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;

class UpdateRequest extends FormRequest
{
    private array $keys = [
        'name', 'mail', 'gender'
    ];

    /**
     * @return bool
     */
    public function authorize(): bool
    {
        return true;
    }

    /**
     * @return array
     */
    public function rules(): array
    {
        return [
            'key' => ['required', 'string', Rule::in($this->keys)],
            'value' => ['required'],
            'name' => ['max:15'],
            'mail' => ['email'],
            'gender' => [Rule::in(Gender::validateList())],
        ];
    }

    /**
     * Get data to be validated from the request.
     *
     * @return array
     */
    public function validationData()
    {
        $data = $this->all();
        if (empty($data['key']) || empty($data['value'])) return $data;

        // keyで設定された値を連想配列のキーとして設定する
        $data[$data['key']] = $data['value'];

        return $data;
    }

    /**
     * バリデーションエラーのカスタム属性の取得
     *
     * @return array
     */
    public function attributes()
    {
        return [
            'key' => '項目名',
            'value' => '属性値',
            'name' => '名前',
            'mail' => 'メールアドレス',
            'gender' => '性別',
        ];
    }
}

先ず、ruleメソッドでは、keyvalueを必須項目に設定します。また、このとき設定可能とするkeyの値を$keysで取得し、keyのValidationルールにRule::in($thit->keys)を設定します。

しかし、そのままだとValdiationの検証をしたい項目とそのルールが紐づいていません。そのため、Validationが実施される前に呼び出さるvalidationDataメソッドにて、あたかもその項目でリクエストが来たかのようにふるまうよう、値の置き換えをします。

     public function validationData()
    {
        $data = $this->all();
        if (empty($data['key']) || empty($data['value'])) return $data;

        // keyで設定された値を連想配列のキーとして設定する
        $data[$data['key']] = $data['value']; // ここで値の置き換え

        return $data;
    }

この処理をすることで、あたかも以下の形式のリクエストが送信されたかのようにふるまうことができます。

変換前のリクエスト

{
  "key": "mail",
  "value": "test@exmaple.com"
}

変換後のリクエスト

{
  "mail": "test@exmaple.com"
}

更新処理の際には、key-valueの各値を更新値の連想配列に含めれば更新が実施されます。

    /**
     * @param UpdateRequest $request
     * @return JsonResponse
     */
    public function __invoke(int $id, UpdateRequest $request): JsonResponse
    {
        $user = User::find(id)->get();

        $user->update([
            $request->get('key') => $request->get('value')
        ]);

        return response()->json($user, 200);
    }

果たして、使いどころがあるかはわかりませんが、動的にValidationを行う一例でした。

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

【Laravel】バッチでユーザーにメール送信

継続は力なり。めげずに今日も備忘録。
バッチの理解を深める為、簡単な処理を実装してみた。

環境

PHP 7.3.8
Laravel 6.18.35

本日のお題

バッチでメールを送ってみる。
今回は実装するアプリケーションの登録ユーザーに一括送信するもの。

メールの環境設定

mailtrap.ioというSMTPのダミーサーバーを利用する。
mailtrap.ioを利用する事で送信したメールは指定したアドレス宛てには送信されずに、mailtrap.ioの画面で結果を確認する事が出来るので、非常に便利です。会員登録したら直ぐに使えます。

mailtrap.ioのInboxes からDemo inbox に遷移して、SMTP情報を確認します。
その情報を元に.envを編集します。

.env
MAIL_DRIVER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=587
MAIL_USERNAME=mailtrap.ioのSMTP情報を参照
MAIL_PASSWORD=mailtrap.ioのSMTP情報を参照
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=test@example.com
MAIL_FROM_NAME="Example"

バッチ処理を書く

バッチコマンドクラスを生成する。

$ php artisan make:command SendMailCommand
SendMailCommand.php
<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use App\User;
//メール送信用ファサード
use Illuminate\Support\Facades\Mail;


class SendMailCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    //コマンドの名前
    protected $signature = 'users:send_mail';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'バッチの説明';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        //モデルからユーザー情報を取り出して
        $users = User::all();
        //メールアドレスで繰り返し
        foreach ($users as $user) {
            echo $user['email']."\n";

            Mail::raw("これバッチでメールしているよ", function($message) use ($user)
            {
                //toで送信先、subjectで件名
                $message->to($user->email)->subject('test');
            });
        }
    }
}

これでバッチが完成

ですが〜
このままバッチコマンドを実行しても失敗する事があります。

 Swift_TransportException  : Expected response code 250 but got code "530", with message "530 5.7.1 Authentication required

これが出た時はキャッシュをクリアしてあげましょう。

$ php artisan cache:clear
$ php artisan config:cache

改めてバッチコマンドを実行

php artisan users:send_mail

mailtrap.ioで正しく受信出来ているか確認してみましょう。
スクリーンショット 2020-09-09 23.36.02.png
上手くいっていますね!

参考

Laravel5で送信メールサーバー設定

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

実務で出てきて少し混乱したPHPの文法

はじめに

2020年の8月から都内の企業でWebエンジニアとして働いています。

開発環境はいわゆるフルスクラッチPHPなのですが、
私はRubyをメインで学習するプログラミングスクール出身でしたので、入社前はほとんどPHPに触ったことがありませんでした。

入社から1ヶ月ほど経った今では基礎文法も大体理解し、新しく出会った関数などをその都度調べながら
既存システムの改修業務を行っています。

そんな業務中、特に違和感のある記述を見かけたので
すぐに忘れないよう、Qiita上に残しておこうと思います。

問題のコード

isset($_REQUEST['search']) && $var = $_REQUEST['search'];

なんの変哲もないコードですが、人目見たときに混乱しました。



今までisset()を使う際は

if(isset($_REQUEST['search'])){
  $var = $_REQUEST['search'];
}

↑のようなパターンを見慣れていたので
論理演算子 && はANDの条件として使われているイメージしか持っていませんでした。


そんな中、出会った問題のコード

isset($_REQUEST['search']) && $var = $_REQUEST['search'];

初見時ワイ「何がANDやねん」
と、心の中でツッコミまくりました。

どういう動きをするのか調べて見ましたが、if文で条件分岐の例ばかり。
結局クリティカルな回答がすぐに見つからなかったので、先輩に質問させてもらいました。

結局のところ

左辺のisset()がtrueの場合に、右辺の代入が行われると教えていただきました。
if文とやってることはほとんど変わらないような気がしますが、今回のように単純な条件下ではワンライナーで読みやすくなる書き方ですね。

試しにpaiza.ioを使用して
以下のコードを実行してみました

$str = 'Hello!';
isset($str) && $var = $str;

echo $var;



結果
Image from Gyazo
や↑ったぜ

この手の書き方はPHP以外の言語でもたまに見かけるらしいです。

まとめ

可読性が上がる場合は今回のようなワンライナーによる記述を
自分も積極的に使っていこうと思います。

まだ入社間もないですが、実務で触るコードは楽しいですね。
しばらくはPHP漬けの日々を送ろうと思います。

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

デザインパターンのお勉強

デザインパターンのお勉強をしたい

このサイトの例を参考にしてちょっとづつデザインパターンを勉強しながらオブジェクト指向の設計を覚えていきたいと思います。
https://www.techscore.com/tech/DesignPattern/index.html/

まだまだ始めたばかりなので、解釈のおかしなところあると思うのでコメントいただけますと助かります。
また普段PHPを使用しているのですが、こんなところでよく使うよというようなアドバイスありましたらいただけますと大変助かります。

コマンドパターン

下記引用

22.1 Commandパターンとは
第22章ではCommandパターンを学びます。あるオブジェクトに対して要求を送るということは、そのオブジェクトのメソッドを呼び出すことと同じです。 そして、メソッドにどのような引数を渡すか、ということによって要求の内容は表現されます。さまざまな要求を送ろうとすると、引数の数や種類を増やさなければなりませんが、 それには限界があります。そこで要求自体をオブジェクトにしてしまい、そのオブジェクトを引数に渡すようにします。それがCommandパターンです。
Commandパターンは、要求をCommandオブジェクトにして、それらを複数組み合わせて使えるようにするパターンです。

実装リポジトリ

https://github.com/TOnodera/Command
サイトの例に従って、まず機能を実装してリファクタリングしました。

感想

「なぜオブジェクト指向でつくるのか?」を読んで疎結合で作ることやメイン処理部分にif文を使わないことでコードの可読性や保守性が上がるメリットは理解した気がしていました。
ただ、デザインパターンはそれぞれその良さをもっているのはわかるものの具体的にどういう部分で適用するのがやっぱり自分は理解していないなと感じました。

このパターンについてもリファクタリングの中では確かに読みやすい&保守性もあがるのはわかるけどやっぱり実践で使わないとだめですね。

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

Laravelのバリデーションでエラー時の遷移先を制御する

問題

  • Laravelのバリデーションでエラーになった際、入力時のページに戻らない
  • Laravelのバリデーションでエラーになった際に入力時のページへ戻る際、値は保持されない

原因

Laravelでバリデーションを適用した際、エラー発生時に入寮時の画面などに戻る際、GETメソッドで遷移されるから

自分はRequestvalidateメソッドを利用し、バリデーションを適用していたため、ルールやエラーメッセージなどの設定はできても、その後の制御ができておらず、冒頭のような問題が発生していた。
バリデーション 5.5 Laravelを見ると、Request以外にもバリデーションを設定できる方法があったので、それを試してみたら問題が解決したので、その方法を記載する。

解決策

validatorを利用する

validator

validatorはコントローラに直接記入して利用する。
基本となるのはこの形。

app/Http/Controllers/SampleController.php
use Validator;

class SampleController extends Controller
{
    public function sample(Request $request)
    {
        $validator = Validator::make($request->all(), [
                //バリデーションルールの記入
            ],
            [
                //エラーメッセージの記入
            ]);

        if ($validator->fails()) {
            return redirect('home')
                        ->withErrors($validator)
                        ->withInput();
            //エラー時の処理
        }
        //バリデーションが通った時の処理
    }
}

Validator::makeRequestValidateメソッドと同じように、バリデーションルールやエラーメッセージを指定する。
Validator::makeで宣言したバリデーションルールを満たさなかった場合、$validator->fails() {}が実行される。

  • redirect: 遷移先の指定
  • withErrors($validator): 遷移先に$validatorを渡す。
  • withInput(): 遷移先にInputがあり、渡したい値があれば、ここに指定。

Validatorを使ってリダイレクト先を指定することで、遷移先ページの指定は解決しそう。
ちなみに、リダイレクト先の指定はroutes\web.phpname()で指定した値も指定できる。

routes\web.php
Route::get('/home', 'HomeController@index')->name('home');

Validatorのカスタマイズ

情報編集画面 → 情報編集確認画面編集完了画面みたいな流れでLaravelのプロジェクトを作成していたとする。
その際、先程のredirect()だと渡せる情報に限界がある場合などが考えられる。
しかし、$validator->fails() {}で指定できるのはredirect()だけではない。
その例を以下に記載する。

app/Http/Controllers/EditCheckController.php
use Validator;

class EditCheckController extends Controller
{
    public function sample(Request $request)
    {
        $validator = Validator::make($request->all(), [
                'name' => 'required|max:20',
                'email' => 'required|email',
                'body' => 'required',
                'delete_flag' => 'boolean',
                //バリデーションルールの記入
            ],
            [
                'name.required' => '名前を入力してください。',
                'name.max' => '名前は20字以内で入力してください。',
                'email.required' => 'Eメールを入力してください。',
                'email.email' => 'Eメールはメールアドレス形式で入力してください。',
                'body.required' => '本文を入力してください。',
                'delete_flag.boolean'  => '0か1を入力してください。',
                //エラーメッセージの記入
            ]);

        if ($validator->fails()) {
            $edit_id = $request -> input('edit_id');
            $name = $request -> input('edit_name');
            $email = $request -> input('edit_email');
            $body = $request -> input('edit_body');
            $delete_flag = $request -> input('edit_delete_flag');
            $edit_data = User::where('id', $edit_id) -> first();
            $edit = array(
                'id' => $edit_id,
                'name' => $name,
                'email' => $email,
                'works_id' => $body,
                'created_at' => $edit_data['created_at'],
                'updated_at' => $edit_data['updated_at'],
                'delete_flag' => $edit_delete_flag
            );
            $back_url = "location.href='/home'";
            return view('edit',['User' => $edit, 'Back' => $back_url])
                -> withErrors($validator);
            //エラー時の処理
        }
        //バリデーションが通った時の処理
    }
}

まるでひとつのコントローラーの処理のようになっているが、このような書き方もできる。
view()を指定した書き方によって、GETメソッド以外による情報を保持してのページ遷移が可能となった。

エラー時における入力値の保持

redirect()以外によるページ遷移と値の保持の仕方を紹介したが、ならredirect()の際はどうやって値を保持すれば良いのか。
withInput()を使用するのも一つの手だが、Laravelではoldヘルパというものが使用できる。
使い方は~.blade.php<Input>などのvalue{{ old('name属性') }}を記入するだけ。

また、oldヘルパでは初期値も設定できる。
データベースの値を初期値にしたい場合は第二引数にその値を設定する。

sample.blade.php
<td><input type="text" name="edit_text" value="{{ old('edit_text', $db->text) }}" ></td>

参考文献

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

[PHP]郵便番号を正規表現でチェックする

今回は下記のコードを使って見ていきます。

$zip = '123−4567';  //←全角

$zip = mb_convert_kana($zip, 'a', 'UTF-8');
if (preg_match("/\A\d{3}[-]\d{4}\z/", $zip)) {
  print('郵便番号:〒' . $zip);
} else {
  print('※郵便番号を 123-4567の形式でご記入ください');
}

↓のように表示されます。

郵便番号:〒123-4567  //←半角になっている

mb_convert_kanaについては → こちら

パラメーターで「'a'」を指定する理由

郵便番号は数字なので「'n'」では?と思うかもしれませんが、
-(ハイフン)が含まれているので英数字扱いとなります。
'a'」と指定することで、英数字を半角に直すことができます。

本題の正規表現ですが、まずpreg_matchというファンクションを使います。
続く/\A\d{3}[-]\d{4}\z/について見ていきます。


\d{3}

dというのは数字「DECIMAL(デシマル)」のこと
{3}は3つ
つまり、「数字を3つ並べること」という指定

[-]

前後を-(ハイフン)で結んでくださいという指定

\d{4}

「数字を4つ並べること」

ここまでで、\d{3}[-]\d{4}で郵便番号の書式をチェックしています。

それでは、前後の「\A」「\z」は何か?

\A

「文章の先頭であること」を指定

\z

「文章の最後であること」を指定

まとめると、/\A\d{3}[-]\d{4}\z/というのは
「数字3つ並んでいるのが先頭で、間に-(ハイフン)を挟んで、終わりは数字4つ並んでいます」
というルールの記述になります。

-(ハイフン)有無のチェックもされているので、
$zip = '1234567';だと

※郵便番号を 123-4567の形式でご記入ください

と返されます。


以上です。お疲れ様でした。

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

Phalcon Devtoolsのインストール(mac)

前回、vagrantでPhalcon開発環境を作ったが、Phalcon Devtoolsの使用も必要となり、
ドキュメントと多少違うところがあり、エラー解決の過程をメモとしておく。

composer global require phalcon/devtools

で、次にエラーが出てきた:

 Problem 1
    - phalcon/devtools v4.0.3 requires ext-phalcon ^4.0.0 -> the requested PHP extension phalcon is missing from your system.
    - phalcon/devtools v4.0.2 requires ext-phalcon ^4.0.0 -> the requested PHP extension phalcon is missing from your system.
    - phalcon/devtools v4.0.1 requires ext-phalcon ^4.0.0 -> the requested PHP extension phalcon is missing from your system.
    - phalcon/devtools v4.0.0 requires ext-phalcon ^4.0.0 -> the requested PHP extension phalcon is missing from your system.
    - Installation request for phalcon/devtools ^4.0 -> satisfiable by phalcon/devtools[v4.0.0, v4.0.1, v4.0.2, v4.0.3].

  To enable extensions, verify that they are enabled in your .ini files:
    - /usr/local/etc/php/7.3/php.ini
    - /usr/local/etc/php/7.3/conf.d/ext-opcache.ini
  You can also run `php --ini` inside terminal to see which files are used by PHP in CLI mode.

「the requested PHP extension phalcon is missing 」に注意。phalcon自体をmacに入れておく。

brew install phalcon/extension/phalcon@4.0.0

composerを今度実行したら、また次にエラーが出た:

  Problem 1
    - laravel/installer v3.0.1 requires ext-zip * -> the requested PHP extension zip is missing from your system.
    - laravel/installer v3.0.1 requires ext-zip * -> the requested PHP extension zip is missing from your system.
    - laravel/installer v3.0.1 requires ext-zip * -> the requested PHP extension zip is missing from your system.
    - Installation request for laravel/installer (locked at v3.0.1, required as ^3.0) -> satisfiable by laravel/installer[v3.0.1].

解決:

$ brew install php@7.4

次にエラーが出てきたら、/usr/local/sbinを作り、権限を与える。

Warning: php 7.4.10 is already installed, it's just not linked
You can use `brew link php` to link this version.
(base) baobaochudeiMac:~ baobaochu$ brew link php
Linking /usr/local/Cellar/php/7.4.10...
Error: Could not symlink sbin/php-fpm
/usr/local/sbin is not writable.
$ sudo mkdir /usr/local/sbin
$ sudo chmod -R 777 /usr/local/sbin
$ brew link php@7.4

最後にもう一回インストールし、問題なさそうだ。

$ composer global require phalcon/devtools

インストールしたが、また使えないようだ。

$ phalcon
-bash: phalcon: command not found

ドキュメントに注意:https://github.com/phalcon/phalcon-devtools
If you get a "phalcon: command not found" message while creating the symlink, make an alias.

$ alias phalcon=/home/[USERNAME]/phalcon-devtools/phalcon

composer経由でインストールした場合、同じく/phalcon-devtools/phalconの場所を探せ。

筆者の場合は下記のパースを入れ替えて、symlinkを作る:

$ cd $HOME

$ vim ~/.bashrc
#開いたファイルに次の一行を追加
alias phalcon=/Users/[USERNAME]/.composer/vendor/phalcon/devtools/phalcon

$ vim .bash_profile
#開いたファイルに次の一行を追加
source ~/.bashrc

#最後に、下記のコマンドを実行
$ source ~/.bash_profile

今度は無事に使えるようになった。

$ phalcon

Phalcon DevTools (4.0.3)

Available commands:
  info             (alias of: i)
  commands         (alias of: list, enumerate)
  controller       (alias of: create-controller)
  module           (alias of: create-module)
  model            (alias of: create-model)
  all-models       (alias of: create-all-models)
  project          (alias of: create-project)
  scaffold         (alias of: create-scaffold)
  migration        (alias of: create-migration)
  webtools         (alias of: create-webtools)
  serve            (alias of: server)
  console          (alias of: shell, psysh)

前回、仮想環境を作ったが、ツールを使用してプロジェクトを作成しテストする。
まず以前作成したindexファイルを削除して、次に

$ cd phalcon
$ phalcon create-project store
$ varant ssh
$ sudo vi /etc/nginx/nginx.conf

nginxのドキュメントルートを/var/www/store/publicに変更します。

/etc/nginx/nginx.conf
#/var/www/
root         /var/www/store/public;

サーバー再起動して、次のページは出てきたら、構築終了。

$ sudo systemctl restart nginx

スクリーンショット 2020-09-09 17.23.45.png

補足:phpstormをご使用の場合、Phalcon 4 Autocompleteをインストールすることでコードは自動補完できる。
https://plugins.jetbrains.com/plugin/12776-phalcon-4-autocomplete

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

[PHP]半角数字に直して、数字かどうかをチェックする

今回使うファンクションはmb_convert_kana

例えば、以下のように記述されていたとする

$age = 20;    //←半角数字

if (is_numeric($age)) {
  print($age . '歳');
} else {
  print('※年齢が数字ではありません');
}

表示は下記の通り

20歳

is_numericというファンクションで、
指定されたパラメータが数値かどうかをチェックすることができる。
上記の例では($age)をチェックしている。

もし、$age = 'あいうえお'とすると

※年齢が数字ではありません

と表示される事になる。

また、$age = '20'ではなく$age = '20'(全角数字)にした場合も、
同じように「※年齢が数字ではありません」と表示されてしまう。

ユーザーが上記のように、半角で入力しなければいけない場合でも、
誤って全角で入力してしまうことが多々ある。

なので、仮に全角数字を入力してしまっても、半角数字に直してくれるよう記述すれば良い。

そこで使うのが冒頭でも述べた通りmb_convert_kanaというファンクション
先にコードを書いてしまうと以下の通り。

$age = 20;    //←全角数字

$age = mb_convert_kana($age, 'n', 'UTF-8');
if (is_numeric($age)) {
  print($age . '歳');
} else {
  print('※年齢が数字ではありません');
}

20と全角数字で入力されているにも関わらず、以下のように表示されます。

20歳

mb_convert_kanaについて説明
mb → マルチバイトの略で、日本語など全角を扱う時に使われる言葉
convert_kana → 様々なカナを変換するファンクション

パラメータによって色々な変換ができるが、
ここでは'n'とすることで半角数字に直すという指定ができる。

'UTF-8'は、使っている文字コードを指定している。

上記コードでは20が全角数字だが、「'n'」のおかげで半角数字に直される。
よって、数値として認識され20歳と表示されるようになる。


以上です。お疲れ様でした。

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

Eccubeで○○円以上送料無料にする処理

app/Customize/Service/PurchaseFlow/Processor/CustomDeliveryFeePreprocessor.php というファイルを下記のように作成します。

CustomDeliveryFeePreprocessor.php
<?php

namespace Customize\Service\PurchaseFlow\Processor;

use Eccube\Service\PurchaseFlow\ItemHolderPreprocessor;
use Eccube\Entity\ItemHolderInterface;
use Eccube\Service\PurchaseFlow\PurchaseContext;
use Eccube\Repository\BaseInfoRepository;
use Eccube\Annotation\ShoppingFlow;

/**
 * Description of CustomDeliveryFeePreprocessor
 *
 * @ShoppingFlow
 */
class CustomDeliveryFeePreprocessor implements ItemHolderPreprocessor {

    /** @var BaseInfo */
    protected $BaseInfo;

    /**
     * DeliveryFeePreprocessor constructor.
     *
     * @param BaseInfoRepository $baseInfoRepository
     */
    public function __construct(
            BaseInfoRepository $baseInfoRepository,
    )
    {
        $this->BaseInfo = $baseInfoRepository->get();
    }

    public function process(ItemHolderInterface $itemHolder, PurchaseContext $context)
    {
        $this->updateDeliveryFeeItem($itemHolder);
    }

    /**
     * @param ItemHolderInterface $itemHolder
     */
    private function updateDeliveryFeeItem(ItemHolderInterface $itemHolder)
    {
        // 10,000円を超える場合は送料無料
        $totalPrice = 0.0;
        foreach ($Shipping->getOrderItems() as $item) {
            if (!$item->isDeliveryFee()) {
                $totalPrice = $totalPrice + $item->getTotalPrice();
            }
        }
        if ( $totalPrice >= 10000 ) {
            foreach ($Shipping->getOrderItems() as $item) {
                if ($item->isDeliveryFee()) {
                    $item->setPrice(0);
                }
            }
        }
    }

}

かんたんですね。

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

[PHP]連想配列とforeach構文

連想配列について

例えば以下の配列があるとする

$fruits = ['リンゴ', 'レモン', 'バナナ'];

この変数$fruitsに格納されている配列において、
リンゴを取り出したい時は以下のように記述する

print($fruits[0]);

これで取り出せたが、それぞれの値に対応する添字を覚えておかないと意味がない。
そんな時に使うのが連想配列
順番が関係ないような配列の場合によく使う。

上記の配列を連想配列のカタチにすると以下のようになる。

$fruits = [
  'apple' => 'リンゴ',
  'lemon' => 'レモン',
  'banana' => 'バナナ'
];

この時、=>の左側の部分('apple')をキー、右側('リンゴ')を値(バリュー)と呼ぶ。
※キーはなんでも良いが、見た時に誰でも理解できるようなものが良い

連想配列において、先ほどと同じようにリンゴを取り出したい時は以下のように記述する

print($fruits['apple']);

foreachについて

foreachは配列専用の構文
配列の中身を繰り返し取り出すことができる。

先ほどの$fruitsの中身(値のみ)をforeachで取り出すには以下のように記述する。

foreach ($fruits as $fruit) {
  print($fruit . "\n");
}

(見やすくするために"\n"として改行している)
このように記述すると、表示は下記の通りになる。

リンゴ
レモン
バナナ

上記例では値のみ取り出しているが、連想配列ではキーも一緒に取り出したい場合もある。
そのような場合は以下のように記述すれば良い。

foreach ($fruits as $fruit => $katakana) {
  print($fruit . ":" . $katakana . "\n");
}

表示は下記の通り

apple:リンゴ
lemon:レモン
banana:バナナ

$fruit => $katakanaの部分は
'apple' => 'リンゴ'
'lemon' => 'レモン'
'banana' => 'バナナ'
に対応しているわけですね〜


以上です。お疲れ様でした。

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

vagrant+ContOS7+php7.2+nginx+phalcon4 環境構築と問題記録

vagrant+ContOS7+php7.2+nginx+phalcon4 環境構築と問題記録

参考資料:
https://qiita.com/wjtnk/items/f2d72fb3790d008a3154

ツールのインストール:
https://www.virtualbox.org/
https://www.vagrantup.com/

1.仮想環境の立ち上げ

$ mkdir phalcon
$ cd phalcon
$ mkdir sync
$ vagrant init CentOS7

phalcon/Vagrantfileを編集する

Vagrant.configure("2") do |config|
  config.vm.box = "centos/7"
  #ローカルでアクセスするときのIPアドレス。
  config.vm.network "private_network", ip: "192.168.10.10"
  #同期先を指定。「カレントディレクトリ(.)を/vagrant以下に同期」と、「syncディレクトリを/var/www/」以下に同期する。
  config.vm.synced_folder ".", "/vagrant"
  config.vm.synced_folder "sync", "/var/www/"
  config.vm.network "forwarded_port", guest: 80, host: 8080
  #ここで、epelとremiを使えるようにします。
  config.vm.provision "shell", inline: <<-SHELL
    sudo yum update -y
    sudo yum -y install epel-release
    sudo rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
  SHELL
end

vagrantを立ち上げる

$ cd phalcon
$ vagrant up --provision

エラーが発生していると、エラーメッセージにより対処する。

https://qiita.com/chubura/items/4166585cf3f44e33271d

Vagrant was unable to mount VirtualBox shared folders. This is usually
because the filesystem "vboxsf" is not available. This filesystem is
made available via the VirtualBox Guest Additions and kernel module.
Please verify that these guest additions are properly installed in the
guest. This is not a bug in Vagrant and is usually caused by a faulty
Vagrant box. For context, the command attempted was:

下記で解消する:

$ vagrant plugin install vagrant-vbguest

2.仮想環境に必要なアプリケーションをインストール

$ vagrant ssh
$ sudo yum install --enablerepo=remi-php72 php php-mbstring php-mcrypt php-mysqlnd php-pdo php-fpm nginx -y

php-fpmの設定の編集

$ sudo vi /etc/php-fpm.d/www.conf

補足:「/」でvimに検索します

/etc/php-fpm.d/www.conf
; user = apache 
; group = apache
; listen = 127.0.0.1:9000
;listen.owner = nobody
;listen.group = nobody

user = nginx    
group = nginx    
listen = /run/php-fpm/php-fpm.sock  
listen.owner = nginx 
listen.group = nginx   

nginxの設定の編集

sudo vi /etc/nginx/nginx.conf

rootに、前述したVagrantfileに指定したrootディレクトリーに指定。
「allow all;」と設定しましたが、Nginx でIPアドレスによるアクセス制御を行う時、別途設定する。
参考:
https://dev.classmethod.jp/articles/nginx-ip-access-control/

/etc/nginx/nginx.conf
 server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name  _;
        root         /var/www;
        allow all;
        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;
        location / {
            index index.php index.html index.htm;
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }

        location ~ .php$ {
            fastcgi_pass unix:/run/php-fpm/php-fpm.sock;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
            include fastcgi_params;
        }
    }

この段階で、一旦サーバーをテストする

$ exit
$ cd sync
$ touch index.php
index.php
<?php phpinfo();

設定が完了したら、仮想環境で、file は反映されているかをチェック

[vagrant@localhost /]$ cd var/www
[vagrant@localhost www]$ ls
cgi-bin  html  index.php

サーバーを起動する。注意:phpのextensionなど新しい追加が発生する時、再起動は必要。

$ vagrant ssh
$ sudo systemctl restart php-fpm
$ sudo systemctl restart nginx

##状態確認、activeの場合は成功
$ sudo systemctl status php-fpm
$ sudo sudo systemctl status nginx

192.168.10.10 にアクセスし、phpinfoページが出てきたら成功。

たまに「Nginxで403 Forbidden」の場合、「/var/www」の配下のファイルの権限を変更するか、またSELinuxを無効にするか、どちらかの対処策あります。
参考資料:https://engineers.weddingpark.co.jp/?p=1765

3.phalcon4をインストール

$ sudo yum install --enablerepo=remi-php72 php-phalcon4 -y

インストールされたphalcon.soを探す。

$ find / -name phalcon.so

下記の箇所に見つかりました。

/usr/lib64/php/modules/phalcon.so
/usr/lib64/php-zts/modules/phalcon.so
php --info | grep phalcon

下記で出力すれば完了:

/etc/php.d/50-phalcon.ini
phalcon
phalcon => enabled

再度192.168.10.10にアクセスし、phpinfoページに「phalcon」が出てきたら成功。
スクリーンショット 2020-09-09 15.20.36.png

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

【PHP】コメントを書くとき、書かないとき

コメントはどうあるべきか?

コメントは、読んですぐに理解できるような、簡潔で、正確なものであるべき。
それはわかるのですが、すべての処理に書いていたら
ソース全体が読みにくくなってしまいます。

コメントも整理が必要だ。

いらないコメントと必要なコメント

見ればわかるようなことはコメントに書かない方がいい。

// 人間かどうかを判断
if ($object->isHuman() === true) {
    // 名前をタロウにする
    $name = 'tarou';
}

メソッド名や変数名などの助けもあって、明らかに処理の内容がわかるとき、
わざわざコメントする必要はないと思います。読めばわかるので。

コメントが必要なのは

・なぜこうなるか
・なにをしているのか(これはなにか)
・勘違いしないか

自分が初めて見るコードだと思って見たときに、
この3点で引っかかりそうならコメントを書くようにしています。

なぜこうなるか

// パスワードがない=本登録していないため対象外
if (empty($user->password)) {
    return false;
}

なぜこうなるのか。パスワードがないから対象外なのではなく、
本登録ではないから、ということが重要な事項の場合があります。
そういった場合にコメントを入れています。

これはなにか(なにをしているのか)

// すべての注文額を合計する
$total_amount = array_sum(array_column($orders->toArray(), 'amount'));

PHP関数やフレームワークの持つヘルパ関数などが組み合わさり、
一見してなにをしているのかがわかりづらい場合など、コメントを入れています。

これについては私がプログラム初心者なので、ソースに対する理解度が低く、
入れているということもあります。
ただ、保守などで、今後どういう理解度の方がこのソースを見るかわからないので、
念のためという面もあります。

勘違いしないか

// 管理者へメール(請求管理者とは別なので注意)
$this->sendMailToAdmin($from, $subject, $body);

この場合だと、請求も含んだ処理をしていて、2つの宛先がややこしいなー、
というように感じたので入れています。
間違えてしまいそうだが、決して間違えてはいけないもの
(そんなことばかりですが)、に入れるようにしています。

1年間プログラムをやってきた所感、という内容なので、
ご意見ありましたら頂戴したいです。

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

Laravel8~Newログインまたも変更あり~Memo

Laravle8のLoginがどうなってるか確認してみる

みなさんこんにちは
ジーズアカデミー 主席講師 山崎ですm(_ _)m
今回はLaravel8にアップデートされLogin画面作成のMemoをしておきます。

以下がLaravel8インストール時の画面です。

前提条件/検証環境

  • LaravelでCRUDを作成した経験がある人
  • Laravelの基本を理解している人
  • 記事内容的には、Laravel8のAuthを使う場合の自分メモです。
  • Laravel8
  • PHP 7.3.x(確認した環境)
  • EC2の場合:t2.small (メモリ2G以上必要 "laravel/jetstream"に必要なため,t2.microだとコケます)
  • Node.js インストール済みであること

【 Laravel6/7でのログイン画面作成はこちらをご参考に】

https://qiita.com/daisu_yamazaki/items/a914a16ca1640334d7a5


Laravel8 ログイン画面作成

Login

Register

1. laravel/jetstreamをインストール

幾つかの種類があるようです、時間的に今回は簡単なものを選択!!

ターミナル
composer require laravel/jetstream

php artisan jetstream:install livewire

php artisan migrate


#vue使う場合には以下も必要
npm install

npm run dev

ダッシュボード

プロフィールページ??

なんか、すごくなってる。。。

まずは Laravel8バージョンのLOGINが実装できました!

Loginのところも「幾つかの選択肢」があるようなので、これも後で調べていこうと思います。
いやー、インストールはサクサク感が出た気がします(個人の感想)。
Login後の機能が拡張されてるので、これから触って調べていこうと思います。
凄いですね~ワクワクします!!
※朝30分でメモったので、間違ってたらごめんなさいm(_ _)m

もう一つのLoginは??※現在検証中
ターミナル
composer require laravel/jetstream

php artisan jetstream:install inertia

npm install

npm run dev

Laravel8.x 公式

https://laravel.com/docs/8.x/frontend#introduction

「Laravel DB.com」も運用中

Laravelをテーブル設計するだけでMigrationも生成できるツール
https://qiita.com/daisu_yamazaki/items/4e13ac43c20bcdedeb40

以上

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

Laravel8 ~New Login まで早速試してみた~

Laravel8 ~New Login まで早速試してみた~

みなさんこんにちは
ジーズアカデミー 主席講師 山崎ですm(_ _)m
今回はLaravel8にアップデートされLogin画面作成のMyMemoをしておきます。

以下がLaravel8インストール完了時の画面です。変わってる・・・。

前提条件/検証環境

  • Laravelを基本を理解してCRUDを作成した経験がある人
  • 記事内容的には、Laravel8のLoginを使う場合の自分メモです。
  • PHP 7.3.x(確認した環境)
  • EC2の場合:t2.small (メモリ2G以上必要 "laravel/jetstream"に必要なため,t2.microだとコケます。Swapで対応できる方はそれでもOK)
  • Node.js インストール済みであること

【 Laravel6/7でのログイン画面作成はこちらをご参考に】

https://qiita.com/daisu_yamazaki/items/a914a16ca1640334d7a5


Laravel8 ログイン画面作成

Login

Register

1. laravel/jetstreamをインストール

幾つかの種類があるようです、時間的に今回は簡単なものを選択!!

ターミナル
composer require laravel/jetstream

php artisan jetstream:install livewire

php artisan migrate

npm install

npm run dev

上記コマンドの2回目は「Livewire」or「inertiajs」を選択します。
どちらも目新しい。

ターミナル
#https://laravel-livewire.com/
php artisan jetstream:install livewire

#https://inertiajs.com/
php artisan jetstream:install inertia

「Livewireは(Bladeインクルードのように)最初のコンポーネント出力をページとともにレンダリングします。...インタラクションが発生すると、Livewireは更新されたデータを使用してサーバーにAJAXリクエストを送信します。」とサイトの説明を見る感じでは、Bladeテンプレート側の記述だけでJavaScriptを生成するようなイメージでしょうか。

「Inertiaにはクライアント側ルーティングがなく、APIも必要ありません。いつものように、コントローラーとページビューを構築するだけ」と「クライアント側とサーバー側の2つを接続する接着剤と考えてください」って感じで書いてますね。フロント側をvue/React/Svelte ...構築する場合にはこちらですね。

ダッシュボード

プロフィールページ??

なんか、すごくなってる。。。

まずは Laravel8バージョンのLOGINが実装できました!

Loginのところも「幾つかの選択肢」があるようなので、これも後で調べていこうと思います。
いやー、インストールはサクサク感が出た気がします(個人の感想)。
Login後の機能が拡張されてるので、これから触って調べていこうと思います。
凄いですね~ワクワクします!!
※朝30分でメモったので、間違ってたらごめんなさいm(_ _)m
※先程、確認したら、すでに同様の記事を上げてらっしゃる人が多数いました。。速い人は本当に速い。アウトプットが重要ですからね。これでいいんです。

Laravel8.x 公式

https://laravel.com/docs/8.x/frontend#introduction

「Laravel DB.com」も運用中

Laravelをテーブル設計するだけでMigrationも生成できるツール
https://qiita.com/daisu_yamazaki/items/4e13ac43c20bcdedeb40

以上

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

Laravel8 : 新ログイン「jetstream」を早速試してみた

Laravel8 : 新ログイン「jetstream」を早速試してみた

みなさんこんにちは
ジーズアカデミー 主席講師 山崎ですm(_ _)m
今回はLaravel8にアップデートされLogin画面作成のMyMemoをしておきます。

以下がLaravel8インストール完了時の画面です。変わってる・・・。

前提条件/検証環境

  • Laravelを基本を理解してCRUDを作成した経験がある人
  • 記事内容的には、Laravel8のLoginを使う場合の自分メモです。
  • PHP 7.3.x(確認した環境)
  • EC2の場合:t2.small (メモリ2G以上必要 "laravel/jetstream"に必要なため,t2.microだとコケます。Swapで対応できる方はそれでもOK)
  • Node.js インストール済みであること

【 Laravel6/7でのログイン画面作成はこちらをご参考に】

https://qiita.com/daisu_yamazaki/items/a914a16ca1640334d7a5


Laravel8 ログイン画面作成

Login

Register

1. laravel/jetstreamをインストール

幾つかの種類があるようです、時間的に今回は簡単なものを選択!!

ターミナル
composer require laravel/jetstream

php artisan jetstream:install livewire

php artisan migrate

npm install

npm run dev

上記コマンドの2回目は「Livewire」or「inertiajs」を選択します。
どちらも目新しい。

ターミナル
#https://laravel-livewire.com/
php artisan jetstream:install livewire

#https://inertiajs.com/
php artisan jetstream:install inertia

「Livewireは(Bladeインクルードのように)最初のコンポーネント出力をページとともにレンダリングします。...インタラクションが発生すると、Livewireは更新されたデータを使用してサーバーにAJAXリクエストを送信します。」とサイトの説明を見る感じでは、Bladeテンプレート側の記述だけでJavaScriptを生成するようなイメージでしょうか。

「Inertiaにはクライアント側ルーティングがなく、APIも必要ありません。いつものように、コントローラーとページビューを構築するだけ」と「クライアント側とサーバー側の2つを接続する接着剤と考えてください」って感じで書いてますね。フロント側をvue/React/Svelte ...構築する場合にはこちらですね。

ダッシュボード

プロフィールページ??

なんか、すごくなってる。。。

まずは Laravel8バージョンのLOGINが実装できました!

Loginのところも「幾つかの選択肢」があるようなので、これも後で調べていこうと思います。
いやー、インストールはサクサク感が出た気がします(個人の感想)。
Login後の機能が拡張されてるので、これから触って調べていこうと思います。
凄いですね~ワクワクします!!
※朝30分でメモったので、間違ってたらごめんなさいm(_ _)m
※先程、確認したら、すでに同様の記事を上げてらっしゃる人が多数いました。。速い人は本当に速い。アウトプットが重要ですからね。これでいいんです。

Laravel8.x 公式

https://laravel.com/docs/8.x/frontend#introduction

「Laravel DB.com」も運用中

Laravelをテーブル設計するだけでMigrationも生成できるツール
https://qiita.com/daisu_yamazaki/items/4e13ac43c20bcdedeb40

以上

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

php 画像向き修正

image.php
$filename = "パス"

if (mime_content_type($filename) == 'image/jpeg') {
          $image = ImageCreateFromJPEG($filename);
        }else {
          $image = ImageCreateFromPNG($filename);
        }


        $exif_datas = @exif_read_data($filename);
        if (isset($exif_datas['Orientation'])) {
          $orientation = $exif_datas['Orientation'];

          //回転角度
          $degrees = 0;
          switch($orientation) {
            case 1:     //回転なし(↑)
              break;
            case 8:     //右に90度(→)
              $degrees = 90;
              break;
            case 3:     //180度回転(↓)
              $degrees = 180;
              break;
            case 6:     //右に270度回転(←)
              $degrees = 270;
              break;
            case 2:     //反転 (↑)
              $mode = IMG_FLIP_HORIZONTAL;
              break;
            case 7:     //反転して右90度(→)
              $degrees = 90;
              $mode = IMG_FLIP_HORIZONTAL;
              break;
            case 4:     //反転して180度なんだけど縦反転と同じ(↓)
              $mode = IMG_FLIP_VERTICAL;
              break;
            case 5:     //反転して270度(←)
              $degrees = 270;
              $mode = IMG_FLIP_HORIZONTAL;
              break;
          }
          //反転(2,7,4,5)
          if (isset($mode)) {
            $image = imageflip($image, $mode);
          }
          //回転(8,3,6,7,5)
          if ($degrees > 0) {
            $image = imagerotate($image, $degrees, 0);
          }

          //保存
          if (mime_content_type($filename) == 'image/jpeg') {
            ImageJPEG($image, $filename);
          }else {
            ImagePNG($image, $filename);
          }
          // //メモリ解放
          imagedestroy($image);
        }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

php

resize.php
bool imagecopyresampled ( resource $dst_image , resource $src_image , int $dst_x , int $dst_y , int $src_x , int $src_y , int $dst_w , int $dst_h , int $src_w , int $src_h )

パラメータ
dst_image
コピー先の画像リンクリソース。

src_image
コピー元の画像リンクリソース。

dst_x
コピー先の x 座標。

dst_y
コピー先の y 座標。

src_x
コピー元の x 座標。

src_y
コピー元の y 座標。

dst_w
コピー先の幅。

dst_h
コピー先の高さ。

src_w
コピー元の幅。

src_h
コピー元の高さ。

返り値
成功した場合に TRUE を、失敗した場合に FALSE を返します。

resize.php
bool imagejpeg ( resource $image [, string $filename [, int $quality ]] )

引数
image
画像リソースを指定します。

filename
画像リソースをファイルに保存する場合、ファイル名を指定します。
quality
画像のクオリティを0(低品質)から100(高品質)で指定します。デフォルトは75です。
返り値
画像の出力・作成に成功した場合は trueを、その他の場合は flaseを返します。

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

php リサイズ

画像を扱う前処理

resize.php
ImageCreateFromJPEG($filename)

これでメモリ(このプログラム内)の中で扱える

画像をリサイズ

resize.php
bool imagecopyresampled(resource $dst_image,resource $src_image,
int $dst_x,int $dst_y,int $src_x,int $src_y,int 
$dst_w,int $dst_h,int $src_w,int $src_h)

パラメータ
dst_image
コピー先の画像リンクリソース。
src_image
コピー元の画像リンクリソース。
dst_x
コピー先の x 座標。
dst_y
コピー先の y 座標。
src_x
コピー元の x 座標。
src_y
コピー元の y 座標。
dst_w
コピー先の幅。
dst_h
コピー先の高さ。
src_w
コピー元の幅。
src_h
コピー元の高さ。

返り値
成功した場合に TRUE を、失敗した場合に FALSE を返します。

画像を出力or 保存

resize.php
bool imagejpeg ( resource $image [, string $filename [, int $quality ]] )

引数
image
画像リソースを指定します。

filename
画像リソースをファイルに保存する場合、ファイル名を指定します。
quality
画像のクオリティを0(低品質)から100(高品質)で指定します。デフォルトは75です。
返り値
画像の出力・作成に成功した場合は trueを、その他の場合は flaseを返します。

実際にリサイズ

resize.php
$filename = "画像パス"
if (mime_content_type($filename) == 'image/jpeg') {
          $image = ImageCreateFromJPEG($filename);
          $size = getimagesize($filename);
        }else {
          $image = ImageCreateFromPNG($filename);
          $size = getimagesize($filename);
        }



        //白紙の画像を作成
        $image2 = ImageCreateTrueColor(640, 480);
        //リサイズ処理
        imagecopyresampled($image2, $image, 0, 0, 0, 0, 640, 480, $size[0], $size[1]);

        //保存
        if (mime_content_type($filename) == 'image/jpeg') {
          imagejpeg($image2, $filename);
        }else {
          imagepng($image2, $filename);
        }

        //メモリ解放
        imagedestroy($image);

リサイズ問題

原寸は「横400px・縦180px」だが、横幅(widthプロパティに「200px」が指定された結果、縦横比を維持して高さは「90px」になる。
どちらかを指定すれば自動で、元画像の比率を保ったまま高さor横が決められる

resize.css
width: auto;

リサイズ計算式

元の画像の横:X1、縦:Y1
リサイズ後の画像の横:X2、縦:Y2
とした時、
X2を任意の値にした時に、アスペクト比を保った状態でのY2の値は
Y2=X2/X1*Y1

実践

resize.php
        //retinadisplay対応
        $resize_width = 462 * 2; //横幅決める
        $resize_height = $resize_width / $size[0] * $size[1]; //縦を比率崩さず出す
        //白紙の画像を作成
        $image2 = ImageCreateTrueColor($resize_width, $resize_height);
        //リサイズ処理
        imagecopyresampled($image2, $image, 0, 0, 0, 0, $resize_width, $resize_height, $size[0], $size[1]);

完成

resize.php
if (mime_content_type($filename) == 'image/jpeg') {
          $image = ImageCreateFromJPEG($filename);
          $size = getimagesize($filename);
        }else {
          $image = ImageCreateFromPNG($filename);
          $size = getimagesize($filename);
        }


        //retinadisplay対応
        $resize_width = 462 * 2; //横幅決める
        $resize_height = $resize_width / $size[0] * $size[1]; //縦を比率崩さず出す
        //白紙の画像を作成
        $image2 = ImageCreateTrueColor($resize_width, $resize_height);

        $x = 0;
        $y = 0;
        $x = floor(($size[0] - $size[1]) / 2);  //切り取るx軸の中心
        $y = floor(($size[1] - $size[0]) / 2);  //切り取るx軸の中心
        //リサイズ処理
        imagecopyresampled($image2, $image, 0, 0, $x, $y, $resize_width, $resize_height, $size[0], $size[1]);

        //保存
        if (mime_content_type($filename) == 'image/jpeg') {
          imagejpeg($image2, $filename);
        }else {
          imagepng($image2, $filename);
        }

        //メモリ解放
        imagedestroy($image);

参考:https://blog.ver001.com/php_image_resize_object-fit/
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q11117777576
https://qiita.com/mikakane/items/290301a308277a384c2d
http://iekasegu.work/column.php?no=144

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

laravelのバージョンアップを経験して

laravel_varsionup.jpg

はじめに

当方、フリーでPHPエンジニアをやっています。

最近Laravelのvar5.2からvar6にバージョンアップするプロジェクトに携わる機会があり、そこで得た経験を大雑把ではありますが、まとめてみました。
これからバージョンアップを計画している方に少しでも参考になれば幸いです!

尚、テストコードの実装があまりさせていない環境でのバージョンアップでしたが、ちゃんとテストコードを書いている場合は、テスト回して確認する事をおすすめします!

基本的には公開されているアップデートガイドを見て進めるのが良いです。

確認する事

  • サーバー
    • laravelのドキュメント、サーバー要件を確認
  • mysql
    • バージョン確認する
  • PHP
    • バージョン確認する
  • PHPライブラリ
    • バージョンアップ後も動くか確認。ライブラリのバージョンを上げなければいけない時、既存のシステムが正常に動くか確認
    • ライブラリによってLaravelのバージョンアップ後、サポートしてない可能性もある為、注意が必要
  • laravelのヘルパー関数
    • 飛び級のバージョンアップ時はだいぶ内容も変わっているので使っている際は注意が必要
  • collection
    • メソッドの内容の変更、廃止されたメソッドなど
  • Eloquent クエリビルダ
    • Eloquentの方が採用率は高いかもしれませんが、混合で使用していたりする場合は両方注意が必要
  • jobs failed_jobsテーブルの変更
    • 5.3からjobsとfailed_jobsのテーブル構成に変更が入っています
  • Laravel Mix
    • css、jsの圧縮をされている際はバージョン確認
  • セッション
    • 5.3からコンストラクタでセッションにアクセスできなくなってます
  • インスタンス化
    • 今はDIを使っている所も多いかと思いますが、appでインスタンス化していて変数を渡している場合、キーを指定して渡して上げないとエラーになります
  • Log
    • 飛び級のバージョンアップの場合、機能も充実して設定方法も変わっているので、注意が必要。slack等にエラーログ飛ばしている場合など。
  • vender配下をオーバーライドしている場合
    • 私が携わったプロジェクトで一番ネックだった所です。あまりしないかもしれませんが、セッションやauth 、その他vender配下のメソッドをオーバーライドして独自に処理を加えている場合、基本的に機能しないと考えておいた方が良いです。

プロジェクトによってはまだまだ確認する所もあるかと思いますが、システムを良く理解している方と相談して進めていくと良いです!

バージョンアッププロジェクトを走らせる前に

注意事項をリストアップしておくと良いです。
例えば、PHPのバージョンアップが必要でPHP関数を普段良く使っている場合、非推奨になっている関数等ありますので、そういったリストと、修正内容を統一するために、補填としてどういった対応が必要か残しておくとチームとして動きやすくなります。

また、必要作業もリストアップしておくのをおすすめします。

最後に

テストコードを普段から書いておくとバージョンアップも楽です:tada:

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

Laravel 8 リリース!

ScreenShot 2020-09-09 1.06.05.png

2020年9月8日 Laravel 8 がリリースされました?

Laravel Jetstream、モデルディレクトリ、モデルファクトリー、マイグレーションスカッシング、レート制限の改善、時間テストヘルパー、動的ブレードコンポーネント等多くの新機能が追加されています。
Laravel 8 はLTSではありません。バグ修正は2021年3月8日、セキュリティ修正は2021年7月8日までのサポートになるのでご注意ください。

Laravel 8 の新機能

https://laravel-news.com/laravel8

(ニュース記事の内容をほぼグーグル翻訳したものです。)

Laravel Jetstream

https://github.com/laravel/jetstream

[Laravel Jetstreamは、以前のバージョンにあった既存のLaravel UI足場を改善します。
ログイン、登録、メール検証、2要素認証、セッション管理、LaravelによるAPIサポート、チーム管理など、新しいプロジェクトの出発点となります。

モデルディレクトリ

Laravel 8のアプリケーションのデフォルトでは app/Models ディレクトリが含まれています。
すべてのジェネレータコマンドは、モデルが app/Models に存在することを前提としています。
ただし、app/Models ディレクトリが存在しない場合は、app ディレクトリ内にモデルを保持していると想定します。

モデルファクトリクラス

Eloquentモデルファクトリは、Laravel 8からクラスベースになり、ファクトリ間の関係のサポートが改善されました。
新しく改善されたモデルファクトリを介してレコードを生成するための新しい構文がいかに素晴らしいかについて、あなたは賛同するでしょう。

use App\Models\User;

User::factory()->count(50)->create();

// using a model state "suspended" defined within the factory class
User::factory()->count(5)->suspended()->create();

マイグレーションスカッシュ

アプリケーションに多くのマイグレーションファイルが含まれている場合は、それらを1つのSQLファイルに圧縮できます。
このファイルは、マイグレーションの実行時に最初に実行され、その後、残りのマイグレーションファイルが実行されます。
既存のマイグレーションを潰すことで、マイグレーションファイルの膨張を減らし、テスト実行中のパフォーマンスを向上させることができます。

レート制限の改善

Laravel 8は、既存のスロットルミドルウェアとの下位互換性をサポートし、はるかに高い柔軟性を提供しながら既存のレート制限機能を改善します。
Laravel 8には、ファサードを介して定義できるレートリミッターの概念があります。

use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Support\Facades\RateLimiter;

RateLimiter::for('global', function (Request $request) {
    return Limit::perMinute(1000);
});

ご覧のとおり、このfor()メソッドはHTTPリクエストインスタンスを取得するため、リクエストを動的に制限することを完全に制御できます。

時間テストヘルパー

Laravelユーザーは、優れたCarbon PHPライブラリを介して、時間の変更を完全に制御できました。Laravel 8は、テスト内の時間を操作するための便利なテストヘルパーを提供することで、この一歩をさらに前進させます。

// Travel into the future...
$this->travel(5)->milliseconds();
$this->travel(5)->seconds();
$this->travel(5)->minutes();
$this->travel(5)->hours();
$this->travel(5)->days();
$this->travel(5)->weeks();
$this->travel(5)->years();

// Travel into the past...
$this->travel(-5)->hours();

// Travel to an exact time...
$this->travelTo(now()->subHours(6));

// Return back to the present time...
$this->travelBack();

これらの方法を使用すると、各テストの間に時間がリセットされます。

動的ブレードコンポーネント

実行時にブレードコンポーネントを動的にレンダリングする必要がある場合があります。
Laravel 8には、<x-dynamic-component/>コンポーネントをレンダリングするための用意がされています。

<x-dynamic-component :component="$componentName" class="mt-4" />

Laravel 8の詳細

これらはLaravel 8の新機能のほんの一部であり、完全なリストを確認するには、Laravel 8リリースノートとアップグレードガイドを確認してください。また、簡単な更新方法が必要な場合は、Laravel Shiftを忘れないでください。

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

Laravel 8 Release !

ScreenShot 2020-09-09 1.06.05.png

2020年9月8日 Laravel 8 がリリースされました?

Laravel Jetstream、モデルディレクトリ、モデルファクトリー、マイグレーションスカッシング、レート制限の改善、時間テストヘルパー、動的ブレードコンポーネント等多くの新機能が追加されています。
Laravel 8 はLTSではありません。バグ修正は2021年3月8日、セキュリティ修正は2021年7月8日までのサポートになるのでご注意ください。

Laravel 8 の新機能

https://laravel-news.com/laravel8

(ニュース記事の内容をほぼグーグル翻訳したものです。)

Laravel Jetstream

https://github.com/laravel/jetstream

[Laravel Jetstreamは、以前のバージョンにあった既存のLaravel UI足場を改善します。
ログイン、登録、メール検証、2要素認証、セッション管理、LaravelによるAPIサポート、チーム管理など、新しいプロジェクトの出発点となります。

モデルディレクトリ

Laravel 8のアプリケーションのデフォルトでは app/Models ディレクトリが含まれています。
すべてのジェネレータコマンドは、モデルが app/Models に存在することを前提としています。
ただし、app/Models ディレクトリが存在しない場合は、app ディレクトリ内にモデルを保持していると想定します。

モデルファクトリクラス

Eloquentモデルファクトリは、Laravel 8からクラスベースになり、ファクトリ間の関係のサポートが改善されました。
新しく改善されたモデルファクトリを介してレコードを生成するための新しい構文がいかに素晴らしいかについて、あなたは賛同するでしょう。

use App\Models\User;

User::factory()->count(50)->create();

// using a model state "suspended" defined within the factory class
User::factory()->count(5)->suspended()->create();

マイグレーションスカッシュ

アプリケーションに多くのマイグレーションファイルが含まれている場合は、それらを1つのSQLファイルに圧縮できます。
このファイルは、マイグレーションの実行時に最初に実行され、その後、残りのマイグレーションファイルが実行されます。
既存のマイグレーションを潰すことで、マイグレーションファイルの膨張を減らし、テスト実行中のパフォーマンスを向上させることができます。

レート制限の改善

Laravel 8は、既存のスロットルミドルウェアとの下位互換性をサポートし、はるかに高い柔軟性を提供しながら既存のレート制限機能を改善します。
Laravel 8には、ファサードを介して定義できるレートリミッターの概念があります。

use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Support\Facades\RateLimiter;

RateLimiter::for('global', function (Request $request) {
    return Limit::perMinute(1000);
});

ご覧のとおり、このfor()メソッドはHTTPリクエストインスタンスを取得するため、リクエストを動的に制限することを完全に制御できます。

時間テストヘルパー

Laravelユーザーは、優れたCarbon PHPライブラリを介して、時間の変更を完全に制御できました。Laravel 8は、テスト内の時間を操作するための便利なテストヘルパーを提供することで、この一歩をさらに前進させます。

// Travel into the future...
$this->travel(5)->milliseconds();
$this->travel(5)->seconds();
$this->travel(5)->minutes();
$this->travel(5)->hours();
$this->travel(5)->days();
$this->travel(5)->weeks();
$this->travel(5)->years();

// Travel into the past...
$this->travel(-5)->hours();

// Travel to an exact time...
$this->travelTo(now()->subHours(6));

// Return back to the present time...
$this->travelBack();

これらの方法を使用すると、各テストの間に時間がリセットされます。

動的ブレードコンポーネント

実行時にブレードコンポーネントを動的にレンダリングする必要がある場合があります。
Laravel 8には、<x-dynamic-component/>コンポーネントをレンダリングするための用意がされています。

<x-dynamic-component :component="$componentName" class="mt-4" />

Laravel 8の詳細

これらはLaravel 8の新機能のほんの一部であり、完全なリストを確認するには、Laravel 8リリースノートとアップグレードガイドを確認してください。また、簡単な更新方法が必要な場合は、Laravel Shiftを忘れないでください。

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