20210415のPHPに関する記事は10件です。

初学者がLaravelを学ぶ3(コントローラー)

コントローラーについて webページの基本的な処理はコントローラを使って行うのが基本です。 またMVCアーキテクチャの基本となるものです。 MVCとコントローラ ルーティングはアクセスしたアドレスをもとに処理を割り振る役割でした。ただそれだけではなく、具体的に実行するべき処理は別に用意されていて、それを特定アドレスに割り振って呼び出すための処理です。 MVCとはモデル、ビュー、コントローラの頭文字をとったものです。 モデルはデータ処理全般を担当します。具体的にはデータベースに関する処理全般を司ると言って良いと思います。 ビューは画面表示を担当します。表示に使うテンプレートなどがこれに相当します。 コントローラは全体の制御を担当します。必要に応じてモデルからデータを取得したりビューを利用して画面表示を作成したりします。 コントローラの作成 作成中のアプリのフォルダディレクトリで以下のコマンドを実行することで作成できます。 php artisan make:controller HelloController これによってHelloControllerが作成できます。 ちなみにHelloの部分の名前を変えることで違うコントローラ名で作成することができます。 下記はHelloController.phpの中身です。 順番に内容を見ていきます。 <?php namespace App\Http\Controllers; use Illuminate\Http\Request; class HelloController extends Controller { // } controllersと名前空間 コントローラはクラスとして作成されます。このクラスはApp\Http\Controllersという名前空間に配置されます。 名前空間とはクラスを階層的に整理するための仕組みです。フォルダを使って階層的にファイルを管理するのと同じだと思っておけばいいと思います。 一行目のnamespace App\Http\Controllers; は名前空間を指定しています。 useによるインポート 次に記述されているのはuse文です。以下のように記述されています。 use Illuminate\Http\Request; ここではIlluminate\Httpパッケージ内に用意されているRequestを使える状態にしています。 まだこの段階ではRequestは不要ですがこれから多用することとなるクラスのためデフォルトでuse文が追加されています。 クラスの定義 続いてクラスが提起されています。HelloControllerは以下のように定義されています。 class HelloController extends Controller コントローラクラスはこのようにControllerというクラスを継承して作成します。 アクションを追加する コントローラに用意される処理はアクションと呼ばれる。これはメソッドの形で用意されます。 今回は以下のようにindexメソッドを追加してみます。 ここではindexのように引数を持たないメソッドとして用意されています。(場合によっては引数を用意することもあります。) アクションメソッドはreturnを使ってHTMLのコードを返しています。結果、returnした内容がウェブブラウザに返され表示されることになります。 <?php namespace App\Http\Controllers; use Illuminate\Http\Request; class HelloController extends Controller { public function index() { return <<<EOF <html> <head> <title>Hello/Index</title> <style> body {font-size:16pt; color:#999; } h1 { font-size:100pt; text-align:right; color:#eee; margin:-40px 0px -50px 0px; } </style> </head> <body> <h1>Index</h1> <p>これは、Helloコントローラのindexアクションです。</p> </body> </html> EOF; } } ただこれだけでは表示はできません。ルーティングを変更する必要があります。 web.phpを開き先程の記述を削除しルーティングを変更していきます。 Route::get('hello', 'HelloController@index'); 第二引数には関数ではなくコントローラ名@アクション名が記述されています。 これにより第一引数のアドレスにアクセスしようとすると第二引数に指定されたアクションが実行されるようになります。 コントローラを使ったルートパラメータの利用 ルートパラメータ(アクセスする際にパラメータとして値を渡すことができる)を使用する場合は以下のように編集します。 class HelloController extends Controller { public function index($id='noname', $pass='unknown') { return <<<EOF <html> <head> <title>Hello/Index</title> <style> body {font-size:16pt; color:#999; } h1 { font-size:100pt; text-align:right; color:#eee; margin:-40px 0px -50px 0px; } </style> </head> <body> <h1>Index</h1> <p>これは、Helloコントローラのindexアクションです。</p> <ul> <li>ID: {$id}</li> <li>PASS: {$pass}</li> </ul> </body> </html> EOF; } } ルーティングも以下のように編集していきます。 Route::get('hello/{id?}/{pass?}', 'HelloController@index'); これによって/hello/taro/yamadaというようにhelloの後に二つのパラメータをつけてアクセスするとそれらのパラメータが画面に表示されます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[PHP] 2つ以上の配列の中の共通の値を取得する

概要 二つの配列を比較して同じ値だけを取り出したい場合の方法をメモします。 方法 array_intersect()を使うことで共通の値だけを取り出すことが可能 <?php $array1 = [1, 2, 3]; $array2 = [2, 3, 4]; $result = array_intersect($array1, $array2); print_r($result); 出力結果 Array ( [1] => 2 [2] => 3 ) 3つ以上を比較する場合は第三引数以降に配列を追加することで可能 $result = array_intersect($array1, $array2, $array3, $array4);
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Monologでログファイルのパーミッションを指定する

Monologでファイルにログを出力する場合、StreamHandlerまたはStreamHandlerを継承したクラスを使用しますが、ファイルのパーミッションを指定する方法を記述します。 ファイルのパーミッションを指定する場合、コンストラクタの第4引数の$filePermissionに8進数で指定します。 new StreamHandler('/app.log', Logger::INFO, true, 0755); StreamHandler.phpの105行目でchmod関数で設定しています。(chmodなのでWindowsでは効果はありません。) StreamHandler.php if ($this->filePermission !== null) { @chmod($this->url, $this->filePermission); }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHPのエラーを表示する

サーバによっては設定でエラーが表示されないようになっていることがある。 エラーを表示させるには以下のコードを追加する。 コード ini_set('display_errors', "On"); 使用例 <?php // エラーを出力する ini_set('display_errors', "On"); $a=1000; $b=0; $c=$a/$b; //0で割っているのでエラーが出る
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

連想配列について

初心者の方は連想配列(辞書的配列)を学ぶと「どこで使うんだろう」と思われる方が多いと思います。 今回はPHPを例にどこで使われているかの一例を紹介いたします。 <?php // データベースからデータを取得する $sql = "SELECT id,date,text FROM mental ORDER BY id desc;"; $stmt = $pdo->prepare($sql); $stmt -> execute(); ?> <table> <tr> <th>id</th> <th>日時</th> <th>メンタルの状態</th> </tr> <!-- HTMLテーブルの2行目以降で全てのレコードを表示 --> <?php while ($row = $stmt -> fetch(PDO::FETCH_ASSOC)) { ?> <tr> <td><?= $row["id"] ?></td> <td><?= $row["date"] ?></td> <td><?= $row["text"] ?></td> </tr> <?php } ?> 今回のサンプルは例外処理部分をカットしたものを掲載しています。実際作成したものは例外処理が入っています。こんな感じで使います。 SELECT文のカラム名が「*」だったのでカラム名をコーディングするように変更いたしました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【新人プログラマ向け】開発とソースコードレビューのコツ

はじめに この4月から新しくプログラマになった方が大勢いると思います。 ようこそこちら側へ! 私は7年システムエンジニアをやっている者です。 新人プログラマに向けて開発とレビューのコツを伝えられたらいいなと思ってこの記事を書きました。 私が実際に作業する時に意識していることなので100%の正解ではないですが、刺さる部分だけ持って帰ってください! 開発のコツ コードを書き始める前に 開発する時のフローやルーティンを構築すると良いです。 私の場合はコードを書き始める前のフローを大切にしています。 その開発案件の要件を把握する どういう点で困っていて、何をするとゴールなのか 言われたことそのまま開発してもゴールじゃない可能性があります 要件を把握したらその周辺の機能やコードについてひたすら調査します どういう機能なのか どういう構造でできているものなのか 新人だと早く着手しなきゃ!と焦っていきなりコードを書きがちですが、調査の時間を多くとった方が結果的に質が高く早く終ることが多いです 周辺調査を終えて開発方針を固めたら先輩や有識者にチェックしてもらう まだコードは書き始めません 調査した内容が合っているか、開発方針が合っているかをこの段階でチェックしてもらいましょう そうすることで出戻りが少なく開発がスムーズに進みます この時点でようやくコードを書き始めます 実際にコードを書く際に まずコードの全体像が掴めるように概形を作成しコミットしてしまうことをオススメします。 例えば以下のようなコードに処理を追加する場合、まずは概形を以下のように書くと良いです。(exec_sampleに_exec処理を追加する) TODOコメント等で何をやるかもこの時点で書いてしまうと、後から「何すればいいんだっけ?」とならないので良いです。 sample.php <?php class Sample { /** * 何らかの実行メソッド */ public function exec_sample(){ // 何を実行しているのかよく分からないがとりあえず長い処理 // TODO: ここに処理を差し込む $result = $this->_exec(); // TODO: デバッグ文を後で消す var_dump($result); // 何を実行しているのかよく分からないがとりあえず長い処理 } /** * TODO: doc書く * * @return string $result */ private function _exec(){ // TODO: 必要な変数の確保、必要に応じて引数で渡す // TODO: $resultは初期値空文字で良いか? $result = ''; // TODO: Aの条件を実装、必要に応じて判定関数化 if(true){ // TODO: Aのケースの場合の処理 $result = 'Aのケースです'; } elseif(true) { // TODO: Bのケースの場合の処理 $result = 'Bのケースです'; } elseif(true) { // TODO: 他にケースあるか?C以降を検討する } else { // TODO: どこにも該当しなかった場合の処理 // 例外を投げるか? // catchする必要があるか?親でキャッチしてくれるか? } return $result; } } $sample = new Sample(); $sample->exec_sample(); また、処理の共通化等に関してもまずは愚直に書いてから「あ、ここ共通化できそう」と思って後からやるのをオススメします。 慣れない状態で先に共通化を意識して書いていくと肝心のロジックが破綻したりするので。 概形を作る ロジックを作る 共通化や関数化をする インデントや使わなかった変数を消すなどのリファクタをし整形する 意識して欲しいことは「まず要件を満たして動くコードを書くことが最優先」ということです。 仕事としてプログラムを書いている以上、正しく意図した通りに動くコードに価値が生まれます。 極端な話、インデントがぐちゃぐちゃになっていようが、未使用の変数が残っていようがその機能を使うユーザーには関係がありません。 もちろんその後の保守性や全体のコードの品質に関わってくるのでキレイにこしたことはないですが、開発時の優先順位は考えた方が良いです。 ソースコードレビューのコツ 少し慣れてきたらソースコードレビューをやる機会もあると思います。 レビューに関しても自分の中でフローを構築すると良いです。 その開発案件の要件を把握する 要件を把握したらプルリクをチェックする 書いているコードの意味や意図が分からなければ聞く その周辺の機能やコードについて調査する 類似の機能やコードはないか レビューする際にオススメなのは手元にコードを持ってきて、改修内容を見つつそのコードにコメントを入れていくことです。 例えば以下のような感じ。 monster_hunterレビュー前.php <?php $weapons = ['片手剣','双剣','大剣','太刀','ランス','ガンランス','ハンマー','笛','スラッシュアックス','チャージアックス','操虫棍','ライトボウガン','ヘビィボウガン','弓']; function make_seed() { list($usec, $sec) = explode(' ', microtime()); return $sec + $usec * 1000000; } srand(make_seed()); $randval = rand(0,13); var_dump($weapons[$randval]); monster_hunterレビュー後.php <?php // クラス化した方が良さそう // 手元のスクリプトだし別にそこまでしなくても良いか? // 武器種の定義 // 武器種の増減があった場合にはここの配列を操作すればよいだけになっている // 各武器種を定数化した方が今後拡張しやすいか? $weapons = ['片手剣','双剣','大剣','太刀','ランス','ガンランス','ハンマー','笛','スラッシュアックス','チャージアックス','操虫棍','ライトボウガン','ヘビィボウガン','弓']; // 乱数のシード値を現在時刻から算出している // これはphp公式リファレンスに載っているもの // @see https://www.php.net/manual/ja/function.srand.php // TODO: docコメント追加してもらう function make_seed() { // microtimeで現在時刻を取得 // msec secの形式の文字列を返す // 例: 0.05883800 1618473243 // それを半角スペースで分割してusecとsecに入れている // usec = 0.05883800 // sec = 1618473243 list($usec, $sec) = explode(' ', microtime()); // var_dump($sec + $usec * 1000000); // 例: 1618597943のような数値となる return $sec + $usec * 1000000; } // 乱数生成器を先程のシード値で初期化 srand(make_seed()); // 乱数を0~13で生成する // TODO: これは武器種数によって変わるので$weaponsのsizeの方が良い、後で指摘する $randval = rand(0,13); // 全武器種の中からランダムに1つの武器を選ぶ処理 // 今日何の武器を使うか迷った時に回す想定 // var_dumpでなくprintの方が良さそう var_dump($weapons[$randval]); コードに対してコメント文を書いていくと気付いたことがすぐメモできたり、あとで確認する時に漏れが少なくなるのでオススメです。 また実際に動かしつつこの変数にはどういう値が入っていて、どういう使い方をしているか、みたいなメモを残していくとコードリーディングが捗り理解が早くなります。 ここから実際にプルリク上で指摘することを決めてコメントします。 指摘する際は温度感を表すために[MUST]や[SHOULD]などを使うと良いでしょう。 ソースコードレビューのレベル あくまで自己流ですが、自分の中でレビューに段階(レベル)を設けています。 レビューをする際に「どのレベルまでレビューするか」 またはレビューをしてもらってる際に「どのレベルの指摘なのか」 を考えると自分のコードは今どのレベルの品質になっているかの目安になって良いです。 レベル1: インデントなどのスタイル、誤字、未使用変数 レベル2: ロジックが破綻していないか、意図した通りに動いているか レベル3: 要件を満たしているか、影響する範囲は正しいか レベル4: 処理負荷が高くないか、重くないか レベル5: 設計、この位置にこの処理があるのはキモいなど レベルの高いレビューをクリアすればするほど良いコードになっていると言えます。 私は案件によってレビューのレベルを変えています。 例えば急ぎ目の案件で来週にはリリースしないといけないような案件ではレベル3までしか見ません。 今後も長く使っていく機能、プロダクトなコアな機能、リファクタ案件などはレベル5まで見ます。 新人の方はまずはレベル3を目指してください。 レベル1に関して、静的解析ツールなど自身で気付ける形にしておくのが良いです。 レベル2に関して、テストコードを書く、網羅テストするなどで担保しておくのが良いです。 レベル3に関して、コードだけでは判断つかない部分だったりするので先輩や有識者を頼ると良いでしょう。 レベル4に関して、大体重いのはループ内でDBアクセスしているものです。 100回select文を実行し、1000回update文を実行している、ようなコードは要注意です。 このあたりは経験がものをいうところが大きいので経験をたくさん積んでください。 N+1クエリ、計算量などがキーワードとなります。 レベル5に関して、これは設計を学ぶ必要があります。 社内に設計に詳しい人がいればその人を頼るといいでしょう。 MVCモデル、クリーンアーキテクチャ、デザインパターンなどがキーワードとなります。 まとめ 慣れないことが多く戸惑うことが多いでしょうが、刺さる方法・やりやすい方法を模索して1人前のエンジニア・プログラマになってください!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHP ハッシュ関数

はじめに ・PHPで、セキュリティに関心がある方 ・ハッシュ、ハッシュ関数が分からない方 ハッシュとは ハッシュとはアルゴリズムに基づき、読解不可能な文字列などに置換する仕組みのことです。 ※パスワードなどの機密情報を扱う時になどに使用します。 代表的なハッシュ関数 PHPには標準で、文字列からハッシュ値を計算し、生成する関数が存在します。 ※以下が代表的な、ハッシュ関数です。 ハッシュ関数 詳細 hash 指定したアルゴリズムで、ハッシュ値を生成する ※バージョン 5.1.2以降 md5 MD5方式で、16進数・32文字のハッシュ値を生成する sha1 SHA-1方式で、16進数・40文字のハッシュ値を生成する password_hash 機密性の高い文字列のハッシュ値を生成する ※バージョン 5.5以降 hash sample_hash.php <?php $str = 'hoge'; var_dump(hash("sha256", $str)); ?> 実行結果 string(64) "ecb666d778725ec97307044d642bf4d160aabb76f56c0069c71ea25b1e926825" md5 sample_md5.php <?php $str = 'hoge'; var_dump(md5($str)); ?> 実行結果 string(32) "a577f0035386e7d04551e867b3d9f024" sha1 sample_sha1.php <?php $str = 'hoge'; var_dump(sha1($str)); ?> 実行結果 string(40) "31f30ddbcb1bf8446576f0e64aa4c88a9f055e3c" password_hash sample_password_hash.php <?php // ハッシュ値を計算する前の文字列 $str = "hoge"; // ハッシュ値を計算 password_hash($str, PASSWORD_DEFAULT); ?> 実行結果 string(60) "$2y$10$zgsW6rm.9wcBnkSw2/Jp3OiJSDy5gsEUAM6fum4zva7/5jauNVixK" おまけプログラム IDとパスワードを入力し、DBに保存するプログラムを作成しました。なお、パスワードはpassword_hashを使用し、ハッシュ化しています。 ※今回使用するDB情報 ユーザー名 DB名 カラム名情報① カラム名情報② id_pass_user hashdb id_data varchar(100) pass_data varchar(100) 新規で作成した、ユーザーにはパーミッション(権限)がないので、以下のコマンドで付与します。今回の場合は、id_pass_userにDBレベル(hashdb)での付与になります。 パーミッションの付与(DBレベル) mysql> grant all on hashdb.*to id_pass_user@localhost; ※入力する、IDとパスワード ID パスワード hogeID hogePASS コード一覧 data_vaildataion.php <?php // ID,パスワードと、DBのバリデーションの補助を実装したクラス class DataVaildataion { //ID,パスワードと、DBのバリデーションに必要なデータをカプセル化 private $hash_pass = null; private $success_message = null; private $error_message = null; private $clean = array(); # ゲッターは今回必要ないので、コメントアウト /*public function getHashPass() { return $this->hash_pass; } public function getSuccessMessage() { return $this->success_message; } public function getErrorMessage() { return $this->error_message; } public function getClean() { return $this->clean; }*/ // セッターで、ID,パスワードのバリデーションの補助 public function setHashPass($hash_pass) { return $this->hash_pass = $hash_pass; } public function setSuccessMessage($success_message) { return $this->success_message = $success_message; } public function setErrorMessage($error_message) { return $this->error_message = $error_message; } public function setClean($clean) { return $this->clean = $clean; } } ?> db.php <?php // 必要なプロパティのあるクラスファイルの呼び出しと、インスタスの生成 require_once('data_vaildataion.php'); require_once('from.php'); $data = new DataVaildataion(); // データベースの接続情報を定数で実装 define( 'DB_HOST', '127.0.0.1'); # phpadminの場合は、localhost define( 'DB_USER', 'id_data_user'); define( 'DB_PASS', '各自のパスワード'); define( 'DB_NAME', 'hashdb'); // Dataクラスのセッターを使用し、ID,パスワードのバリデーションを実装 if(!empty($_POST['btn_submit'])) { if(empty($_POST['id_data']) || empty($_POST['pass_data'])) { echo $data->setErrorMessage('IDまたは、パスワードが未入力です。').PHP_EOL; exit(); }else { // Dataクラスのセッターを使用し、IDのサニタイズの実装 (シングルクフォートと、ダブルクフォートをHTMLに変換しない) $data->setClean($clean['id_data'] = htmlspecialchars( $_POST['id_data'], ENT_QUOTES)); // 上記と同じく、パスワードのサニタイズの実装 $data->setClean($clean['pass_data'] = htmlspecialchars($_POST['pass_data'], ENT_QUOTES)); // セキリュティを考慮し、password_hashを採用(同じハッシュを生成しない。DBとの比較の際は、password_verifyを採用) $data->setHashPass($hash_pass['hash_pass'] = password_hash($clean['pass_data'], PASSWORD_DEFAULT)); } // Dataクラスのセッターを使用し、DBのバリデーションを実装後、DBに保存 if(empty($data->setErrorMessage($error_message)) ) { $mysqli = new mysqli( DB_HOST, DB_USER, DB_PASS, DB_NAME); if($mysqli->connect_errno ) { echo $data->setErrorMessage('エラー番号 '.$mysqli->connect_errno).PHP_EOL; exit(); }else{ $sql = "INSERT INTO hash (id_data, pass_data) VALUES ( '$data->setClean($clean[id_data])', '$data->setClean($hash_pass[hash_pass])')"; } $res = $mysqli->query($sql); if($res) { echo $data->setSuccessMessage('登録が完了しました。'); }else{ echo $data->setErrorMessage('登録に失敗しました。'); } $mysqli->close(); } } ?> from.php <?php require_once('data_vaildataion.php'); ?> <!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>ハッシュ化しよう</title> </head> <body> <h1>新規登録画面</h1> <div class="input_area"> <form action="db.php" method="post"> <dl class="id"> <dt>ID</dt> <dd><input type="text" name="id_data"></dd> </dl> <dl class="pass"> <dt>PASS</dt> <dd><input type="text" name="pass_data"></dd> </dl> <input type="submit" name="btn_submit" value="新規登録"> </form> </div> </body> </html> hashdb +----+---------+----------------------------------------------------------------+ | id | id_data | pass_data | +----+---------+----------------------------------------------------------------+ | 1 | (hogeID) | ($2y$10$0V2iu9qPDLJ/LOo629jT2OSNWlEHqUzADek23k.Ns.swWZiT3GRxu) | +----+---------+----------------------------------------------------------------+ ※上記のコードで、IDとハッシュ化されたパスワードがDBに保存できます。 参考サイト ・文字列からハッシュ値を取得する
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHPで返却しているJSONが途中で切れるバグを解消した

環境 PHP 7系 JavaScript (Pure) Docker HAProxy 2.2 VSCode Remote Container 小さい Web システムプロジェクトなので、APIを作成するためのライブラリ等は使っていない。 発生した問題 echo json_encode($data); という簡単なコードで、APIを作成していた。 小さいプロジェクトなので、APIを作成するためのライブラリ等は使っていない。 比較的短いJSONを出力すると、APIから返却されたJSONが途中で切れてしまうバグに遭遇した。 {"locale": "ja-JP"} これぐらいだと {"locale": のように切れてしまう。これが {"locale": "ja-JP", "dummy": "なんでなんだろうなああああああああああああ"} のように長いJSONを返すと、切れないで表示される。(JavaScriptが正常にパースできる。) 原因 header('Content-Type: application/json'); echo('{"locale": "ja-JP"}'); このように、echoする前にヘッダを設定する必要があった。ちなみに実際には、JavaScriptのコールバックが必要なJSONPコールだったので、 application/javascript にした。 コメント あまり使ったことのないHAProxyのせいだと思い込み、かつ似たようなIssueが過去に報告されていたのでかなりはまりました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【PHP】Google Ads APIで入札情報を更新したい!

はじめに サンプル使わずAPIでレポートデータを取得していたわけですが 過去記事 運用チームからの今度の要望は、 【Googleに登録している広告グループの入札情報を自サイトから直接更新したい】 というものでした。 ほーそうきたか。 まあいちいち管理画面にログインするのメンドクサイもんね。。 分からんでもないね。 ってなわけで今回は、 これまでどおりサンプルプログラム(Googleが用意してくれてる「クライアントライブラリ」ってやつ)は 使わない前提で(ここまできたら意地でも使いたくない!!) 「更新ってどうすりゃいいの!?」ってお話です。 今回のは基本的に全部マニュアル見れば書いてあったのだけど、 欲しい情報があっちゃこっちゃ飛び散っちゃってたのでまとめたくらいの、 メモ書き程度の内容になります。 何度も繰り返しますが、 公式ではクライアントライブラリを使うことを推奨してますので、 ここでのやり方はあくまでも参考として見てくださいネ! 前提 oAuth2でのAPIアクセスはアクセストークンが必須ですので、 そこが取れなきゃお話になりません。 ということで、上述の過去記事を参考にしてoAuth2認証をします。 リフレッシュトークンとクライアントID、クライアントシークレットから アクセストークンを取得するという作業になります。 アクセストークンを取得できたら、ヘッダーを作成します。 こんなかんじに。 //ヘッダー情報をセット $_header = [ "Content-Type: application/json", "Accept: application/json", "Authorization: Bearer $access_token", "developer-token: $developer_token", "login-customer-id: $login_customer_id", ]; これができたら準備はOK! 更新 レポートデータはHeaderさえセットできればあとはクエリ言語で全部取ってこれたのですが、 マスタ系の更新には必ず「リソース名」が必要になります。 今回は広告グループを更新するので、こんなかんじ。 //クライアントID $clientid = "CLIENT_ID"; //広告グループID:管理画面で確認できます //※追加する場合は[-1]など存在しない値をセット $adgroupid = "ADGROUP_ID"; //リソース名 $_resourcename = "customers/$clientid/adGroups/$adgroupid"; 処理に呼び出すメソッドは【Mutate】。 使い方の詳細はこちら: 公式リファレンス 今回は広告グループの値を更新するので、POSTするURLは $_url = "$_endpoint/$_version/customers/$clientid/adGroups:mutate"; 実際にセットする値は、 operationsの下にcreate/update/removeを指定します。 (removeは試してないからよくわからんけど) 今回は、広告グループの中でも ・名前 ・目標コンバージョン単価 ・目標費用対効果 ・デフォルトの上限クリック単価 ・上限CPM ・目標インプレッション単価 を更新します。 ステータスも変更できます。 正常処理が完了すると、リソース名が返ってきます。 //updateMask【必須】:update対象のカラム名をカンマ区切りで全部指定 $_setting["operations"][0][0]["updateMask"] = "name,target_cpa_micros,target_roas,cpc_bid_micros,cpm_bid_micros,target_cpm_micros"; //リソース名【必須】 $_setting["operations"][0][0]["update"]["resourceName"] = $_resourcename; //広告グループ名 $_setting["operations"][0][0]["update"]["name"] = "広告グループ TEST-1"; //目標コンバージョン単価:NULLで値のリセットが可。リセットした場合、キャンペーンのデフォルト単価が適用される(Google広告の仕様) //microsなので値に×1000000する。セットする際は文字列にしないとエラーになる $_targetcpa = 10000; $_setting["operations"][0][0]["update"]["target_cpa_micros"] = strval($_targetcpa * 1000000); //目標費用対効果:NULLで値のリセットが可。 //指数なので値に÷100する。セットする際は文字列にしないとエラーになる $_targetroas = 200; $_setting["operations"][0][0]["update"]["target_roas"] = strval($_targetroas / 100); //デフォルトの上限クリック単価:NULLや0入力不可。必ず1以上(microsなので正確には1000000以上)を指定する。 //microsなので値に×1000000する。セットする際は文字列にしないとエラーになる $_cpcbid = "100"; $_setting["operations"][0][0]["update"]["cpc_bid_micros"] = strval($_cpcbid * 1000000); //上限CPM:NULLや0入力不可。必ず1以上(microsなので正確には1000000以上)を指定する。 //microsなので値に×1000000する。セットする際は文字列にしないとエラーになる $_cpmbid = "100"; $_setting["operations"][0][0]["update"]["cpm_bid_micros"] = strval($_cpmbid * 1000000); //目標インプレッション単価:NULLや0入力不可。必ず1以上(microsなので正確には1000000以上)を指定する。 //microsなので値に×1000000する。セットする際は文字列にしないとエラーになる $_targetcpm = 100; $_setting["operations"][0][0]["update"]["target_cpm_micros"] = strval($_targetcpm * 1000000); //curl START $_curl = curl_init(); //OPTIONをセット curl_setopt_array($_curl, array( CURLOPT_URL => $_url, CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 120, CURLOPT_HTTPHEADER => $_header, CURLOPT_POSTFIELDS => json_encode($_setting), )); //curl EXEC(文字列で取得) $_resp = curl_exec($_curl); //エラーハンドリング用 $_errno = curl_errno($_curl); //curl END curl_close($_curl); //エラーハンドリング if ($_errno !== CURLE_OK) { //エラー処理 } //エラーでなければjsonを連想配列化 $_result_json = json_decode($_resp, true); $_result = is_array($_result_json["results"]) ? $_result_json["results"] : []; //リソース名が戻ってこれば正常終了 if ($_result[0]["resourceName"] == $_resourcename) { return true; } 数値にどんな値を入れるかは、公式ドキュメントに割と親切に書いてあるので、そちらをよく参照してください。 エラーの場合はエラーコードとメッセージが返ってきます。 こんなかんじに: { "error": { "code": 400, "message": "Request contains an invalid argument.", "status": "INVALID_ARGUMENT", "details": [ { "@type": "type.googleapis.com/google.ads.googleads.v6.errors.GoogleAdsFailure", "errors": [ { "errorCode": { "operationAccessDeniedError": "MUTATE_ACTION_NOT_PERMITTED_FOR_CLIENT" }, "message": "A mutate action is not allowed on this campaign, from this client.", "trigger": { "stringValue": "VIDEO" }, "location": { "fieldPathElements": [ { "fieldName": "operations", "index": 0 } ] } } ] } ] } } ちなみにこれは、更新できない項目をUPDATEしようとしてエラーになったものです。 割と細かくエラー内容を教えてくれる印象でしたね。 おわりに 今回は割とさらっと更新出来ました。少しだけ扱いに慣れてきたのかも。 GoogleAPI難しくて途方に暮れてる方の一助になりますように。。 次はv6から新たに追加された更新履歴の取得に取り掛かりまーす!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravelでのデバッグ方法4パターンまとめ

Laravelのデバッグ方法って何かいっぱいあるよね... なぜこの記事を書こうと思ったか 少しでも開発を効率化する為です。 僕自身のメモ用っていうのもあるんですが、パターンに応じてどのデバッグ方法を使うのがベストかというのが分からないんですよね? その時にどんな選択肢があるかも知っておきたかったので、記事にまとめようと思いました! 間違っているもの、他にもこんな方法があるよ!とかあれば是非教えて頂ければ助かります 環境 ターミナル $ php artisan --version Laravel Framework 5.5.50 $ php -v PHP 7.1.33 (cli) (built: Oct 31 2019 17:37:57) ( NTS ) Copyright (c) 1997-2018 The PHP Group Zend Engine v3.1.0, Copyright (c) 1998-2018 Zend Technologies $ composer -v Composer version 2.0.12 2021-04-01 10:14:59 1. Logファサード Logファサードを使用して、ログに変数の値などを出力するやり方。 簡単でお手軽です。 使用したいControllerなどで、下記をUseに指定します(Blade内でも使えます) use Illuminate\Support\Facades\Log; あとは、Logファサードを使用し // 変数 Log::debug($test); // 配列 Log::debug(print_r($arr, true)); // オブジェクト Log::debug(print_r($object, true)); のように出力します。 useを使用しない場合は、下記のように「\」を先頭につければ指定しなくても出力できます! \Log::debug($test); 出力する際のメソッド(ログレベル)は下記の通り。 Log::emergency($message); Log::alert($message); Log::critical($message); Log::error($message); Log::warning($message); Log::notice($message); Log::info($message); Log::debug($message); 上から順にレベル(緊急度)が高く、下記のように設定ファイル(config/app.php)にレベルを記述しておくと、そのレベルより上のログしか出力されなくなるとのこと。 config/app.php 'log_level' => env('APP_LOG_LEVEL', 'debug'), 以下、公式より引用。 Laravelはデフォルトで全ログレベルをストレージに書き込みます。 しかし、実働環境ではapp.php設定ファイルのlog_levelオプションへ、ログすべき最低の重大さレベルを指定したいことでしょう。 このオプションを一度設定すると、Laravelは指定された重大さ以上の全レベルをログします。 たとえば、log_levelにerrorを設定すると、error、critical、alert、emergencyメッセージがログされます。 開発環境だと、debugだけ使用してログを出力して本番環境はそれ以外で出力するみたいな使い方かな 出力場所は、デフォルトでstorage/log/laravel.logに出力されます。 もし日次でファイルを分けたいなら、config/app.phpに下記のように設定すれば分かれます config/app.php 'log' => 'daily' 2. Tinker Laravelに標準で組み込まれているようなので、特に準備せずに使えるようです! (名前ディズニーのキャラみたいでカワイイ?) ターミナルで、下記コマンドを叩きます。 ターミナル $ php artisan tinker Laravel Framework 5.5.50 bash-4.2# php artisan tinker Psy Shell v0.9.12 (PHP 7.1.33 — cli) by Justin Hileman >>> すると上記のように入力待ちの状態になるので、あとはphpのコマンドを入力すれば実行結果が返ってきます。 ターミナル >>> array ('a' => '1', 'b' => '2', 'c' => '3'); => [ "a" => "1", "b" => "2", "c" => "3", ] 変数に値を格納して、操作することも可能。 ターミナル >>> $hoge = new Carbon\Carbon('now'); => Carbon\Carbon @1618184500 {#4459 date: 2021-04-12 08:41:40.625537 Asia/Tokyo (+09:00), } >>> $hoge->dayOfWeek => 1 >>> $hoge->addDay(); => Carbon\Carbon @1618270900 {#4459 date: 2021-04-13 08:41:40.625537 Asia/Tokyo (+09:00), } 終了するには、 exit ターミナル >>> exit Exit: Goodbye ちょっとphp標準のメソッドの動きを確認したい オブジェクトの中身を確認したい と言った「画面を動かすまでもないけど実行結果を見たい」という場合には有効に使えそう。 個人的には、Carbonの動きとか把握するのにかなりありがたい存在? プロジェクト内で、public static functionを定義していればそれも使えるようです。 ※追記 public static以外のメソッドもNewすれば使えるようです。 コメントで教えて頂いた @nunulk さんありがとうございました >>> $hoge = new \App\Hoge() => App\Hoge {#1000} >>> $hoge->piyo() => "piyo" >> 3. Debugbar こちらはめちゃくちゃ有名なので、導入している方も多いかと思います。 準備 下記コマンドでインストール ターミナル composer require barryvdh/laravel-debugbar .envの下記の値をtrueに設定します(本番環境ではfalseに戻すのを忘れずに) .env DEBUGBAR_ENABLED=true 忘れないように、envの値を反映させます ※追記 このタイミングで私は php artisan config:cacheしていたのですが、開発環境でconfigをキャッシュするのは推奨されないとのことなので、cacheしていない場合は特になにもしなくてOKです! 以下、公式より引用。 一般的には、本番環境へのデプロイ作業の一環として、php artisan config:cacheコマンドを実行すべきでしょう。 アプリケーションの開発期間中は設定が頻繁に変更されることも多いので、ローカルでの開発中にこのコマンドを実行してはいけません。 Note: 開発過程の一環としてconfig:cacheコマンド実行を採用する場合は、必ずenv関数を設定ファイルの中だけで使用してください。 設定ファイルがキャッシュされると、.envファイルはロードされなくなり、env関数の呼び出しは全てnullを返します。 ・config:cacheすると、envファイルはロードされなくなる ・env関数を設定ファイル以外で使っている場合は、nullになってしまう ってことですね。 既にcacheしてしまっている場合は、下記コマンドでクリアします。 ターミナル php artisan config:clear コメントで教えて頂いた @kaya754 さん、ありがとうございました! 準備は以上です。 使い方 ブラウザにアクセスすると、ページの下部にデバッグバーが表示されます。 それぞれタブごとに様々な情報が表示されますが、よく使うタブは下記の通りです。 タブ 内容 Messages 出力したログの確認 Views レンダリングされたViewの一覧 Route ルーティング関係の一覧 Query 裏で走っているSQL Session Sessionの一覧と値 Request Requestの一覧と値 Messagesには、デバッグバーの下記メソッドでログを出力できます。 \Debugbar::emergency('emergency'); \Debugbar::alert('alert'); \Debugbar::critical('critical'); \Debugbar::error('error'); \Debugbar::warning('warning'); \Debugbar::notice('notice'); \Debugbar::info('info'); \Debugbar::debug('debug'); \Debugbar::log('log'); 出力してみるとこんな感じです。 一番上の行にあるように、Logファサードで出力したログもこちらで見れるみたいです? いちいちlaravel.logを見るよりこっちの方が簡単ですね。 Viewsは、実際にシステムを動かして、このページを編集したいという時にViewを特定するのに便利かな! Routeは、ルーティングの確認に便利。 web.phpを見ても良いんですが、大きなシステムだとコードを多すぎて1ページでは情報が把握しきれない事があるんですよね? QueryではSQLが把握できます。 Laravelで開発している時ってSQLがどれだけ走ってるかとか意識しづらいと思うんですが、確認してあげる事でN+1問題等にも気付けるんじゃないかと思います。 SessionやRequestは、コード上だけでは分かりづらい中身が見れるのでめっちゃありがたい。 モデルを返した時に、コレクションで返ってきてる事が分かりますね。 これ以外にもタブは幾つかありますが、僕自身まだあまり使いこなせていないので、もっとこんな事もできるとかあれば教えてほしいです 4.ヘルパーメソッド dump()もしくはdd()を使って、値をブラウザ上に出力する方法です。 2つの違いは、 ・dump()は、処理が止まらずに出力するだけ ・dd()は、記述時点で処理が止まる って感じらしい。 使い方はめちゃ簡単で、引数に出力したい値を渡すだけ。 $test = new Carbon\Carbon('now'); dump($test); この状態でブラウザにアクセスすると、上部にバーが表示されてログが出力されます。 ページを見ながら値を確認できるので、分かりやすいですね? View側でControllerから渡ってきた値を確認したいという事もあるので、Viewで書けないのかな?と思いましたが、Viewでも下記にように書けば使えるようです! <div id="wrapper"> <div class="head-information head-margin-top"> <h2>テストページです</h2> @php $test = new Carbon\Carbon('now'); dump($test); @endphp </div> </div> ただし、Viewで書くと記述した場所に出力されるので、デザインが崩れる可能性はありますw 今度は、Contoller側にてdd()で出力してみます。 public function index() { $test = new Carbon('now'); dd($test); return view('page.mypage.dashboard.test'); } すると、ページが表示されずにログだけページに表示されるのがわかります。 dd()では書いた場所で処理が止まるので、上記のコードではreturn Viewが行なわれてないことが分かります。 View側でdd()を書くとどうなるか... <div id="wrapper"> <div class="head-information head-margin-top"> <h2>テストページです</h2> @php $test = new Carbon\Carbon('now'); dd($test); @endphp </div> <h1>さすがディオ!おれたちにできない事を平然とやってのけるッ そこにシビれる! あこがれるゥ!</h1> </div> 途中で読み込みが終わっているので、ジョジョの名言が出力されていないことが分かりますね( ・∀・)!! divタグも閉じられていない事になっているので、クラス名に対してCSSも適用されていない View側でdd()を使う事はあまりなさそうですが、Viewでエラーになっている箇所の手前で使うという使い方はできそうです。 個人的まとめ 基本は、dump()でログ出力 エラー箇所の手前で処理を止めたい場合は、dd() dump()だとViewのデザインが崩れて困るという場合は、debugbarにログ出力 タスクスケジューラ等、画面を必要としない処理はLogファサード LaravelやPHPのメソッド、自作モデルやメソッドの動きを確認したい場合はTinker 参考 laravel-debugbar Laravel 5.5 Artisanコンソール Laravel 5.5 パッケージ開発 Laravel 5.5 エラーとログ laravelデバッグバーの導入 Laravel 5.5 設定 終わりに 軽く調べた感じは他にもデバッグ方法はありそうでしたが、ひとまずこれだけ知っていれば大抵のパターンで困らないんじゃないかな〜と思う! もっと便利なやり方があれば、使いたい所存?
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む