20210505のPHPに関する記事は9件です。

PHP変数の埋め込みかた

PHP変数の埋め込み方 PHPの文字列に変数を埋め込みたい時はダブルクォーテーションを使います。 <?php $a = 1; echo "{$a}回目です。"; ?> 文字列をシングルクォーテーションで囲むとエラーになりますのでご注意ください。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

VS CodeのPHP Intelephense で拡張モジュールのサポートを追加する

対象 Visual Studio Code (VS Code)の extension で PHP の Language Server である PHP Intelephense を使っている人が対象です やりたいこと intelephense で補完が効く PHP extension (拡張モジュール) を増やしたい 詳細 intelephense を導入していると、PHP のよく使われる拡張モジュールのクラスについてはコード補完や定義表示のサポートをしてくれる(補完用のStubを有効にする)設定になっています しかし、デフォルトでStubが有効にされている extension は限られています(21/05/05時点で71) 実は設定を変更するだけでStubを有効にできる extension が多くあります(21/05/05時点でデフォルト71+107) 方法 今回は Redis の extension のコード補完・定義表示を設定することにします。設定前はクラス名に Hover しても定義が表示されず、 Undefined type 'Redis'. となっています。 VS Codeの設定画面を開きます (Code > Preferences > Settings または Command(Ctrl) + ,) User設定またはWorkspace設定のいずれかを選び、 Extensions > intelephense > intelephense Stubs で Add Item をクリック、 有効にしたいモジュール名を入力します 設定可能なモジュールのリスト または、たとえばWorkspace設定の場合、 .vscode/settings.json を直接編集しても設定可能です。まとめてたくさんの extension の Stub を有効にしたいときは、こちらの方法が良さそうですね。 無事、定義が表示されるようになりました 補足 技術的には、JetBrainsの phpstorm-stubsを利用しているようです
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravelで同一ページで複数のページネーション

Laravelで同一ページ内で複数のページネーションを実装するときのメモ 前提 バージョン:Laravel 6 実装方法 ①第3引数に値を渡す デフォルトでは第3引数が'page'となっているため同じページ中に複数のページネーションがあっても全て連動して動いてしまう。 これを避けるために、それぞれ別の値を渡す。 $hoge = Hoge::Paginate(5, ['*'], 'hogePage'); $funya = Funya::Paginate(5, ['*'], 'funyaPage'); ②リクエストへの処理追記 ①でページネーションを独立させることができるが、このままではページ遷移時に他のページネーションがリセットされてしまう。 appendsメソッドを使用して他のページネーションにも値を渡すことでこれを回避できる。 $hoge = Hoge::Paginate(5, ['*'], 'hogePage') ->appends(['funyaPage' => \Request::get('funyaPage')]); $funya = Funya::Paginate(5, ['*'], 'funyaPage') ->appends(['hogePage' => \Request::get('hogePage')]); 結果 以下のように独立したページネーションを同一ページ内で実装できた。 サンプルコード全文 DemoContoroller.php <?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Hoge; use App\Funya; class DemoController extends Controller { public function paginateDemo() { $hoges = Hoge::Paginate(5, ['*'], 'hogePage') ->appends(['funyaPage' => \Request::get('funyaPage')]); $funyas = Funya::Paginate(5, ['*'], 'funyaPage') ->appends(['hogePage' => \Request::get('hogePage')]); return view('paginateDemo',[ 'hoges' => $hoges, 'funyas' => $funyas, ]); } } paginateDemo.blade.php <!doctype html> <html lang="ja"> <head> <!-- Required meta tags --> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- Bootstrap CSS --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous"> <title>paginateDemo</title> </head> <body> <ul class="list-group"> @foreach($hoges as $hoge) <li class='list-group-item'>{{ $hoge->name }}</li> @endforeach </ul> {{ $hoges->links() }} <ul class="list-group"> @foreach($funyas as $funya) <li class='list-group-item'>{{ $funya->name }}</li> @endforeach </ul> {{ $funyas->links() }} </body> </html> web.php <?php Route::get('/paginateDemo', 'DemoController@paginateDemo')->name('paginateDemo');
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

初めて投稿します

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

Laravelで簡単なCMSを作成(フォームリクエストでバリデーション)

Laravelで簡単なCMSを作成してみます。記事登録までの機能は下記の記事を参考に。 今回は新規登録する記事にバリデーション機能を追加します。Laravelのバリデーション機能には「フォームリクエスト」という独自のバリデーションクラスを作成し適用できる機能が用意されています。「フォームリクエスト」の利点は、コントローラメソッドにタイプヒンティングすることで、バリデーションロジックをコントローラメソッド内に記述する必要がなくなり、メソッドがスッキリすることです。 フォームリクエストクラス作成 artisanコマンドでフォームリクエストのひな形を作成できます。 https://readouble.com/laravel/8.x/ja/validation.html#creating-form-requests php artisan make:request ArticlesRequest バリデーションルール作成 フォームリクエストクラスのrulesメソッドでバリデーションルールを定義します。 https://readouble.com/laravel/8.x/ja/validation.html#creating-form-requests ArticlesRequest.php <?php namespace App\Http\Requests; use Illuminate\Foundation\Http\FormRequest; class ArticlesRequest extends FormRequest { /** * Determine if the user is authorized to make this request. * * @return bool */ public function authorize() { return true; } /** * Get the validation rules that apply to the request. * * @return array */ public function rules() { return [ 'title' => 'required|unique|max255', 'body' => 'required', ]; } } エラーメッセーのカスタマイズ messageメソッドをオーバーライドすることでエラーメッセージをカスタマイズできます。 https://readouble.com/laravel/8.x/ja/validation.html#customizing-the-error-messages ArticlesRequest.php public function messages() { return [ 'title.required' => 'タイトルを入力してください', 'body.required' => '本文は入力必須です', ]; } バリデーションルールの実行 コントローラメソッドで作成したArticlesRequestクラスをタイプヒントで指定することで、コントローラメソッドが実行される前にバリデーションが実行されます。 https://readouble.com/laravel/8.x/ja/validation.html#creating-form-requests ArticlesController.php use App\Http\Requests\ArticlesRequest; public function create(ArticlesRequest $request) { $validated = $request->validated(); $article = Article::create([ 'title' => $request->title, 'body' => $request->body, 'user_id' => Auth::id(), 'slug' => $request->title, ]); // 中間テーブルにtagを登録 $article->tags()->attach($request->tags); return redirect('/articles'); } バリデーションエラーの表示 @errorディレクティブを使用すると、特定の属性のバリデーションエラーメッセージが存在するか確認でき、$message変数でエラーメッセージを取得できます。 https://readouble.com/laravel/8.x/ja/validation.html#the-at-error-directive add.blade.php <label class="block"> <span class="text-gray-700">Title</span> <input type="text" name="title" class="mt-1 block w-full @error('title') border-red-500 @enderror"> @error('title') <p class="text-red-500 text-xs italic mt-3">{{ $message }}</p> @enderror </label> <label class="block"> <span class="text-gray-700">Body</span> <textarea class="mt-1 block w-full @error('body') border-red-500 @enderror" rows="3" name="body"></textarea> @error('body') <p class="text-red-500 text-xs italic mt-3">{{ $message }}</p> @enderror </label> フォームの再取得 バリデーションエラーがあると直前のページにリダイレクトされます。直前のフォーム画面で入力された値は、oldメソッドまたはヘルパを使用することで取得できます。 https://readouble.com/laravel/8.x/ja/validation.html#repopulating-forms add.blade.php <label class="block"> <span class="text-gray-700">Title</span> <input type="text" name="title" class="mt-1 block w-full @error('title') border-red-500 @enderror" value="{{ old('title') }}"> @error('title') <p class="text-red-500 text-xs italic mt-3">{{ $message }}</p> @enderror </label> <label class="block"> <span class="text-gray-700">Body</span> <textarea class="mt-1 block w-full @error('body') border-red-500 @enderror" rows="3" name="body">{{ old('body') }}</textarea> @error('body') <p class="text-red-500 text-xs italic mt-3">{{ $message }}</p> @enderror </label> カスタムバリデーションルール 独自のバリデーションルールを定義できます。 https://readouble.com/laravel/8.x/ja/validation.html#custom-validation-rules ルールオブジェクトを作成 artisanコマンドでルールオブジェクトを作成します。 php artisan make:rule Uppercase カスタムルール定義 LaravelのドキュメントではUpperCaseのルールを紹介しているので、これを使ってみます。 UpperCase.php <?php namespace App\Rules; use Illuminate\Contracts\Validation\Rule; class Uppercase implements Rule { /** * Create a new rule instance. * * @return void */ public function __construct() { // } /** * Determine if the validation rule passes. * * @param string $attribute * @param mixed $value * @return bool */ public function passes($attribute, $value) { return strtoupper($value) === $value; } /** * Get the validation error message. * * @return string */ public function message() { return 'The :attribute must be uppercase.'; } } カスタムルールの適用 ルールオブジェクトをほかのバリデーションルールと同様に指定します。 ArticleRequest.php public function rules() { return [ 'title' => ['required', 'unique:users', 'max:255', new Uppercase], 'body' => 'required', ]; } 1回切りのカスタムルール作成 他のフォームでは使用しないルールは、ルールオブジェクトではなくクロージャを渡すことで実現できます。 https://readouble.com/laravel/8.x/ja/validation.html#using-closures ArticleRequest.php public function rules() { return [ // 'title' => 'required|unique:users|max:255', 'title' => [ 'required', 'unique:users', 'max:255', function ($attribute, $value, $fail) { if (! preg_match('/^【.+】/u', $value)) { $fail('【単語】見出し の形式でタイトルを書いてください'); } } ], 'body' => 'required', ]; }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Macで複数のバージョンのPHPを同時に使う

OSXで複数のバージョンのPHPを同時に使うの更新記事で、Macで複数のネイティブのPHPを切り替えなしに使う方法を説明します。 ターミナルのウインドウで切り替える 設定 ターミナル > 環境設定 > プロファイル > コマンドを実行で目的のPHPのバイナリのパスをexportします。 export PATH="/usr/local/Cellar/php@7.4/7.4.16/bin/:$PATH" テキストタブでタイトルをPHP7.4などと変えます。ウインドウで背景の色を変えるとさらに区別しやすいでしょう。 利用 ターミナル > ファイルからタイトルで決めたPHPを選びます。 composerで 例えば現在、phpmdはphp8では動作しません。CIではPHPのバージョンの指定ができますが、ローカルでも実行できれば便利です。 composer.jsonのscriptsでPHPのパスを指定します。 "phpmd": ["/usr/local/Cellar/php@7.4/7.4.16/bin/php ./vendor/bin/phpmd src text ./phpmd.xml"], 実行にはcomposerコマンドで composer phpmd 同様にビルトインサーバーも "serve": "/php -dzend_extension=xdebug.so -S 127.0.0.1:8080 -t public", "serve7": "/usr/local/Cellar/php@7.4/7.4.16/bin/php -dzend_extension=xdebug.so -S 127.0.0.1:8081 -t public", 別々のポート(8080, 8081)で別々のPHPバージョンで立ち上がります。 composer serve composer serve7 グローバルに切り替える これまで同時に使う方法を説明しましたが、同時ではなく、グローバルに切り替えて使う場合はこの記事に複数のPHPのインストールから切り替え方法まで詳しく解説されています。 この記事中で紹介されているsphpスクリプトで、Webサーバーを含めてPHPバージョンを切り替えます。 例) $ sphp 8.0 sphp 8.0 Switching to php@8.0 Switching your shell Unlinking /usr/local/Cellar/php@7.4/7.4.16... 0 symlinks removed. Unlinking /usr/local/Cellar/php/8.0.3... 24 symlinks removed. Linking /usr/local/Cellar/php/8.0.3... 24 symlinks created. Switching your apache conf Restarting apache Stopping `httpd`... (might take a while) ==> Successfully stopped `httpd` (label: homebrew.mxcl.httpd ==> Successfully started `httpd` (label: homebrew.mxcl.httpd PHP 8.0.3 (cli) (built: Mar 5 2021 00:11:37) ( NTS ) Copyright (c) The PHP Group Zend Engine v4.0.3, Copyright (c) Zend Technologies with Zend OPcache v8.0.3, Copyright (c), by Zend Technologies All done!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ワイ「何でsalt無しでHash::checkできるんや???」

とあるWeb制作会社 ワイ「パイセン、こないだ頼まれとったパスワード保存処理完成しましたで」 先輩「おお、ありがとうな」 先輩「・・・何やこれ」 ワイ「言われた通りハッシュ化しといて、saltと一緒に保存しとりまっせ」 ワイ「検証する時は、入力値とsaltくっつけてハッシュ化して比較すればいけまっせ」 先輩「何で令和に、しかもLaravel8つこてる時に生PHP書いとるんやお前」 先輩「お前が今言うた事、LaravelのHash::make と Hash::check でできるから、置き換えや」 ワイ「便利でんなー」 ワイ「ほな、 Hash::make でハッシュ化されたパスワードとsaltを受け取って保存しとく、みたいな感じでっか?」 先輩「saltは気にせんでええよ。 Hash::make はハッシュ化されたパスワードしか返さんし、 Hash::check する時にsaltは要らん」 ワイ「は? そしたらどうやって正しいパスワードかどうか検証するんでっか」 ワイ「気になって夜しか眠られへん」 (ワイ記法思ったより疲れたのでここまでで終わりです。 @Yametaro 先生へのリスペクトが高まりますね) 結論 Hash::makeの返り値に、入力値のハッシュ値だけでなくsaltやハッシュ化アルゴリズム等ハッシュ化に必要な情報が全て含めてある。よって、別の形で保存する必要は無い。 Hash::makeとHash::checkはPHP組み込み関数 password_hash と password_verify をラップして使いやすくしてくれたもの。便利だから使いまくろう。 調べたこと Hash::make と Hash::check の中身を見る所から始めます。 ソースコードを読むと、パスワードのハッシュ化と検証にはPHPの組み込み関数 password_hash と password_verify を使っているようでした。 そして password_hash の説明には以下のようにあります。 使ったアルゴリズムやコスト、そしてソルトもハッシュの一部として返されます。 つまり、ハッシュを検証するために必要な情報は、すべてそこに含まれているということです。 そのため、password_verify() でハッシュを検証するときに、 ソルトやアルゴリズムの情報を別に保存する必要はありません。 どのような形式で他の情報を付与しているのか? 検証時にどのように確認するのか? まで見ようと思うとCのコードを読む必要がありそうなのですが、当方Cはからきしであるため、ここまでにします。 https://github.com/php/php-src/blob/master/ext/standard/password.c 5/6 追記 @yu-ichiro さんにコメント(ありがとうございます!)頂いた所、この部分はPHPの仕様というより、ハッシュ化アルゴリズムの都合のようです。 パスワードのハッシュ値以外の情報をどのように付与しているのかについて、Laravel標準で使われているハッシュ化アルゴリズムBcryptの仕様がWikipediaにまとめられていました。 LaravelではBcryptの他にArgon2も使う事ができるので、Argon2の仕様も簡単にググってみましたが日本語記事が見つけられませんでした。こちらの仕様書は英語で難しかったので諦めましたが、気になる方がいれば読んでみても良いかと思います。 その他参考にしたドキュメントなど
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Wordpressでheaderで遷移できない時。

ググって出てくる事を試して全く改善されなかったので書いておきます。 ①前後にhtmlやechoでの出力はないか? ②Location前後にスペースはないか? ③exit;の記載 上記3点を確認しても改善されなくて途方にくれてたら上の方に... get_header(); こいつのせいでした。 こいつを遷移させるコードの 後ろに持ってきたら正常に動作しました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CakePHP4のテーブルが無い場合のモデルの対処、書く方法

コントローラーにビジネスロジックを書かずにモデルに書くための方法をまとめておきます(備忘録用)。 CakePHP2ならば... Model/User.php <?php App::uses('AppModel', 'Model'); /** * User Model */ class User extends AppModel { public $useTable = false; . . . } 上記のようにpublic $useTable = false;と記述すればテーブルを持たないモノでもロジックを書く事ができましたが、CakePHP4では下記のように書いてもエラーが返ってくる。 Model/Table/User.php <?php declare(strict_types=1); namespace App\Model\Table; use Cake\ORM\Table; /** * User Model */ class UsersTable extends Table { /** * Initialize method */ public function initialize(array $config): void { parent::initialize($config); $this->setTable(false); //エラーになる } } (CakePHP2の経験者なら必ずやるエラー。) コアな部分を読むとわかりますが$this->setTable()はStringしか入れられず、読み込むテーブルを無効化することができない仕様になっています。 色々と調べてみると、Model/Tableではテーブルが存在しないモデルは作れないみたいです。 How to do...? CakePHP4では、モデルのないフォームを使用することで 対処することができます。 一例で写真のバリデーションをモデルのないフォームで記述してみます。 Formの記述 Form/PhotoForm.php <?php namespace App\Form; use Cake\Form\Form; use Cake\Form\Schema; use Cake\Validation\Validator; /** * PhotoForm */ class PhotoForm extends Form{ protected function _buildSchema(Schema $schema): Schema{ return $schema ->addField('img',['type' => 'img']); } public function validationDefault(Validator $validator): Validator { $validator ->add('img','validator_msg',[ //自作のバリデーションの読み込み 'rule' => [$this,'uploadValidator'], ]); return $validator; } protected function _execute(array $data): bool { $result = true; if (!empty($errors)) { $this->setErrors($errors); $result = false; } return $result; } /** * uploadValidator - 画像のバリデーション */ function uploadValidator($check, array $context){ //PHPのアップロードのバリデーション $error = $check->getError(); switch ($error) { case UPLOAD_ERR_OK: break; case UPLOAD_ERR_INI_SIZE: return '10MB以下のファイルをアップロードしてください。'; case UPLOAD_ERR_FORM_SIZE: return 'ファイルが大きすぎます。'; case UPLOAD_ERR_PARTIAL: return 'アップロードに失敗しました。もう一度アップロードをお試しください。'; case UPLOAD_ERR_NO_TMP_DIR: return 'アップロードに失敗しました。もう一度アップロードをお試しください。'; default: return 'エラーが発生しました。アップロードファイルをご確認ください。'; } return true; } } Contorollerの記述。 Contoroller/PhotosContoroller.php <?php $data = []; $data['img'] = $this->request->getData('data.Photo'); //PhotoFormをインスタンス化してバリデーションを噛ませる $contact = new PhotoForm(); pr($contact->getErrors()); //アップロードした容量が多かった場合のエラー内容 //Array //( // [img] => Array // ( // [validator_msg] => 10MB以下のファイルをアップロードしてください。 // ) //) /* アップロードエラー検出時 ⇒ 次画像のアップロード状況調査処理を中断 */ if ($contact->execute($data)) { $this->Flash->warning($contact->getErrors()['img']['validator_msg']); break; } _executeメソッドが返せる値はbool値のみなので、バリデーションで弾かれた場合false、弾かれない場合はtrueを返すように書く。 そして、Controllerにif文で分岐を作るときれいにおさまる。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む