20211129のPHPに関する記事は8件です。

property_exists()でstatic|selfを使う

はじめに 静的クラス(関数)で自身のクラスのプロパティが存在するか調べたい、という願いを叶える記事です。 解決 普通に書くとこうなります。 ダメな例 public static function existsFoo() { return property_exists(static, 'foo'); } しかし、この状態だとこんなエラーが出ます。 syntax error, unexpected token ",", expecting ":" もう答えは書いてありますが、さっぱりわからない、という方もいると思います。 まずは、正解をご覧ください。 正解例 public static function existsFoo() { return property_exists(static::class, 'foo'); } staticに::classを付け加えました。 ::classとは class キーワードでもクラス名の解決を行うことが出来ます。 クラスの名前が ClassName になっているクラスの完全修飾名を取得するには、 ClassName::class を使います。 要するに、クラスの名前解決をしてエラーを取り除きますよーという優れものです。 また、property_exists()についても少しみてみます。 function property_exists($object_or_class, string $property): bool { } @param object|string $object_or_class The class name or an object of the class to test for @param string $property — The name of the property @return bool 第一引数の$object_or_classの型に注目です。object|stringとありますね。今回のケースではstring型になっています。 終わりに このstatic::classは色々なところで使われます。もし躓くことがあれば、また思い出してみてください。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Nikita Popov、PHP開発から離れる & PHP財団設立のお知らせ

Nikita、会社辞めるってよ The first is that I'm changing jobs at the end of the month, and won't be working on PHP in a professional capacity anymore. I'll still be around, but will have much less time to invest in PHP development. 今月末で転職するため、今後仕事としてPHPに関わることはなくなります。 今後も活動は続けますが、PHPに関わる時間はずっと少なるでしょう。 Nikita Popovは、ここ数年のPHPエコシステムを主導してきた人物です。 それまでもボランティアで年間1000以上のContributeをしていたのですが、2019年にJetBrainsに入社してからは毎年4000以上のContributeという圧倒的な仕事量で、PHPの進化・現代化に大きく貢献してきました。 PHP7以降はRFCの半分以上に関わってきたという恐ろしいバイタリティです。 一方でガチガチstrictぺちぱーの急先鋒であり、昔ながらのアバウトゆるふわPHPerとは相容れないところも多々ありました。 しかしながら、有無を言わせぬその仕事っぷりから徐々に賛同者を増やし、ついには動的プロパティ禁止なんてものを成立させるところまでやってきました。 そんなPHP開発の中心人物がいなくなってしまうと今後のPHPの進化が止まってしまうのではないかと懸念されるのですが、そうならないように手を打っていたみたいです。 PHP財団設立のお知らせ The second one is that the long-discussed idea of a PHP Foundation is finally becoming a reality! The initial purpose of the PHP Foundation is to support the development of PHP by contracting developers to work on php-src either part-time or full-time. If that sounds interesting to you, be sure to apply! 長い間議論されてきた、PHP財団のアイデアがついに現実となりました! PHP財団の最初の目的は、PHP開発者をサポートすることです。 パートタイムもしくはフルタイムの契約でPHP開発に関わってもらいます。 興味がわいたら、ぜひ応募してみてください! 詳しくはThe New Life of PHP – The PHP Foundationという記事にありますが、これまでのボランティアベースの開発ではなく、仕事としてPHP開発に携わるような仕組みを作り上げたとのことです。 もちろんNikitaだけの力ではなく、多くの企業や開発者たちの協力あってのものです。 とはいえつい先日Babelが火の車って記事を訳したばっかりなので、こっちも大丈夫なのか?と少々心配になってしまうわけですが、こちらは最初から多くの企業がバックについているので、早急にどうにかなるということはなさそうです。 特に、やたらPHPに力を入れているJetbrainsがいるのは心強いですね。 そもそもNikitaを自社の仕事そっちのけでフルタイムPHP開発に従事させていたのがJetbrainsですからね。 PhpStormがあるからという理由もあるでしょうが、この会社のPHPへの入れ込みっぷりはどういうわけなんだろうか。 PHP開発の現状 2021年時点において、PHP開発の主要人物はわずか二人です。 すなわち、Nikita PopovとDmitry Stogovです。 Nikitaは累積Contribution2位で、PHP本体のほとんどあらゆる場所に顔を出しています。 Dmitryは累積Contribution1位であり、そしてJITを理解している唯一の人物なのだそうです。 もちろん彼ら以外にもSara GolemonやChristoph M. Beckerといった長年PHPに関わっている人物がおり、CommitやContributeし続けている人もたくさんいますが、しかしお金が発生しているわけでもないので、別にいつ辞めてしまってもおかしくありません。 そんな現状をどうにかしようとする試みのひとつが、今回のPHP財団です。 PHPの開発を仕事としてやってもらいコア開発者を増やすことで、PHPの質と人員の量を保ち、そして結果として裾野も広がることに繋げていきます。 この試みが軌道に乗るようであれば、今後もPHPの進化は続いていくにちがいありません。 Open collective PHP財団は、 Open collective で個人・組織からの寄付を受け付けています。 せっかくなので微力ながら支援してみようと思ったのですが、なんか拒否されてできませんでした。 なんで?
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

テストタイトル

投稿内容 次に大きい文字 $test = "aa"; echo $test;
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravelでポケモン図鑑をつくってAWSでデプロイまでしてみた

株式会社やどかりのカイノと申します。 アドベントカレンダーを作ってみんなに書いてください〜って言ってやってもらってる張本人です。 今年もう少しで終わりだー今年もクソお世話になりましたー! やどかり&ネッコス Advent Calendar 2021の1日目を担当させていただきます。 明日は圭ちゃんです はじめに 2020年8月に入社して2021年6月までWeb開発をやってました。 2021年の7月からAndroid開発とWeb開発の2足のワラジでやってます。 今年はエンジニアとしてだけでなくマネジメント系の仕事もかなり増えててそっちもめちゃくちゃ面白いのですがやっぱりコード書いている時間は楽しいなとこの開発をしている時に改めて思いました。 去年も似たような記事を書いたのですが以前よりはレベルアップしているなー 、というか分かったこと増えたなーと感じました。 とはいえまだまだわからないところは多いので精進していきます。 ということで学んだことの棚卸しもしながら作りました 使用言語 Laravel 6.20 php 7.4 ポケモン図鑑つくりました(PC推奨) 作ったことなかったので一度作りたかったんですよね。 仕事の合間に結構急ぎで作ったので色々と雑になってます。ドメインもまだ設定してないです。 csv配布 ポケモン各種情報が入ったDBです。 これ使ってぜひみなさんもポケモンの何かアプリ作ってみてください。 クリックしたらダウンロードできます サイトはこんな感じです 一覧画面 レイアウトはテキトーです。 詳細画面 フシギダネは最初に仲間にしたポケモンなのでめちゃめちゃ覚えてるし好きですね。 種族値も取れることを知ったので徹底攻略みたいに表示してみました。 やったこと Laravelでコマンド作成 ポケモンAPIを叩く 取得したAPIを各パラメータに入れる DB設計&作成 ポケモンごとにDBにインサート 画面に表示 種族値も表示してみた AWSでサーバ構築してデプロイ Laravelでコマンド作成 app/Console/Commands/GetPokemonInfo.php このpathに下記のようにコマンド作成 今回はphp artisan command:getpokemoninfoで実行できるようにしました。 <?php namespace App\Console\Commands; require "vendor/autoload.php"; use Illuminate\Console\Command; use App\Models\Pokemon; use GoogleTranslate\GoogleTranslate; class GetPokemonInfo extends Command { /** * The name and signature of the console command. * * @var string */ protected $signature = 'command:getpokemoninfo'; /** * The console command description. * * @var string */ protected $description = 'Command description'; /** * Create a new command instance. * * @return void */ public function __construct() { parent::__construct(); } /** * Execute the console command. * * @return mixed */ public function handle() { try { $p_no_array = range(1, 898); foreach ($p_no_array as $no) { // すでに取得済みの場合はスキップ $pokemon = Pokemon::where('p_id', $no)->first(); if (!empty($pokemon)) { continue; } // ポケモンごとの情報をcurlで取得 $url = 'https://pokeapi.co/api/v2/pokemon/'.$no; $curl = curl_init($url); curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'GET'); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); $r = curl_exec($curl); $data = json_decode($r, true); $p_info = self::getPokemonInfo($data); print_r($p_info['id']); print_r($p_info['jp_name']."\n"); print_r($p_info['en_name']."\n"); print_r("\n"); $p_info = Pokemon::createPokemon($p_info); sleep(1); } curl_close($curl); } catch(Exception $e) { echo $e->getMessage(); } } static function getPokemonInfo($d) { $p_info = []; // パラメータを設定 $p_info['id'] = $d['id']; $p_info['en_name'] = $d['name']; $from = "en"; // English $to = "ja"; // 日本語 $st = new GoogleTranslate($p_info['en_name'], $from, $to); $p_info['jp_name'] = $st->exec(); $p_info['type1'] = $d['types'][0]['type']['name']; if (isset($d['types'][1])) { $p_info['type2'] = $d['types'][1]['type']['name']; } else { $p_info['type2'] = null; } $p_info['ability1'] = $d['abilities'][0]['ability']['name']; if (isset($d['abilities'][1]) && !$d['abilities'][1]['is_hidden']) { $p_info['ability2'] = $d['abilities'][1]['ability']['name']; $p_info['hidden_ability'] = $d['abilities'][2]['ability']['name']; } else { $p_info['ability2'] = null; if (isset($d['abilities'][1]['is_hidden'])) { $p_info['hidden_ability'] = $d['abilities'][1]['ability']['name']; } else { $p_info['hidden_ability'] = null; } } $p_info['hp'] = $d['stats'][0]['base_stat']; $p_info['attack'] = $d['stats'][1]['base_stat']; $p_info['defense'] = $d['stats'][2]['base_stat']; $p_info['special_attack'] = $d['stats'][3]['base_stat']; $p_info['special_defense'] = $d['stats'][4]['base_stat']; $p_info['speed'] = $d['stats'][5]['base_stat']; $p_info['total_stats'] = $p_info['hp'] + $p_info['attack'] + $p_info['defense'] + $p_info['special_attack'] + $p_info['special_defense'] + $p_info['speed']; $p_info['front_default'] = $d['sprites']['front_default']; $p_info['back_default'] = $d['sprites']['back_default']; if (isset($d['sprites']['other']['dream_world'])) { $p_info['dream_world_front_default'] = $d['sprites']['other']['dream_world']['front_default']; } else { $p_info['dream_world_front_default'] = null; } if (isset($d['sprites']['other']['home'])) { $p_info['home_front_default'] = $d['sprites']['other']['home']['front_default']; } else { $p_info['home_front_default'] = null; } if (isset($d['sprites']['other']['official-artwork'])) { $p_info['official_artwork_front_default'] = $d['sprites']['other']['official-artwork']['front_default']; } else { $p_info['official_artwork_front_default'] = null; } $p_info['height'] = $d['height']; $p_info['weight'] = $d['weight']; return $p_info; } } このコマンドでやりたいことは 「ポケモンAPIから取得した各ポケモン情報をパラメータに格納してDBにインサートさせる」ことです。 ポケモンAPIを叩く $p_no_array = range(1, 898); foreach ($p_no_array as $no) { // すでに取得済みの場合はスキップ $pokemon = Pokemon::where('p_id', $no)->first(); if (!empty($pokemon)) { continue; } // ポケモンごとの情報をcurlで取得 $url = 'https://pokeapi.co/api/v2/pokemon/'.$no; $curl = curl_init($url); curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'GET'); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); $r = curl_exec($curl); $data = json_decode($r, true); $p_info = self::getPokemonInfo($data); print_r($p_info['id']); print_r($p_info['jp_name']."\n"); print_r($p_info['en_name']."\n"); print_r("\n"); $p_info = Pokemon::createPokemon($p_info); sleep(1); } curl_close($curl); ポケモンAPIのurlにcurlでアクセスして受け取ったJSONをデコードしてます。 これを1~898回繰り返します。 図鑑No.1のフシギダネからNo.898バドレックスまでです。 サーバに攻撃にならないようにsleep()をいれて間隔を少しだけ空けてます。 取得したAPIを各パラメータに入れる getPokemonInfoというfunctionを呼び出して 各パラメータの中にポケモン情報を格納しています。 https://pokeapi.co/api/v2/pokemon/1 を実行してみるとわかるのですが情報がめちゃめちゃあってどれを使おうかを決めて各パラメータにいれねばなりません。 地味な作業でした。。。 static function getPokemonInfo($d) { $p_info = []; // パラメータを設定 $p_info['id'] = $d['id']; $p_info['en_name'] = $d['name']; $from = "en"; // English $to = "ja"; // 日本語 $st = new GoogleTranslate($p_info['en_name'], $from, $to); $p_info['jp_name'] = $st->exec(); $p_info['type1'] = $d['types'][0]['type']['name']; if (isset($d['types'][1])) { $p_info['type2'] = $d['types'][1]['type']['name']; } else { $p_info['type2'] = null; } $p_info['ability1'] = $d['abilities'][0]['ability']['name']; if (isset($d['abilities'][1]) && !$d['abilities'][1]['is_hidden']) { $p_info['ability2'] = $d['abilities'][1]['ability']['name']; $p_info['hidden_ability'] = $d['abilities'][2]['ability']['name']; } else { $p_info['ability2'] = null; if (isset($d['abilities'][1]['is_hidden'])) { $p_info['hidden_ability'] = $d['abilities'][1]['ability']['name']; } else { $p_info['hidden_ability'] = null; } } $p_info['hp'] = $d['stats'][0]['base_stat']; $p_info['attack'] = $d['stats'][1]['base_stat']; $p_info['defense'] = $d['stats'][2]['base_stat']; $p_info['special_attack'] = $d['stats'][3]['base_stat']; $p_info['special_defense'] = $d['stats'][4]['base_stat']; $p_info['speed'] = $d['stats'][5]['base_stat']; $p_info['total_stats'] = $p_info['hp'] + $p_info['attack'] + $p_info['defense'] + $p_info['special_attack'] + $p_info['special_defense'] + $p_info['speed']; $p_info['front_default'] = $d['sprites']['front_default']; $p_info['back_default'] = $d['sprites']['back_default']; if (isset($d['sprites']['other']['dream_world'])) { $p_info['dream_world_front_default'] = $d['sprites']['other']['dream_world']['front_default']; } else { $p_info['dream_world_front_default'] = null; } if (isset($d['sprites']['other']['home'])) { $p_info['home_front_default'] = $d['sprites']['other']['home']['front_default']; } else { $p_info['home_front_default'] = null; } if (isset($d['sprites']['other']['official-artwork'])) { $p_info['official_artwork_front_default'] = $d['sprites']['other']['official-artwork']['front_default']; } else { $p_info['official_artwork_front_default'] = null; } $p_info['height'] = $d['height']; $p_info['weight'] = $d['weight']; return $p_info; } DB設計&作成 今回はpokemonテーブルのみ作りました。 Laravelのマイグレーションで作っています。 <?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreatePokemonsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('pokemons', function (Blueprint $table) { $table->bigIncrements('id'); $table->integer('p_id')->nullable(); $table->string('jp_name')->nullable(); $table->string('en_name')->nullable(); $table->string('type1')->nullable(); $table->string('type2')->nullable(); $table->string('ability1')->nullable(); $table->string('ability2')->nullable(); $table->string('hidden_ability')->nullable(); $table->integer('hp')->nullable(); $table->integer('attack')->nullable(); $table->integer('defense')->nullable(); $table->integer('special_attack')->nullable(); $table->integer('special_defense')->nullable(); $table->integer('speed')->nullable(); $table->integer('total_stats')->nullable(); $table->string('front_default')->nullable(); $table->string('back_default')->nullable(); $table->string('dream_world_front_default')->nullable(); $table->string('home_front_default')->nullable(); $table->string('official_artwork_front_default')->nullable(); $table->integer('height')->nullable(); $table->integer('weight')->nullable(); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('pokemons'); } } ポケモンごとにDBにインサート インサートするファンクションをModel内で作成しました。 ここはシンプル。 <?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class Pokemon extends Model { protected $table = 'pokemons'; protected $dates = ['publication_date', 'expiration_date', 'registration_date']; protected $fillable = [ 'p_id', 'jp_name', 'en_name', 'type1', 'type2', 'ability1', 'ability2', 'hidden_ability', 'hp', 'attack', 'defense', 'special_attack', 'special_defense','speed', 'total_stats', 'front_default', 'back_default', 'dream_world_front_default', 'home_front_default', 'official_artwork_front_default', 'height', 'weight' ]; static function createPokemon($p_info) { if (empty($pokemon)) { self::create([ 'p_id' => $p_info['id'], 'jp_name' => $p_info['jp_name'], 'en_name' => $p_info['en_name'], 'type1' => $p_info['type1'], 'type2' => $p_info['type2'], 'ability1' => $p_info['ability1'], 'ability2' => $p_info['ability2'], 'hidden_ability' => $p_info['hidden_ability'], 'hp' => $p_info['hp'], 'attack' => $p_info['attack'], 'defense' => $p_info['defense'], 'special_attack' => $p_info['special_attack'], 'special_defense' => $p_info['special_defense'], 'speed' => $p_info['speed'], 'total_stats' => $p_info['total_stats'], 'front_default' => $p_info['front_default'], 'back_default' => $p_info['back_default'], 'dream_world_front_default' => $p_info['dream_world_front_default'], 'home_front_default' => $p_info['home_front_default'], 'official_artwork_front_default' => $p_info['official_artwork_front_default'], 'height' => $p_info['height'], 'weight' => $p_info['weight'] ]); } return true; } } 画面に表示 <div id="pokemon_block"> <div class="wrap-inner"> <ul class="poke_list flexlist"> <?php foreach ($pokemons as $pokemon) : ?> <li class="item"> <a href="{{ route('poke_show', $pokemon['id']) }}"> No.<?php echo $pokemon['id'] ?> <?php echo $pokemon['jp_name'] ?> <div class="imgarea"> <img src="<?php echo $pokemon['front_default'] ?>" alt=""> </div> </a> </li> <?php endforeach ?> </ul> </div> </div> 一旦全部のポケモンを表示させました。 'front_default'は画質が低いので大きな遅延はないのですが、他の重めの画像だと表示までに30秒くらいはかかってました。 今回は'front_default'を選んで遅延がないようにしました。 ただ、すこーしだけ遅いので全件表示よりは各世代ごとに分けて出すとかにする方が現実的ですね。 種族値も表示してみた <?php for($i = 0; $i < $pokemon['hp']/10; $i++): ?> <span class="single_gauge">▓</span> <?php endfor ?> "▓"という文字列を種族値/10の回数分だけ表示するように出しています。 これでこのポケモンの種族値の高さざっくりと見やすくなりましたね。 さてはこの種族値は何でしょう? ↓下のリンクが答えです。 AWSでサーバ構築してデプロイ サーバ構築はシンプルにしています。 ・ec2 linux/apache ・EIP ・RDS ハッサムが好き! かっこいい系のポケモンが好きなんですよね。 ハッサムはアルファサファイアやってた時にサイクルパでめっちゃ使ってましたね~ 使いやすいしかっこいいし(語彙力) おわりに これで終わりです。 もっと色々やりたかったのですが、とりあえずここまでにしました。 今回でポケモンDBを作れたので今後色々なアプリに使えるなーと思ってます。 勉強がてら遊びがてら使っていこうと思います。 今年も仕事納め前で絶賛忙殺中な毎日ですがわずかな合間を縫って10時間以内で全部作りました。 0から開発してサーバにアップするまでのスピード感も少しずつ付いてきた気がします。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHP sort array by key

$name = array_column($projects, 'name'); array_multisort($name, SORT_ASC, $projects);
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MAMPでローカルDB開発環境(確認編)

このページでは、下記の内容を解説していきます。 Laravelで作成したページを確認する ターミナルでMAMPのMySQLにログインする方法 MAMP環境にLaravelを制作された方は、このページを参考に、それぞれブラウザで開いて確認してみましょう。 Laravelで作成したページを確認する Laravelでは、artisanコマンドでビルトインWEBサーバーを起動することができます。 まず、Laravelの中にcdコマンドで移動します。 ターミナルで以下のコマンドを入力して下さい。 cd /Applications/MAMP/htdocs/Laravel 続けて、サーバーを起動します。 php artisan serve 上記のコマンドを入力するとURLが発行されますので、ブラウザにURLを入力してページを開きます。 すると作成中のWEBページを確認することができます あとはLaravelのルーティングで設定した後でブラウザから各ページを確認してください。 例:php artisan serveで表示されたURLが「http://127.0.0.1:8000」で、Laravelで「/login」というURLをルーティングした場合は、「http://127.0.0.1:8000/login」とすることでページを開くことができます。 サーバー起動中はターミナルにアクセスログが表示されます。 コマンド入力で、Laravelを編集する際は「command + C」でサーバーを落とし、入力画面に戻してください。 MAMP環境のMySQLヘログイン MAMP環境にアクセスします。 MAMPのコマンド群は「/Applications/MAMP/Library/bin/」に格納されていますので、cdコマンドで階層へ移動し、コマンドを入力することでMAMPのログインコマンドを使用することができます。 ターミナルで以下のコマンドを入力して下さい。 cd /Applications/MAMP/Library/bin/ 移動したら、MAMPのMySQLにログインします。 下記のコマンドを入力して下さい。 ./mysql -u root -p パスワードの入力を求められますが、MAMPのWEBスタートページに記載されているので、確認して入力して下さい。 MAMPのデータベースにMySQLでログインできましたか? ここからはサーバーサイドLESSON3で学習したように、コマンドで操作してデータベースを確認してみて下さい。 以上で、MAMPでLaravel環境構築は終了になります。 ここからは、もとのカリキュラムを進めてみてください。artisanコマンドを入力する箇所は、カリキュラム内容と異なるので、カレントディレクトリの表示を確認して、MAMPのLaravel直下で行う様に注意してください。 ご不明点はお問い合わせチャットからご質問ください。 まとめ artisanコマンドを使用するときは、「/Applications/MAMP/htdocs/Laravel_CRUD/Laravel/」階層で実行する。 artisan コマンドでサーバーを立てる。 MySQLにログインする時は、「Applications/MAMP/Library/bin/」階層でログインコマンド「./mysql -u root -p」を実行する。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel Eloquentとクエリビルダの違いを整理してみた

はじめに 株式会社じげんの藤井です。 リフォームマッチングサイト リショップナビの開発を担当しています。 今年度の6月に現場配属され、半年ほどLaravelを使った開発に携わってきたので、 混同しがちなクエリビルダとEloquentとの相違点をまとめます。 これからLaravelを触り始める方の参考になれば幸いです。 クエリビルダとは? LaravelのDB関連の機能として代表的なものに、クエリビルダがあります。 こちらはPHPを使ってSQL文を構築する仕組みで、メソッドチェーンでSQL関連のメソッドを並べてSQLを発行できるので、SQLがわかる人には直観的に理解しやすいという特徴があります。 具体的には、以下のように使用します。 use \Iluminate\Support\Facades\DB; $posts = DB::table('posts') ->select('id', 'author_id') ->where('author_id', '10') ->orderBy('created_at', 'desc') ->get(); DBファサードのtableメソッドで、扱う対象となるDBのテーブルを指定しています。 select, where, orderByに関しては生のSQLと同じで、クエリをgetメソッドで実行し、結果を$postsに格納しています。 クエリビルダは、SQLインジェクションからアプリケーションを守る機能を備えています。(Eloquentも同様) 不正なSQL文が送られてきた場合、それをSQL文ではなく単なる文字列として扱う(エスケープする)ことで、DBに対する攻撃を防ぎます。 具体的には、PHPのプリペアドステートメントに対してPDOパラメータを後からバインディング(PHPのbindValue()のような処理が内部的に走る)することで、挿入されたパラメータが生SQLとして解釈され、意図しないSQL文が発行されてしまうのを事前に防いでいます。 Eloquentとは? Laravelの機能として提供されているO/Rマッパーです。 RDBのテーブルとモデルを関連付ける機能を実現しており、PHPの書き方でDBを操作することを可能にします。 関連付ける具体的な方法としては、作成するモデルのクラス名を単数形で、DBのテーブル名をその複数形で作成することによって、自動的に紐づけることができます。 具体的には、以下のように使用します。 use App\Models\Post; $posts = Post::where('author_id', 10) ->orderBy('created_at', 'desc') ->get(); Postモデルに紐づいた、DBのpostsテーブルから、author_idカラムが10のものを検索し、created_atカラムを降順に並べて返却したデータを$postsに格納しています。 また、DB間の差異をEloquentが吸収する(例えば、本来MySQLとPostgreSQLで異なる書き方をするべきであるところを、Eloquentが各々に適したSQLを自動的に発行してくれる)ため、アプリケーション側からDBの種類や仕様を意識しなくて良くなります。 「アプリケーションとDBを疎結合にする」と言い、保守性が高まります。 クエリビルダとEloquentの返り値の違い クエリビルダとEloquentの大きな違いとして、返り値の形式があります。 クエリビルダの返り値 DB::table('posts') ->get(); stdClassのオブジェクト、またはそのCollectionとなります。 stdClassとはPHP標準で搭載されているClassで、プロパティやメソッドが一切定義されていないクラスです。 オブジェクトの代替として利用することがあるようです。 Eloquentの返り値 Post::all(); モデルオブジェクト、またはそのCollectionとなります。 Collectionの各要素がそのままPostクラスのインスタンスになっているため、foreachなどを使って個別の要素を取り出せば、クラス内に実装されたメソッドなども使えます。 クエリビルダとEloquentはどのように使い分ける? Eloquentは、実は内部処理でクエリビルダを利用しています。そのため、クエリビルダで使用できるメソッドは全てEloquentでも使用可能です。 クエリビルダの方が適している場合 パフォーマンスを重視する場合:一覧画面の実装など、多くのデータを取得する必要がある場合、よりパフォーマンスの良いクエリビルダが適しています。 複雑な条件を扱う場合:SQLに慣れていれば、クエリビルダはEloquentよりも発行されるSQLを把握しやすく、複雑な条件を適切に指定することができます。 Eloquentの方が適している場合 記述を簡潔にしたい場合:Eloquentではモデル同士にリレーションを貼ることができ、関連したモデルを簡単に呼び出すことが可能です。そのため、join句を使う必要のあるクエリビルダよりも相対的に記述が短くなります。 クエリスコープを使いたい場合:上記の「記述を簡潔にする」と近い項目ですが、クエリの共通条件をメソッド化してしまい切り出すことで、同じクエリを繰り返し書かなくて良くなる「クエリスコープ」という機能がEloquentに実装されています。繰り返しを避けることができるようになるだけでなく、条件の一部が変更になった際に修正が1箇所で足りるといったメリットがあります。 こうして、両者を使い分けていくと良いのではないかと考えています。  〆 私自身、両者の違いを曖昧に理解していたまま使用していましたが、今回まとめてみることで大変勉強になりました。 皆さまの参考になれば幸いです。 今回は以上となります。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

macOS に phpenv で PHP 8.1 をインストールする

PHP 8.1.0 が2021年11月25日にリリースされて、 phpenv + php-build では2020年11月29日に PHP 8.1.0 が追加された(ちなみに、 PHP 8.1.0 を追加する PR は私が送った)ので、早速 macOS にインストールしてみた。 といっても PHP 8.0 のときと変わらず、下記のコマンドでインストールできた。 $ PHP_BUILD_CONFIGURE_OPTS="--with-bz2=/usr/local/opt/bzip2 --with-iconv=/usr/local/opt/libiconv" phpenv install 8.1.0 下記のような感じで、問題なくインストールできていることを確認した。 $ phpenv versions 5.6.40 7.0.33 7.1 7.1.33 7.2 7.2.34 7.3.32 * 7.4 (set by /Users/tagawa/.anyenv/envs/phpenv/version) 7.4.26 8.0 8.0.13 8.1 8.1.0 $ phpenv shell 8.1.0 8.1.0 $ php -v PHP 8.1.0 (cli) (built: Nov 29 2021 11:23:44) (NTS) Copyright (c) The PHP Group Zend Engine v4.1.0, Copyright (c) Zend Technologies with Zend OPcache v8.1.0, Copyright (c), by Zend Technologies with Xdebug v3.1.1, Copyright (c) 2002-2021, by Derick Rethans 以上です。どなたかのご参考になれば幸いです。 以下、インストールした環境やエラーメッセージなどのメモ。 環境 macOS: 12.0.1 phpenv: v0.9.0-rc.1 php-build: v0.11.0dev はじめに実行したコマンド phpenv を最新の状態にして、 $ phpenv update PHP 8.1.0 をインストールしようとしたところ、 PHP 8.0 のときと同じように bzpi2 と iconv でエラーが発生した。 $ phpenv install 8.1.0 エラーメッセージ bzip2 configure: WARNING: unrecognized options: --with-png-dir, --with-libxml-dir, --with-icu-dir configure: error: Please reinstall the BZip2 distribution iconv configure: WARNING: unrecognized options: --with-png-dir, --with-libxml-dir, --with-icu-dir configure: error: Please specify the install prefix of iconv with --with-iconv=<DIR> 解決方法 PHP 8.0 のときと同じように、 brew で bzip2 と iconv をインストールして、冒頭のコマンドのように phpenv でインストールする際にパスを渡す。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む