20211011のPHPに関する記事は12件です。

テスト投稿

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

【Laravel】楽天レシピAPIからレシピを取得する方法

はじめに 献立アプリを作る際に、楽天レシピAPIからレシピ(1カテゴリにつきランキング上位4つのレシピ)を取得したので、そのときのコードを備忘録として残しておきます。 Bladeのbodyタグ内に記述 welcome.blade.php <body> @php $json = json_decode('APIテストフォームでパラメータ(categoryId=10といった感じ)を指定し、GETをクリックしたら出てくるデータをここにコピペ', true); use App\Models\Menu; $array = $json['result']; for($i=0; $i<sizeof($json['result']); $i++){ $menu = new Menu(); $menu->recipe_category_id = 10; $menu->user_id = 1; $menu->step = ''; $menu->seasoning = ''; $menu->menu_name = $array[$i]['recipeTitle']; $menu->image_path = $array[$i]['foodImageUrl']; $menu->description = $array[$i]['recipeDescription']; $menu->ingredient = implode(',', $array[$i]['recipeMaterial']); $menu->save(); } @endphp </body> この記述を行った後、このページをリロードすると、自分で用意したテーブルのカラム内にそれぞれのデータを入れることができます。 また、IDを変えていくことで、そのIDを持つカテゴリの上位4つのレシピをどんどん取得することができます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel8 マイページを見られるユーザーを限定する(アクセス制限)

やりたいこと マイページを自分(特定のユーザー)以外がアクセスできないようにしたい。 未ログイン状態からのアクセスがあればログイン画面にリダイレクトしたい。 ログイン済みであっても他人のマイページは閲覧できないようにしたい。 環境 PHP7 Laravel8 前提 マイページそのものは作成しておく マイページのURLにパラメータとしてユーザーIDが表示される状態になっている コントローラー コントローラーでは、if文を使ってパラメーターに入るユーザーIDとアクセスしようとしているユーザーのユーザーIDが一致しないと閲覧できないようにした。 app/Http/Controllers/RecordUsersController.php <?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use App\Models\Record; use App\Models\User; use Illuminate\Support\Facades\DB; class RecordUsersController extends Controller { // public function show_by_user($id) { $user = Auth::user(); $id = Auth::id(); $user = User::find($id); $records = Record::where('user_id',$user->id)->sortable()->get(); if($user->id == $id){ return view('record.showbyuser', [ 'user_name' => $user->name, 'records' => $records, ]); }else{ return redirect('/login'); } } } ルーティング ルーティングでは->middleware('auth')を追記して、未ログイン状態からアクセスするとログインを要求するように変更。 routes/web.php use App\Http\Controllers\RecordUsersController; // ユーザー投稿の一覧表示画面 Route::get('/record/user/{user_id}', [RecordUsersController::class, 'show_by_user'])->name('show_by_user_record')->middleware('auth'); できたこと マイページを自分(特定のユーザー)以外がアクセスできないようになった。 未ログイン状態からのアクセスがあればログイン画面にリダイレクトするようになった。 ログイン済みであっても他人のマイページは閲覧できないようになった。 うまくいっていないこと URLパラメーターに入るユーザーIDがアクセスしようとするユーザーIDと一致しないときにエラー文を表示したり、別ページにリダイレクトさせようとしたができなかった。if~else..の記述に問題があると思われるが、現状原因不明のまま。今後改善したい。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【PHP】配列ポインタ操作関数はIteratorを無視する

配列ポインタ操作関数にオブジェクトを突っ込む やたらたくさんあるPHPの配列関数ですが、大半は配列の全ての値に対して一律に処理を行う関数です。 キーと値を入れ替えるarray_flip、特定のカラムを取り出すarray_column、任意の関数を適用するarray_walkなどですね。 ところでこの中に一部、配列のポインタを直接触る関数群があります。 キーを取得するkey、値を取得するcurrent、ポインタをひとつ進めるnext、ポインタを先頭に戻すresetなどです。 よく見るとこれらの関数、シグネチャがarray|object &$arrayとなっていて、実は配列以外にオブジェクトも反復動作させることができます。 となればIteratorを使って操作したくなるわけですが、ここには罠が存在します。 class A implements IteratorAggregate{ public $a = 1; public $b = 2; public function getIterator() { return new ArrayIterator([3, 4]); } } // foreach $a = new A(); foreach ($a as $v) { var_dump($v); // 3, 4 } // current while ($v = current($a)) { var_dump($v); // 1, 2 next($a); } なんかIterator無視するんですけど。 IteratorはPHPの機能のひとつで、オブジェクトの反復動作を任意に設定することができる機能です。 本来はオブジェクトをforeachすると可視のプロパティが順に出てくるのですが、それを異なる動作にすることができます。 のですが、配列ポインタ操作関数は反復動作とは関係ないので動作に影響しないというわけですね。 一見同じような機能なのに動作が違うということで、非常にわかりにくい挙動となっています。 しかも、このあたりの話はマニュアルにも全く書かれていません。 僅かにforeachに書かれている『foreach は、 current() や key() のような関数で使われる、内部的な配列のポインタを変更しない点に注意して下さい。』がほぼ唯一の言及ですが、これの一文だけでIteratorが効かないとまで解釈しきれる人はそう多くないでしょう。 対策としては、そもそも今どき配列ポインタ操作関数を自力で使わないのが一番です。 ループ制御はオブジェクトだろうが配列だろうがforeach一択です。 ちなみにArrayObjectを継承すると、getIteratorが存在するかどうかでforeachとnextの出力がかわります。 益々わけがわからない。 class A extends ArrayObject{} // foreach $a = new A([1, 2]); foreach ($a as $v) { var_dump($v); // 1, 2 } // current while ($v = current($a)) { var_dump($v); // 何も出力されない next($a); } class B extends ArrayObject{ public function getIterator() { return new ArrayIterator([3, 4]); } } // foreach $b = new B([1, 2]); foreach ($b as $v) { var_dump($v); // 何も出力されない } // current while ($v = current($b)) { var_dump($v); // 3, 4 next($b); } PHP8.1 この動作は非常にわかりにくいということで、PHP8.1以降は配列ポインタ操作関数にオブジェクトを突っ込めないようになります。 PHP8.1でE_DEPRECATED、PHP9でエラーになる予定です。 $a = new A([1, 2]); while ($v = current($a)) { var_dump($v); next($a); } // PHP8.0まで エラー無し // PHP8.1以降 E_DEPRECATED // PHP9移行 エラー
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

laravel5.5 会員の退会機能 論理削除(ソフトデリート)の実装

はじめに laravel5.5を使用しており、最新のバージョンではありません。 論理削除の流れ 退会したユーザのデータをDBから完全に削除せず、 復元が可能であるような方法を論理削除と言います。 ユーザが'退会する'というボタンをクリック ↓ ユーザは登録した情報でログインができなくなる ↓ DBには、ユーザが会員登録したデータは残っている状態 前提 laravelの環境構築を終えている MAMPを使用 DBの接続を終えている ユーザのログイン機能は実装済み 実装手順 ログイン機能が実装済みの方は1から読み進めてください。 0.ログイン機能の実装 1.データベースの編集 2.userモデルの編集 3.seederでデータを入れてみる 4.ルーティングの追加 5.viewの編集 6.コントローラーの作成 7.動作確認 0. ログイン機能の実装 laravelのバージョンによってコマンドが異なります。 ターミナル //Larvel5.8まで $php artisan make:auth //Laravel6.x 以降 $composer require laravel/ui --dev $php artisan ui bootstrap --auth このコマンドのみでログイン機能は完了です。(便利すぎます...!) 本来は$php artisan migrateをターミナルで実行します。 今回はカラムの追加がありますのでそのまま次の作業に進みましょう。 1. データベースの編集 今回は既存のcreate_users_tableを編集していきます。 softDeletes()と定義することで論理削除に必要なカラムが作成されます。 * xxxxには日時などが入ります。 database/migrations/xxxx_create_users_table.php class CreateUsersTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('users', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->string('name_kana'); $table->string('address'); $table->char('postal_code', 7); $table->string('email')->unique(); $table->string('password'); $table->rememberToken(); + $table->softDeletes(); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('users'); } } カラムが追記できたら下記を忘れずに実行しましょう。 ターミナル $php artisan migrate DBにdeleted_atというカラムが作成されているか確認してみて下さい。 2. userモデルの編集 use SoftDeletes でソフトデリートを使用できるようにしています。 app/User.php <?php namespace App; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; + use Illuminate\Database\Eloquent\SoftDeletes; class User extends Authenticatable { use Notifiable; + use SoftDeletes; /** * The attributes that are mass assignable. * * @var array */ protected $fillable = [ 'name', 'email', 'password', ]; /** * The attributes that should be hidden for arrays. * * @var array */ protected $hidden = [ 'password', 'remember_token', ]; } 3. seederでデータを入れてみる まずは、Userモデルのseedを作成します。 ターミナル php artisan make:seeder UsersTableSeeder seedsディレクトリの中に UsersTableSeeder.phpが作成されますので、編集していきましょう。 name,email,passwordは何でも構いませんので自由に決めてください。 ⚠️emailのドメインはなるべくexample.comを使用した方が良いです。 database/seeds/UsersTableSeeder.php <?php use Illuminate\Database\Seeder; class UsersTableSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { + DB::table('users')->insert([ + 'name' => 'テスト', + 'email' => 'test@example.com', + 'password' => Hash::make('000000'), + ]); } } DatabaseSeeder.phpに以下を追記します。 database/seeds/DatabaseSeeder.php <?php use Illuminate\Database\Seeder; class DatabaseSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { + $this->call(UsersTableSeeder::class); } } 編集が終わったら、DBに反映させます。 $php artisan db:seed データが入っているか、DBを確認してみましょう。 4. ルーティングの追加 退会処理を行うためのルーティングを追記します。 routes/web.php <?php Route::get('/', function () { return view('welcome'); }); Auth::routes(); Route::get('/home', 'HomeController@index')->name('home'); + Route::post('/user', 'UsersController@withdrawal')->name('user.withdrawal'); 5. viewの編集 今回は、ヘッダーの中に”退会する”というボタンを作成したいと思います。 本来はフォームだけでもいいのですが、既存のheaderに合わせてドロップダウンの中に表示させたいため、 aタグとformを使って実装しています。 confirm('本当に退会しますか?')はアラートを表示させるために記述しています 以下のような確認のアラートが出てきます。 document.getElementById('withdrawal-form').submit()は、 formのid="withdrawal-form"と指定している部分の要素を取得して .submit()で送信処理を行っています。 resources/views/layouts/app.php <body> <div id="app"> <nav class="navbar navbar-default navbar-static-top"> <div class="container"> <div class="collapse navbar-collapse" id="app-navbar-collapse"> ...省略 <!-- Right Side Of Navbar --> <ul class="nav navbar-nav navbar-right"> <!-- Authentication Links --> @guest <li><a href="{{ route('login') }}">Login</a></li> <li><a href="{{ route('register') }}">Register</a></li> @else <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false" aria-haspopup="true" v-pre> {{ Auth::user()->name }} <span class="caret"></span> </a> <ul class="dropdown-menu"> <li> <a href="{{ route('logout') }}" onclick="event.preventDefault(); document.getElementById('logout-form').submit();"> Logout </a> <form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;"> {{ csrf_field() }} </form> </li> + <li> + <a href="{{ route('user.withdrawal') }}" + onclick="confirm('本当に退会しますか?'); + event.preventDefault(); + document.getElementById('withdrawal-form').submit();"> + 退会する + </a> + <form id="withdrawal-form" action="{{ route('user.withdrawal') }}" method="post" style="display: none;"> + {{ csrf_field() }} + </form> + </li> </ul> </li> @endguest </ul> </div> </div> </nav> @yield('content') </div> <!-- Scripts --> <script src="{{ asset('js/app.js') }}"></script> </body> 6. コントローラーの作成 まずは、UsersControllerを作成するコマンドを打ちます。 ターミナル $php artisan make:controller UsersController 作成されたら、中身を編集していきます。 Auth::user()は、ログインしている人の情報が取得できます。 ⚠️Authを使用するときはuseを書き忘れないように気をつけましょう。 $user->delete()で削除の処理を行います。 そして、Auth::logout()でログアウトさせています。 app/Http/Controllers/UserController.php <?php namespace App\Http\Controllers; use Illuminate\Http\Request; + use Illuminate\Support\Facades\Auth; class UsersController extends Controller { + public function withdrawal() + { + $user = Auth::user(); + $user->delete(); + Auth::logout(); + return redirect(route('login')); + } } 7. 動作確認 ここまで作業ができましたら、動作の確認をしてみます。 ①サーバーを立ち上げる ②seederで入れた情報でログインする ③ヘッダーの"退会する"ボタンを押す ④再度、seederで入れた情報でログインしてみる ログインができなければ、きちんと退会機能ができています。 dbも確認してみましょう。 deleted_atの中に日時が入っていれば、OKです。 最後に 今回はルーティングにidを持たせず実装を行いました。 softdeleteを使用すると、とても簡単に実装ができました。 参考文献 この記事は以下の情報を参考にして執筆しました。 [Laravel] ソフトデリートと取得、復元、完全削除
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

laravel facebookログインをローカル環境でテストしてみる。

初めに Facebook,Twitterログインをlaravelに実装したいけど、 それぞれの管理画面で見ると、localhostでは実装できないようになっている。 過去の記事では、できてたようですけど、厳しくなったらしい。 https必須とも記載ありました。 ngrokを使えば、HTTPSでも提供してくれるしできるんじゃね?と思い、試してみました。 SNSログイン完了後に情報を取得するまでが目的です。 結論 ngorkで発行されたURLをそれぞれのSNSの設定画面 コールバックURLを登録し、 .envに記載することでローカル環境でテストできました。 注意点 ngrok の無料プランは接続する度、払い出されるアドレスは変更されるので、 SNSの管理画面のリダイレクトuriと .envの APP_URLは都度変更が必要です。 めんどうであれば、有料プランに変更しましょう。 サーバーに公開する以外で他に簡単な方法あれば教えてください。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHPで画像サイズを変更してみた

Linuxのconvertコマンドを知らず、 convertコマンド1行で出来ることを苦戦しながらPHPで実装したので、 せっかくなのでメモとして残します。 業務での目的としては1000x1000の画像を、 上下に余白をつけて1000x1200にするというようなものでしたが、 Qiita用に少し修正して上下左右に余白をつける例にしてみました。 余白をつける方針 画像にどう余白をつけるかというと、 余白用の画像を作成して、その上に元の画像を重ねるという方針です。 サンプル ファイル名や余白の幅は固定になっているので、 参考にする場合は適宜修正していただければと思います。 resizeImage.php <?php // ファイルパスは固定 const IMAGE_PATH = __DIR__ . '/images/target.jpeg'; const RESIZE_WIDTH = 20; const RESIZE_HEIGHT = 20; const RESIZE_FILE_NAME = "after"; // 元の画像名を指定してサイズを取得 list($width, $height) = getimagesize(IMAGE_PATH); // リサイズ後の画像の幅、高さを計算 $afterWidth = $width + (RESIZE_WIDTH * 2); $afterHeight = $height + (RESIZE_HEIGHT * 2); // サイズを指定して余白画像を作成 $backgroundImg = imagecreatetruecolor($afterWidth, $afterHeight); $backgroundColor = imagecolorallocate($backgroundImg, 255, 255, 255); // 白の背景を作成 imagefilledrectangle( $backgroundImg, 0, 0, $afterWidth, $afterHeight, $backgroundColor ); //画像オブジェクトを返却 $baseImage = @imagecreatefromjpeg(IMAGE_PATH); // 余白画像と元画像を合成 imagecopy( $backgroundImg, $baseImage, RESIZE_WIDTH, RESIZE_HEIGHT, 0, 0, $width, $height ); // コピーした画像を出力する imagejpeg($backgroundImg , RESIZE_FILE_NAME . '.jpg'); プログラムの説明 元画像のサイズを取得 list($width, $height) = getimagesize(IMAGE_PATH); listを使って、getimagesizeの返却値から画像の幅と高さを取得してます。 元画像のサイズが固定なら不要ですが、今回は元画像のサイズによらず上下に余白をつけるだけなので、 元画像のサイズを取得します。 ちなみにgetimagesize()は画像の形式なども返却されるようです。 余白画像を作成 $backgroundImg = imagecreatetruecolor($afterWidth, $afterHeight); imagecreatetruecolorで余白画像を作成します。 パラメータは幅と高さです。 余白の画像なので元画像より幅と高さを大きくします。 この段階だと背景色は黒になります。 また返却値は画像オブジェクト(GDImage クラスのインスタンス)です。 余白画像を白にする $backgroundColor = imagecolorallocate($backgroundImg, 255, 255, 255); 余白画像作成時点で色の指定が出来ればいいのですが、 最初からは指定が出来ないようだったので、 まずはimagecolorallocateで A color identifier(色のID)を取得します。 1つ目のパラメータは先ほど作成した画像オブジェクトです。 2, 3, 4はRGBで指定すればいいようなので、 白以外にしたい場合はここを変更します。 ちなみに、この時点では色のIDを取得しただけなので余白画像は白くなってません。 最初、ここで苦戦しました。 「白くならない、、」と。ちゃんとドキュメントは読んだ方がいいですね。 // 白の背景を作成 imagefilledrectangle( $backgroundImg, 0, 0, $afterWidth, $afterHeight, $backgroundColor ); 次に、imagefilledrectangleで画像に色をつけます。 一応説明すると、 1つ目のパラメータで色をつけたい画像オブジェクトを指定。 2, 3つ目のパラメータで画像左上のx,y座標。 4, 5つ目のパラメータで画像右下のx,y座標。 6つ目のパラメータで色のIDを指定。(ドキュメント的には「imagecolorallocate() で作成された色識別子。」) やっと背景画像が白くなりました。 余白画像に元画像を合成 //画像オブジェクトを返却 $baseImage = @imagecreatefromjpeg(IMAGE_PATH); // 余白画像と元画像を合成 imagecopy( $backgroundImg, $baseImage, RESIZE_WIDTH, RESIZE_HEIGHT, 0, 0, $width, $height ); imagecopyで余白の上に元画像をコピーします。 パラメータが多くてややこしいですが、やりたいことさえわかっていれば簡単かと思います。 1つ目のパラメータに背景の画像オブジェクト、2つ目に元画像の画像オブジェクトを指定します。 余白を作る上で大事なのが3, 4つ目のパラメータで、 ここで元画像のコピーの位置をずらすことで余白になります。 画像ファイルに出力 // コピーした画像を出力する imagejpeg($backgroundImg , RESIZE_FILE_NAME . '.jpg'); imagejpegでjpegに画像ファイルを出力します。 ここでやっと画像が作成されます。 改良の余地はたくさんありそうですが、 普段、PHPで画像の操作をしていない私のような方の参考になればと思います。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

composerコマンドのオプションをデフォルトにしたい

オプションを毎回付けるのが面倒 面倒な上に忘れがち。 $ composer install -o $ composer dump-autoload -o デフォルトでオプションを付ける composer.jsonのconfigから設定できます。 composer.json { "config": { "optimize-autoloader": true } } 設定後は自動でオプションが適用されます。 # オプションなしでOK $ composer install $ composer dump-autoload 設定方法の詳細は公式ドキュメントに掲載されています。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

composerのロングオプションはコマンドによって違うこともある

ロングオプションに注意! autoloadのoptimizeオプションはinstallとdump-autoloadでロングオプションの表記が違います。 詰みました。 $ composer install --optimize-autoloader $ composer dump-autoload --optimize ショートオプション-oは共通です。 $ composer install -o $ composer dump-autoload -o 他にもこういうオプションがあるのだろうか... 詰んだら公式ドキュメントへ。 普段はショートオプション使いですがw ロングオプションの方がコマンドの意図が分かり易いので、覚えておいて損はないと思います!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Laravel】CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP のせいでtimestampのカラムが勝手に更新されてしまう

timestampはデフォルトで, CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP属性がつく マイグレーションファイルでtimestampのカラムを設定すると, レコードを更新すると日付が自動更新されるようになっています. DBを確認すると, カラムの属性にCURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMPがついています. これを消せばカラムが自動更新することがなくなります. migrate.php <?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class TestTable extends Migration { public function up() { Schema::create('test_tables', function (Blueprint $table) { $table->timestamp('output_at')->comment('出力日時'); }); } // 略 } nullableにするだけ マイグレーションファイルのカラムを設定するときにnullableと追加すると, CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMPが消えるようになります. migrate_new.php <?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class TestTable extends Migration { public function up() { Schema::create('test_tables', function (Blueprint $table) { $table->timestamp('output_at')->nullable()->comment('出力日時'); }); } // 略
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Javascript】画像URLを入力した瞬間に画像プレビューできるテキストエリアを作ってみた

はじめに 最近業務でjavascriptでUI実装をする機会が増え、その最中今後も使いそうな機能については備忘録をのこしておこうと思っての投稿です! 「ネット検索した画像URLをそのまま画像出力をする機能が必要だったためその機能実装メモです! こんなかんじ? 完成コード hoge.blade.php // 画像URL入力 <input type="url" id="service-infomation-image-url" oninput="serviceInfomationImagePreview()" name="image_url[]" placeholder="画像URLを入力してください"> <div class="item-wapper6"> //画像マウスオーバーで拡大するcss <div class="img-wapper6"> //画像マウスオーバーで拡大するcss <span> <div id="image-position" class="-ml-16 mr-80 -mt-5"></div> </span> </div> </div> //Javascript <script type="text/javascript"> function serviceInfomationImagePreview() { var url = document.getElementById("service-infomation-image-url"); var urlValue = url.value ; var imagePosition = document.getElementById("image-position"); imagePosition.innerHTML = '<img src="' + urlValue + '" class="mt-7 ml-16 w-full h-full object-center object-cover lg:w-8 lg:h-8" />'; } </script> id="image-position”のタグの配下領域にこのimgタグをセット。 textareaタグに入力した値がこの このimgの値に動的にセットさせる。  この処理のトリガーをinputタグに入力したタイミングにするため oninput="serviceInfomationImagePreview()とします。  こうすることで入力した時点でurlの画像が即時描画という流れです! hoge.css .item-wapper img:hover { transform: scale(3); transition-duration: 0.3s; margin:0 0 0 30px; } .item-wapper img{ transition-duration: 0.3s; } 画像マウスオーバーで拡大するcss
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【PHP】match式のやり方

<?php $number = 3; $result = match ($number) { 1 => 'one', 2 => 'two', 3 => 'three', default => 'other', }; echo $result; 結果 3
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む