20210513のPHPに関する記事は18件です。

[AWS_13.2]必須モジュール gd がインストールされていないか、無効化されています。

環境 AWS EC2 t2.micro PHP 8.0.2 WordPress 5.7.2 エラー 原因 phpのアップデートでphpのつく諸々を削除したが、phpを再インストールする際にその諸々は再インストールしていなかった。 解決法 yum -y install mysql httpd php-mbstring php-xml gd php-gd
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Docker X Laravel PHP CS Fixer を導入して、ソースコードを自動整形する

環境 https://github.com/ucan-lab/docker-laravel 最強のLaravel開発環境をDockerを使って構築する 記事執筆時バージョン PHP: 8.0 Laravel: 8.0 php-cs-fixer: 3.0.0 PHP Coding Standards Fixer(php-cs-fixer) リポジトリ名はPHP-CS-Fixer、正式名称はPHP Coding Standards Fixer、コマンド名はphp-cs-fixerとなります。 php-cs-fixer の導入 $ composer require --dev bamarni/composer-bin-plugin $ composer bin tools require friendsofphp/php-cs-fixer .php-cs-fixer.dist.php php-cs-fixerの設定ファイルを追加します。 $ touch .php-cs-fixer.dist.php .php-cs-fixer.dist.php <?php declare(strict_types=1); $finder = PhpCsFixer\Finder::create() ->in([ __DIR__ . '/app', __DIR__ . '/config', __DIR__ . '/database/factories', __DIR__ . '/database/seeders', __DIR__ . '/routes', ]); $config = new PhpCsFixer\Config(); return $config ->setRiskyAllowed(true) ->setRules([ '@PhpCsFixer:risky' => true, 'blank_line_after_opening_tag' => false, 'linebreak_after_opening_tag' => false, 'declare_strict_types' => true, 'phpdoc_types_order' => [ 'null_adjustment' => 'always_last', 'sort_algorithm' => 'none', ], 'no_superfluous_phpdoc_tags' => false, 'global_namespace_import' => [ 'import_classes' => true, 'import_constants' => true, 'import_functions' => true, ], 'php_unit_test_case_static_method_calls' => [ 'call_type' => 'this' ], 'phpdoc_align' => [ 'align' => 'left', ], 'not_operator_with_successor_space' => true, ]) ->setFinder($finder); .gitignore に追加 vendor-bin ディレクトリと .php-cs-fixer.cache ファイルはGit管理は不要なので、 .gitignore に追加します。 /vendor-bin .php-cs-fixer.cache php-cs-fixer 実行 # version $ ./vendor/bin/php-cs-fixer --version PHP CS Fixer 3.0.0 Constitution by Fabien Potencier and Dariusz Ruminski # dry run $ ./vendor/bin/php-cs-fixer fix -v --diff --dry-run # fix $ ./vendor/bin/php-cs-fixer fix -v --diff GitHub Actions でプルリク作成時に自動チェックする $ mkdir -p .github/workflows $ touch .github/workflows/pull-request-php-cs-fixer.yml pull-request-php-cs-fixer.yml name: PHP Coding Standards Fixer on: pull_request: jobs: php-cs-fixer: runs-on: ubuntu-latest defaults: run: working-directory: backend steps: - uses: actions/checkout@v2 - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: '8.0' - name: Prepare run: | wget https://github.com/FriendsOfPHP/PHP-CS-Fixer/releases/download/v3.0.0/php-cs-fixer.phar -O php-cs-fixer chmod a+x php-cs-fixer - name: OS Version run: cat /etc/os-release - name: PHP Version run: php -v - name: PHP CS Fixer Version run: php php-cs-fixer --version - name: PHP CS Fixer Run run: php php-cs-fixer fix --diff -vvv --dry-run 補足: ルールセット GitHubにルールセットがまとめられています。 おすすめルールセットは PhpCsFixer:risky です。 https://github.com/FriendsOfPHP/PHP-CS-Fixer/tree/3.0/doc/ruleSets 補足: php-cs-fixerの細かい設定 PHP-CS-Fixer Configuratorという便利なサービスがあります。 細かい変更を行いたい場合はこちらをご利用下さい。 https://mlocati.github.io/php-cs-fixer-configurator
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

jsからphpにデータを渡してjsonファイルで保存する

jsからサーバーにデータを保存したかった。 XAMPPを導入し、PHPを何となく書けるようになった。 しかし、データベースの使い方がよく分からなかった。 そんな時に無理やり編み出した手法をここに晒す。 save.php <?php $postData = json_decode(file_get_contents("php://input"),true);//jsからjson受け取り $value1 = $postData[0]; $value2 = $postData[1]; echo json_encode("やったあ"); file_put_contents("./data.json", json_encode([$value1, $value2])); ?> script.js async function save(value1, value2){ let req = await fetch("./save.php",{ method: "post", headers: {"Content-Type": "application/json"}, body: JSON.stringify([value1, value2]), }); let res = await req.json(); console.log(res);//"やったあ" } save(0,1);//[0,1]という配列が"data.json"として保存される。 ファイル名がばれれば余裕で外からjsonファイルの中身を覗けるので、大事な情報の保存には向かない。 データベースを使わずに見られても良いデータを保存したいとき向け。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

sprintfで書式を整える

$date = sprintf('%04d年 %02d月 %02d日', 2021, 5, 13); print($date); //%の後の数字(04etc)で表記する桁数を指示している //dは数字の意味で、数字以外が記入されたときにエラーで弾くようになっている。 //※これだけで万全ではないので、注意 //文字を書きたいときは、d→sに変更するとOK
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Laravel】Seederファイルを作成して、ダミーデータを格納する

Seederファイルの作成が初見だったためメモです ファイルの作成 $ php artisan make:seeder 任意のファイル名 作成したファイルに以下のように記述しました。色んなパターンあると思います <?php use App\Models\Company; class CreateCompanySeeder extends Seeder { public function run() { $menu = Company::create([ 'name' => 'hoge-company' ]); } } 作成したファイルを実行するように記述する  /database/seeds/DatabaseSeeder <?php use Illuminate\Database\Seeder; class DatabaseSeeder extends Seeder { /** * Seed the application's database. * * @return void */ public function run() { $this->call(CreateCompanySeeder::class); } } 実行 $ php artisan db:seed クラスを指定しても実行できる $ php artisan db:seed --class=CreateCompanySeeder
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

メンタル疾患症状管理、服薬管理Webシステム(書き込み結果、ファイル出力編)

メンタル疾患病状管理、服薬管理Webシステム(書き込み結果、ファイル出力編)のソースコードを公開いたします。 ファイル書き込み(result.php)のソースコードです。 <!-- result.php --> <!-- メンタル疾患、服薬管理の表示プログラム --> <!-- メンタル疾患、服薬管理システム --> <!-- 新規作成 2021/5/12 --> <!-- 作成者:乃木坂好きのITエンジニア --> <?php $message = 'OK'; $year = htmlspecialchars($_REQUEST['year']); $month = htmlspecialchars($_REQUEST['month']); $day = htmlspecialchars($_REQUEST['day']); $sleep = htmlspecialchars($_REQUEST['sleep']); $mental = htmlspecialchars($_REQUEST['mental']); $morning = htmlspecialchars($_REQUEST['morning']); $evening = htmlspecialchars($_REQUEST['evening']); $night = htmlspecialchars($_REQUEST['night']); $iraira = htmlspecialchars($_REQUEST['iraira']); $head_pain = htmlspecialchars($_REQUEST['head_pain']); $offence = htmlspecialchars($_REQUEST['offence']); $die = htmlspecialchars($_REQUEST['die']); $OD = htmlspecialchars($_REQUEST['OD']); $nothing = htmlspecialchars($_REQUEST['nothing']); $panik = htmlspecialchars($_REQUEST['panic']); $kanashibari = htmlspecialchars($_REQUEST['kanashibari']); $content = htmlspecialchars($_REQUEST['content']); $line = $year . $month . $day. "\n". "睡眠度:" . $sleep . "\n" . "気分の落ち込み度" . $mental . "\n" . "投薬管理: " . $morning . " " . $evening. " " . $night ."\n" . "あてはまる主な症状: " .$iraira . " " . $head_pain . " ". $offence . " " .$die . " " . $OD . " " .$nothing . " " .$panik . " " .$kanashibari. "\n" . "症状の詳細:" . $content . "\n" . PHP_EOL; file_put_contents(__DIR__ . '/articles.txt', $line, FILE_APPEND | LOCK_EX); require_once 'views/result.tpl.php'; 書き込み結果を表示するソースコードです。(result.tpl.php) <!-- result.tpl.php --> <!-- 結果表示ののテンプレートプログラム --> <!-- メンタル疾患、服薬管理システム --> <!-- 新規作成 2021/5/12 --> <!-- 作成者:乃木坂好きのITエンジニア --> <!DOCTYPE html> <html lang='ja'> <?php include('header.inc.php'); ?> <body> <h1>書き込みました</h1> <p><?= $message ?></p> <p> <?php if(isset($year)) { echo $year . ', '; } if(isset($month)) { echo $month . ', '; } if(isset($day)) { echo $day . ', '; } if(isset($sleep)) { echo $sleep . ', '; } if(isset($mental)) { echo $mental; } if(isset($morning)) { echo $morning; } if(isset($evening)) { echo $evening; } if(isset($night)) { echo $night; } if(isset($iraira)) { echo $iraira; } if(isset($head_pain)) { echo $head_pain; } if(isset($offence)) { echo $head_pain; } if(isset($die)) { echo $die; } if(isset($OD)) { echo $die; } if(isset($nothing)) { echo $nothing; } if(isset($panic)) { echo $nothing; } if(isset($kanashibari)) { echo $kanashibari; } if(isset($content)) { echo $content; } ?> </p> <form action='mental.php' method='get'> <button type='submit' id="submit">戻る</button> </form> <?php include('footer.inc.php'); ?> </body> </html>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

メンタル疾患症状管理、服薬管理Webシステム(画面入力編)

メンタル疾患症状管理、服薬管理Webシステム(画面入力編)のソースコードを公開いたします。 メインとなるmental.phpのソースコードです。 <!-- mental.php --> <!-- ボディー部分のプログラム --> <!-- メンタル疾患、服薬管理システム --> <!-- 新規作成 2021/5/12 --> <!-- 作成者:乃木坂好きのITエンジニア --> <?php $message = 'メンタル疾患、投薬管理システム'; $lines = file(__DIR__ . '/articles.txt', FILE_IGNORE_NEW_LINES); require_once 'views/mental.tpl.php'; ヘッダー部分の部分のテンプレートソースコードです。 <!-- header.inc.php --> <!-- ヘッダー部分のテンプレートプログラム --> <!-- メンタル疾患、投薬管理システム --> <!-- 新規作成 2021/5/12 --> <!-- 作成者:乃木坂好きのITエンジニア --> <head> <meta charset='utf-8'> <title>メンタルチェックシステム</title> <style> body { background-color:bisque; padding: 10px; } p.header { font-size:20px; color:crimson; } h1 { font-size: 40px; color:blueviolet; } h2 { font-size: 20px; color:blue; } #submit { background-color:darkgreen; border: 1px solid aqua; padding 15px 90px; border-radius: 10px; font-size:15px; color: #fff; } #submit:hover { background-color:darkblue; } a{ display:inline-block; padding:10px 20px 10px 20px; color:white; background-color:green; font-size:18px; font-weight: bold; border:solid 3px pink; border-radius:8px; } a:hover { background-color:darkcyan; } .nogizaka{ font-size:8px; color:red; } </style> </head> ボディー部分のテンプレートソースコードです <!-- mental_tpl.php --> <!-- ボディー部分のテンプレートプログラム --> <!-- メンタルチェックシステム --> <!-- 新規作成 2021/5/12 --> <!-- 作成者:乃木坂好きのITエンジニア --> <!DOCTYPE html> <html lang='ja'> <?php include('header.inc.php'); ?> <script type="text/javascript"> <!-- function check(){ //変数の定義 const content = document.getElementById('content'); const submit = document.getElementById('submit'); if(content.value.replace(/\s+/, '').length === 0 ){ window.alert('詳細が入力されていません。'); return false; } else { if(window.confirm('送信してよろしいですか?')){ // 確認ダイアログを表示 return true; } else{ // 「キャンセル」時の処理 window.alert('キャンセルされました'); // 警告ダイアログを表示 return false; // 送信を中止 } } } // --> </script> <body> <h1>メンタル疾患、投薬管理</h1> <p class="header"><?= $message ?></p> <form action='result.php' method='post' onSubmit="return check()"> <dl> <label for='year'>年</label> <select name="year"> <option value="2021年">2021年</option> <option value="2022年">2022年</option> <option value="2023年">2023年</option> <option value="2024年">2024年</option> <option value="2025年">2025年</option> </select> <p></p> <label for='month'>月</label> <select name="month"> <option value="1月">1月</option> <option value="2月">2月</option> <option value="3月">3月</option> <option value="4月">4月</option> <option value="5月">5月</option> <option value="6月">6月</option> <option value="7月">7月</option> <option value="8月">8月</option> <option value="9月">9月</option> <option value="10月">10月</option> <option value="11月">11月</option> <option value="12月">12月</option> </select> <p></p> <label for='day'>日</label> <select name="day"> <option value="1日">1日</option> <option value="2日">2日</option> <option value="3日">3日</option> <option value="4日">4日</option> <option value="5日">5日</option> <option value="6日">6日</option> <option value="7日">7日</option> <option value="8日">8日</option> <option value="9日">9日</option> <option value="10日">10日</option> <option value="11日">11日</option> <option value="12日">12日</option> <option value="13日">13日</option> <option value="14日">14日</option> <option value="15日">15日</option> <option value="16日">16日</option> <option value="17日">17日</option> <option value="18日">18日</option> <option value="19日">19日</option> <option value="20日">20日</option> <option value="21日">21日</option> <option value="22日">22日</option> <option value="23日">23日</option> <option value="24日">24日</option> <option value="25日">25日</option> <option value="26日">26日</option> <option value="27日">27日</option> <option value="28日">28日</option> <option value="29日">29日</option> <option value="30日">30日</option> <option value="31日">31日</option> </select> <p></p> <dd>睡眠度を選んでください。 <select name="sleep"> <option value="よく眠れた">よく眠れた</option> <option value="眠れた">眠れた</option> <option value="普通">普通</option> <option value="あまり眠れなかった">あまり眠れなかった</option> <option value="全く眠れなかった">全く眠れなかった</option> </select></dd> <p></p> <dd>気分の落ち込み度 <select name="mental"> <option value="大きい"> 大きい <option value="やや大きい"> やや大きい <option value="普通"> 普通 <option value="やや小さい"> やや小さい <option value="小さい"> 小さい </select> </dd> <p></p> <dd>服薬管理 <input type="checkbox" name="morning" id="morning" value="朝食後">朝食後 <input type="checkbox" name="evening" id="evening" value="夕食後">夕方後 <input type="checkbox" name="night" id="night" value="寝る前">寝る前 </dd> <p></p> <dd>あてはまる主な症状をチェックしてください <br> <input type="checkbox" name="iraira" id ="iraira" value="イライラしている">イライラしている <input type="checkbox" name="head_pain" id="head_pain" value="頭痛がする">頭痛がする <input type="checkbox" name="offence" id="offence" value="攻撃的">攻撃的 <input type="checkbox" name="die" id="die" value="自殺願望">自殺願望 <input type="checkbox" name="OD" id="OD" value="大量に薬を飲みたい">OD <input type="checkbox" name="nothing" id="nothing" value="何もする気がない">何もする気がない <input type="checkbox" name="panik" id="panic" value="パニック状態">パニック状態 <input type="checkbox" name="kanashibari" id="kanashibari" value="金縛りにあった">金縛りにあった <br> </dd> <p></p> <dd>今日の様子を詳しく書いてください</dd> <dd><textarea name="content" id="content" rows="5" cols="100" ></textarea></dd> <p></p> </dl> <input type="submit" value="button" id="submit" onMouseOver="changeColor()" onMouseOut="revertColor()"> <script> function changeColor(){ document.getElementById('submit').style.backgroundColor = 'yellow'; } function revertColor(){ document.getElementById('submit').style.backgroundColor = null; } </script> <h2>投稿一覧</h2> <?php foreach ($lines as $line) { ?> <p><?= $line ?></p> <?php } ?> <?php include('footer.inc.php'); ?> <br> <a href="../index.html" id="menu">メニュー画面に戻る</a> フッターのソースコードです。 <!-- footer.tpl.php --> <!-- フッター部分のテンプレートプログラム --> <!-- メンタル疾患、服薬管理システム --> <!-- 新規作成 2021/5/12 --> <!-- 作成者:乃木坂好きのITエンジニア --> <hr> <footer class="nogizaka">by 乃木坂好きのITエンジニア</footer>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【php】複数のデータセットを入力画面から作成する方法

<?php while ($data = trim(fgets(STDIN))) { $list[] = $data; } var_dump($list); ?> 入力 9 1 8 2 4 1 5 9 4 6 8 2 4 6 3 2 出力 array(4) { [0]=> string(7) "9 1 8 2" [1]=> string(7) "4 1 5 9" [2]=> string(7) "4 6 8 2" [3]=> string(7) "4 6 3 2" }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Laravel8 laravel/ui】既存のusersテーブルからお好みのテーブルに変更する方法を分かりやすく素早く解説してみた

①usersモデルの複製 マイグレーションで作成しても大丈夫ですが、こっちの方が簡単だと思うので簡単な方を説明します。Custom.phpは適当に付けた名称なので、ファイル名は好きに決めてもらって大丈夫です。 パス:~/app/Models/ cp User.php Custom.php ②Custom.phpの編集 クラス名を変更するだけです class User extends Authenticatable ↓ class Custom extends Authenticatable ③~/config/auth.phpの編集 providers => users内のUser::classを先程作成したファイル名と同じくCustom::classに変更して下さい。 /* |-------------------------------------------------------------------------- | User Providers |-------------------------------------------------------------------------- | | All authentication drivers have a user provider. This defines how the | users are actually retrieved out of your database or other storage | mechanisms used by this application to persist your user's data. | | If you have multiple user tables or models you may configure multiple | sources which represent each model / table. These sources may then | be assigned to any extra authentication guards you have defined. | | Supported: "database", "eloquent" | */ 'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\Models\User::class, ], // 'users' => [ // 'driver' => 'database', // 'table' => 'users', // ], ], /* ↓ /* |-------------------------------------------------------------------------- | User Providers |-------------------------------------------------------------------------- | | All authentication drivers have a user provider. This defines how the | users are actually retrieved out of your database or other storage | mechanisms used by this application to persist your user's data. | | If you have multiple user tables or models you may configure multiple | sources which represent each model / table. These sources may then | be assigned to any extra authentication guards you have defined. | | Supported: "database", "eloquent" | */ 'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\Models\Custom::class, ], // 'users' => [ // 'driver' => 'database', // 'table' => 'users', // ], ], /* ④~/app/Http/Controllers/Auth/RegisterController.phpの編集 use App\Models\User; ↓ ①で複製したファイルの名前に変更してください use App\Models\Custom; protected function create(array $data) { //ここを変更する return User::create([ 'name' => $data['name'], 'email' => $data['email'], 'password' => Hash::make($data['password']), ]); } ↓ protected function create(array $data) { //ここを変更する return Custom::create([ 'name' => $data['name'], 'email' => $data['email'], 'password' => Hash::make($data['password']), ]); } protected function validator(array $data) { return Validator::make($data, [ 'name' => ['required', 'string', 'max:255'], 'email' => ['required', 'string', 'email', 'max:255', 'unique:users'], //←を変更する 'password' => ['required', 'string', 'min:8', 'confirmed'], ]); } ↓ protected function validator(array $data) { return Validator::make($data, [ 'name' => ['required', 'string', 'max:255'], 'email' => ['required', 'string', 'email', 'max:255', 'unique:テーブル名'], //←を変更する 'password' => ['required', 'string', 'min:8', 'confirmed'], ]); } ⑤ 終わりです 素早く且つ分かりやすく解説出来たでしょうか...
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CakePHP で mPDF を使う

こちらの記事と同様のことを Ubuntu 21.04 で行いました。 CakePHP 4 に mPDF 8 を導入してテンプレートから PDF を生成 プロジェクトの作成 composer create-project --prefer-dist cakephp/app:4.2.* sample-project サーバーの起動 cd sample-project/ bin/cake server 起動の様子 $ bin/cake server Welcome to CakePHP v4.2.6 Console ------------------------------------------------------------------------------- App : src Path: /home/uchida/lang/php/cake/sample-project/src/ DocumentRoot: /home/uchida/lang/php/cake/sample-project/webroot Ini Path: ------------------------------------------------------------------------------- built-in server is running in http://localhost:8765/ You can exit with `CTRL-C` [Thu May 13 17:14:26 2021] PHP 7.4.16 Development Server (http://localhost:8765) started http://localhost:8765 にアクセス mPDF のインストール composer require mpdf/mpdf TakaoMincho.ttf のシンボリックリンクを作成 mkdir data mkdir data/font cd data/font ln -s /usr/share/fonts/truetype/takao-mincho/TakaoMincho.ttf . PDF を出力するプログラム src/Controller/SampleController.php <?php declare(strict_types=1); namespace App\Controller; use Mpdf\Mpdf; class SampleController extends AppController { public function index() { $mpdf = new Mpdf([ 'fontDir' => [ROOT . DS . 'data' . DS . 'font'], 'fontdata' => [ 'takao' => ['R' => 'TakaoMincho.ttf'], ], 'default_font' => 'ipa', ]); $html = '<h1>こんにちは、世界!</h1>'; $html .= '<blockquote>'; $html .= 'May/13/2021 PM 17:03<br />'; $html .= '</blockquote>'; $mpdf->WriteHTML($html); $encodedName = rawurlencode('sample001.pdf'); return $this->response->withType('pdf') ->withHeader('Content-Disposition', "attachment;filename*=UTF-8''{$encodedName}") ->withStringBody($mpdf->Output('', 'S')); } } templates/Sample/my_pdf.php <html> <head> <?= $this->Html->css(['sample/my_pdf.css']) ?> </head> <body> <h1><?= $title ?></h1> <p>Sample</p> <p>サンプル用のPDFです</p> </body> webroot/css/sample/my_pdf.css h1 { color: #f00; } サーバーを起動して、 http://localhost:8765/Sample にアクセスする 次の環境で確認しました。 $ php -v PHP 7.4.16 (cli) (built: Mar 23 2021 16:15:03) ( NTS ) Copyright (c) The PHP Group Zend Engine v3.4.0, Copyright (c) Zend Technologies with Zend OPcache v7.4.16, Copyright (c), by Zend Technologies $ composer --version Composer version 2.0.9 2021-01-27 16:09:27
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

自分が書いたQiita記事まとめ

はじめに 私はプログラミング歴1年の初心者です。 実務でWebサイトのコーディングを1年間行ってきました。 そろそろシステム開発もできるようになりたいということで LaravelやReactをこれから勉強していこうと思っております。 この記事の目的 この記事をエントリーポイントにしようと思います。 自分が書いた記事をまとめておく記事です。 目次 HTML/CSS関係(初心者) Ruby関係(初心者) PHP関係(1年目以降〜) Python関係(1年目以降〜) JavaScript関係(1年目以降〜) リンク集 HTML/CSS関係(初心者) Ruby関係(初心者) Railsアプリ作成の記事(プログラミング学習を始めてから1ヶ月くらい?) PHP関係(1年目以降〜) Laravelの記事(就職後に勉強し始めたのである程度わかってきたくらい?) Python関係(1年目以降〜) Pythonの記事 Djangoの記事 JavaScript関係(1年目以降〜) パッケージ関係(1年目以降〜) Homebrewの記事 Composerの記事
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ajax非同期通信でPHPへ一括POST、結果を受取る(備忘録)

本業ではなく、欲しいと思ったツールを時折作っているので、忘れていることが多い・・・ 今回はajaxでの非同期通信 やりたいことは  ①ページ内の要素を一括してrecieve.phpへ送信  ②recieve.phpで(DB検索など)処理して結果(件数など)を返す  ③結果を表示 ajax_post.html <html> <head> <script type="text/javascript" src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <script type="text/javaScript"><!-- function res_num(){ var $form = $('#form1'); var data = $form.serialize(); //ajax通信 $.ajax({ type: "post", url: "recieve.php", data: data , success: function(res) { // 成功時の処理 document.getElementById('res').value = res; } }); } //--></script> </head> <body> <form name='form1' id='form1' method='POST' action='hoge.php'> 対象日:<input type='date' name='b_date' id='base_date' value='2021-05-13'><br> 単 価:<input type='text' name='tanka' id='cb_tanka' value='1234'><br> <input type='button' onclick='res_num();' value='検索'><br> 結 果:<input name='res' id='res' value=''> </form></body></html> recieve.php <?php $b_date = $_POST['b_date']; $tanka = $_POST['tanka']; //普段のように受け取れるので、処理を書く //例えばDB問い合わせて、結果件数を$resに入れる echo $res; ?> こんだけ でも忘れちゃうのよね(T.T)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

XAMPP環境からMAMP環境に移す

ローカル環境の整理 自分の備忘録代わりに投稿します。XAMPPのMySQLの調子が悪かったので試しにMAMPの環境でやってみました。 具体的にはXAMPP環境のフォルダを別ファイルに移し、アンインストール。そしてMAMP環境にて再度プロダクトをローカル環境にて動かす事を目標に設定しました。 ファイルが読み込めない… 早速MAMPのアクセスファイルを動かしてlocalhostで開いてみると Warning: Unknown: failed to open stream: No such file or directory in Unknown on line 0 早速エラーが、、、そもそも開くことが出来なかった…。エラー分を読んでみると、ファイルが開けないとのこと。理由を調べてみたら、ファイルをドキュメントファイル下で開いていたため日本語名で読み込めなくなったことが発覚。やっぱり全部英語で書かなきゃだめなんですね。 ファイルをCドライブ直下に移して再度挑戦。 なぜかまだ開けない。index.phpにアクセスしようとしてもロード時間が延々と続きタイム合うとしてしまう。理由を調べてみると、データベースにアクセス出来ないとこういう症状が出るらしい。 このとき私は気づきました。XAMPPをアンストした際にMySQLも消してしまった事を。そして今はMAMP環境下のMySQLを動かしていることを、、、 仕方ないのでMAMPのPHPMyAdminでテーブルを再度作り直すことに。幸いにもテーブルは3つとそこまで多くもなく複雑でもないのでコードや本番環境のデータベースを見ながら再度設計。 データベースが読み込めない ここまででなんとか元の形に近づいて来たけどまだ開けない。しっかりとユーザーとパスワードも再設定し、コードを修正。だがまだ開けない。 $dbh = new PDO('mysql:dbname=kuchikomi;host=localhost:8888;' どうやらこの辺りが怪しいと睨む。 ということでMAMPのサイトを見てみることにする。するとホーム画面に以下のような記述が。 ふむふむつまりportを8888から8889に変えれば行けるってことか? $dbh = new PDO('mysql:dbname=kuchikomi;host=localhost:8889;' ということで上記の様にコードを変更。すると、、、 無事アクセス出来ました! 機能のエラー ファイルを読み込めたのでデータベースとも接続出来たけどデータベースの追加時にエラーが起こったので修正していく。 SQLSTATE[42S22]: Column not found: 1054 Unknown column 'review_date' in 'field list' 口コミを投稿しようとしたらこんなエラーが。。。 読んでみるとreview_dateのカラムが見つからないらしい。 そんなバカなと思いながらコードを見ても特に問題点は見つからない。それならばとMySQLにアクセスしてカラムを見てみると、、、 原因分かりました。はい。「,」<- こいつの所為でした。 こいつを修正してリロードしてみたら出来ました。 なんとかこれでローカル環境で問題なく動かすことに成功、、、 長い道のりだった。 まとめ 少し作業が面倒であったがちゃんと事前の準備をすればXAMPP環境からMAMP環境に移し替えることは可能、おそらくエクスポート機能だったりを上手く活用すればもっと早くできると思います。 また、この方法が良くない方法であったり、なにか間違いがあれば遠慮なく教えていただけると幸いです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHPオリジナル問題作成1

前回、Javaでオリジナル問題を作成してきました。 Javaオリジナル問題作成1(Java入門編:スッキリわかるJava Javaオリジナル問題作成2(Java入門編:スッキリわかるJava Javaオリジナル問題作成3(Java入門編:スッキリわかるJava Javaオリジナル問題作成4(Java入門編:スッキリわかるJava 今回はPHP版のオリジナル問題を作成していこうと思います。 内容は上記のJavaオリジナル問題とほぼ同じです。 ■開発環境 ・VScode ・XAMPP 対象 ・PHPの基礎がわかる人 ・PHPを復習したい人 ・PHPの問題を解きたい人 ■階層 ■実行 URLはmain部分を変更して実行していってください。 変数 ■問題1 int型の変数宣言し、11の値を挿入して下さい。 作成した変数の中身を表示して下さい。 解答 main.php //問題1 <?php $i = 11; echo $i; //実行結果 11 条件分岐と繰り返し、配列 ■問題1 for文を使って1から10を表示して下さい。 ただし、3は表示させないで下さい。 ■問題2 配列の要素5つ(1,2,3,4,5)作成して下さい。 拡張for文を使って配列の各要素の値を順番に取り出して下さい。 ■問題3 変数に「晴れ」を代入してください。 晴れだった場合は〇を表示、それ以外は✖を表示になるようにしてください。 実行し、今回は「〇」が表示されればOKです。 解答 main2.php //問題1 <?php for ($i = 0; $i < 10; $i++) { if ($i === (3 - 1)) { continue; } echo $i + 1; echo '<br>'; } //実行結果 1 2 4 5 6 7 8 9 10 main3.php //問題2 <?php $array = [1, 2, 3, 4, 5]; foreach ($array as $a) { echo $a; echo "<br>"; } //実行結果 1 2 3 4 5 main4.php //問題3 <?php $h = "晴れ"; if ($h == "晴れ") { echo "〇"; } else { echo "✖"; } //実行結果 〇 メソッド、複数クラスを用いた開発 ■問題1 メソッド名:total 戻り値:int 引数リスト:$i ,$j 処理内容:iとjを足した結果を戻す メソッドを呼び出し、処理内容の結果を表示して下さい。 ※メソッドを呼び出す際の引数(実引数)は10と20 ■問題2 配列の要素5つ(172,149,152,191,155)作成して下さい。 sortメソッドを用いて並び替えをして下さい。 配列の要素を表示してください。 ■問題3 otherフォルダにTest.php作成(メソッドを作成し、helloを表示) otherフォルダにTest1.php作成(メソッドを作成し、hello1を表示) main7.phpでTest.phpとTest1.phpのメソッドを呼び出す。 解答 main5.php //問題1 <?php function total($i, $j) { $total = $i + $j; return $total; } $to = total(10, 20); echo $to; //実行結果 30 main6.php //問題2 <?php $array = [172, 149, 152, 191, 155]; sort($array); foreach ($array as $a) { echo $a; echo "<br>"; } //実行結果 149 152 155 172 191 main7.php //問題3 <?php namespace mondai\main; use mondai\other\test; use mondai\other\test1; require 'other/Test.php'; require 'other/Test1.php'; test\h(); test1\h(); //実行結果 hello hello1 Test.php <?php namespace mondai\other\test; function h() { echo "hello"; echo "<br>"; } Test1.php <?php namespace mondai\other\test1; function h() { echo "hello1"; }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHPバージョン8→7.4

プロジェクトの都合でダウングレードしました。 現在のバージョンを調べる コンソール php -v バージョンが8になってました。 インストール済みの PHP バージョンを確認 コンソール brew search php HomebrewでインストールできるPHP7系を検索 コンソール brew search php@7 7.4がインストールされてなかったのでインストールしました。 コンソール brew install php@7.4 PHPのPATHを通す コンソール echo 'export PATH="/usr/local/opt/php@7.4/bin:$PATH"'>>~/.zshrc MacOSによってbashかzshか違うみたいなので、Bashの人は .bashrcとか触ってください。 phpを起動 コンソール brew services start php ここで一回ターミナルを閉じて、再度起動 コンソール php -v PHP7.4になった! 参考にしました https://mykii.blog/what-is-shell-bash-and-zsh/ https://qiita.com/takutoki/items/021b804b9957fe65e093
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【PHP】GoogleAPIで操作履歴を取りたい!

はじめに 運用担当者から連絡があり、 「入札とかいろんな変更履歴をAPIから自動で取りたい」 とのご要望をいただきました。 履歴とな!!? と思わず管理画面チェックしました。 そうか、あいつか。。 Google広告の管理画面の左にヒッソリと、 そう実にヒッソリといるあいつですね。。 なるほど操作を一つ一つ記録してくれているなんて、さすが。 画面からは2年前の変更履歴まで確認できるらしいです。 Googleのドキュメントはこちら 変更履歴取得リソースChangeEvent GoogleAPIのversion6.0.0より、 変更履歴の情報をAPIで取得できるようになりました。 リソース名はChangeEventです。 詳細はリリースノート参照 むしろ割と最近までAPIでは履歴取れなかったんだなあ。 まあどうしても必要な情報ってわけではないから、あとまわしにされてたのかな? ということで 出来たてほやほや(ってほどでももうないけど)の ChangeEventを使ってみることにする。。 前提 まずはおなじみのoAuth2認証。 認証に関しては、過去記事参照のこと。 【PHP】Google Ads APIをサンプルプログラム無しで使いたい!! リフレッシュトークンとクライアントID、クライアントシークレットを使ってoAuth2認証を行い、 アクセストークンを取るところまで。 アクセストークンが取れたら、ヘッダーに認証情報をセットします。 //ヘッダー情報をセット $_header = [ "Content-Type: application/json", "Accept: application/json", "Authorization: Bearer $access_token", "developer-token: $developer_token", "login-customer-id: $login_customer_id", ]; 準備おーけー。 クエリ言語でデータ取得 ChangeEventはレポートと同じようにreadonlyのリソースで、 Googleクエリ言語でアクセスすれば簡単に取れます。 クエリ言語はSQLに似たAPI照会方法で、 「SELECT~」の構文を作成して、 APIにgoogleAds:searchでアクセスします。 GoogleAPIではgetというメソッドも一応あるけど、 デバッグとテスト用にあるだけで推奨されていなくて、 参照だけであれば基本searchか SearchStreamを使うように記載があります。 (SearchStreamは使ったことない) クエリ言語に関してはGoogleさんがドキュメントもたくさん用意してくれているし、 クエリビルダーって機能でデモ的に構文まで全部作れちゃうから、 使い慣れるととても便利! SQLみたいにテーブルとテーブルをJOINしたりはできなくて、 1リソースに1アクセスしなければいけないので注意。 ただし、一つのリソースしか指定していなくても API内部で紐付いていて、値が取れるものもあります。 change_eventであれば、 *ad_group *campaign *customer *feed *feed_item のリソースは取れます。 どのリソースが取れるかはそれぞれ違うので、 使いたいもののドキュメントを参照しましょう。 私はいつも英語との格闘になる・・・ 今回はChangeEventの全項目を取得するためのクエリを作成します。 クエリでは、リソース名「ChangeEvent」ではなく、「change_event」と指定します。 リソースによってWHERE条件文やLIMITなど必須項目が異なります。 change_eventの場合は、 *WHEREに期間を指定すること(履歴は過去30日分しか取れないので、その有効値) *LIMITで上限件数を指定すること の2つが必須条件らしい。 $_query_str = " SELECT campaign.id ,campaign.name ,campaign.bidding_strategy_type ,ad_group.id ,ad_group.name ,change_event.resource_name ,change_event.change_date_time ,change_event.change_resource_type ,change_event.change_resource_name ,change_event.client_type ,change_event.user_email ,change_event.old_resource ,change_event.new_resource ,change_event.resource_change_operation ,change_event.changed_fields ,change_event.campaign ,change_event.ad_group ,change_event.feed ,change_event.feed_item FROM change_event WHERE change_event.change_date_time >= '2021-05-01 00:00:00' AND change_event.change_date_time <= '2021-05-10 23:59:59' LIMIT 10000 "; //クエリをセット $_query = ["query" => $_query_str]; //URLをセット //※versionやcustomeridは環境に合わせてセットすること 2021/5現在の最新versionはv7 $_url = "https://googleads.googleapis.com/v7/customers/$customerid/googleAds:search"; //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($_query), )); //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"] : []; //履歴情報を整理 foreach ($_result as $_idx => $_lineval) { if (!is_array($_lineval)) continue; //キャンペーン情報 $_campid = $_lineval["campaign"]["id"]; $_campname = $_lineval["campaign"]["name"]; //広告グループ情報 $_adgroupid = $_lineval["adGroup"]["id"]; $_adgroupname = $_lineval["adGroup"]["name"]; //履歴情報 $_resourcename = $_lineval["changeEvent"]["resourceName"]; $_changedt = $_lineval["changeEvent"]["changeDateTime"]; $_changertype = $_lineval["changeEvent"]["changeResourceType"]; //AD/AD_GROUP/AD_GROUP_AD/CAMPAIGN/CAMPAIGN_BUDGETなど $_changername = $_lineval["changeEvent"]["changeResourceName"]; $_clienttype = $_lineval["changeEvent"]["clientType"]; //画面かAPIか自動ルールかなど $_useremail = $_lineval["changeEvent"]["userEmail"]; $_oldresource = $_lineval["changeEvent"]["oldResource"]; //旧リソース $_newresource = $_lineval["changeEvent"]["newResource"]; //新リソース $_rchangeop = $_lineval["changeEvent"]["resourceChangeOperation"]; //CREATE/UPDATE/REMOVE $_changefields = $_lineval["changeEvent"]["changedFields"]; //変更対象フィールド } 1つのキャンペーンまたは広告グループごと、操作(登録・更新・削除)ごとにデータが来るようです。 1つの広告グループで複数の項目を更新した場合、1レコードで来ることになります。 ここまでは今まで通りというか割と簡単だなあと思っていたのだけど、 実際のデータを確認してみると想像していたよりかなり複雑だと感じたので、 以下の項目でまとめようと思いました。 リリースされてそれほど経ってないので、おそらく不具合もちらほらあるような。。 履歴データの分析 たとえば広告グループAの単価設定を「目標コンバージョン単価:1000円」と設定した場合、 APIから来るデータはこんなかんじ。 (名称やコードは適当、実際は対応した値が入ります) ["campid"]=> "1234567890" ["campname"]=> "テストキャンペーン" ["adgroupid"]=> "9999999999" ["adgroupname"]=> "広告グループA" ["resourceName"]=> "customers/123456789/changeEvents/11111111111111111~0~0" ["changeDateTime"]=> "2021-05-12 20:00:46.462725" ["changeResourceType"]=> "AD_GROUP" ["changeResourceName"]=> "customers/123456789/adGroups/9999999999" ["clientType"]=> "GOOGLE_ADS_AUTOMATED_RULE" ["userEmail"]=> "testtesttest@test.com" ["oldResource"]=> {["adGroup"]=> {["targetCpaMicros"]=> "1400000000"}} ["newResource"]=> {["adGroup"]=> {["targetCpaMicros"]=> "1000000000"}} ["resourceChangeOperation"]=> "UPDATE" ["changedFields"]=> "targetCpaMicros" changeResourceTypeに属するchangedFieldsを更新しました、という情報です。 上の例だとAD_GROUPの中にあるtargetCpaMicrosという項目が対象。 Googleのドキュメントでad_groupを調べてみるとtarget_cpa_microsというやつがちゃんといますね。。 このときの変更履歴は、 oldResourceとnewResourceの中に、changeResourceTypeに対応するリソース名⇒changedFieldsの構造で入ってます。 oldResource["adGroup"]["targetCpaMicros"] = "1400000000" newResource["adGroup"]["targetCpaMicros"] = "1000000000" ※Microsで来るので÷1000000したのが変更値 つまりこの履歴だと、 Googleの自動ルールが目標コンバージョン単価を1400円⇒1000円に変更しました。 って感じで内容が分かるのです。 メンドクサイのはここから。 changedFieldsには、複数項目が来る場合があります。 前述のように、1つのキャンペーンや広告グループに対して複数の更新を行った場合の履歴は、 以下のようにな感じにデータが来ます。 例えば広告グループのキーワードを追加した場合。 ["campid"]=> "1234567890" ["campname"]=> "テストキャンペーン" ["adgroupid"]=> "9999999999" ["adgroupname"]=> "広告グループA" ["resourceName"]=> "customers/123456789/changeEvents/1616161616161616~0~1" ["changeDateTime"]=> "2021-05-11 18:01:05.247115" ["changeResourceType"]=> "AD_GROUP_CRITERION" ["changeResourceName"]=> "customers/123456789/adGroupCriteria/111111111111~333333333333" ["clientType"]=> "GOOGLE_ADS_WEB_CLIENT" ["userEmail"]=> "testtesttest@test.com" ["oldResource"]=> {["adGroupCriterion"]=> { }} ["newResource"]=> {["adGroupCriterion"]=> {  ["resourceName"]=> "customers/123456789/adGroupCriteria/111111111111~333333333333"  ["keyword"]=> { ["matchType"]=> "BROAD" ["text"]=> "テストキーワード"}  ["criterionId"]=> "333333333333"  ["adGroup"]=> "customers/123456789/adGroups/9999999999"  ["negative"]=> bool(false) }} ["resourceChangeOperation"]=> "CREATE" ["changedFields"]=> "adGroup,criterionId,keyword.matchType,keyword.text,negative,resourceName" 今回はresourceChangeOperationがCREATEなのでoldResourceはカラです。 同じようにresourceChangeOperationがREMOVEの場合はnewResourceがカラで来ます。 oldとnew両方に値が入ってるのはUPDATEだけということになります。 この例では、ad_group_criterionの adGroup,criterionId,keyword.matchType,keyword.text,negative,resourceNameと 6種類のフィールドを変更したことになります。 newResourceを見てみると、 adGroupCriterionの下に5つ(keywordの下には更に2つ)の構造になっていますね。。 このようにchangedFieldsは、複数フィールドの場合はカンマ区切りで来ます。 更にkeyword.matchTypeのようにカンマが入っているのは、 更に下に階層構造を持っていることを意味します。 これがフィールドによって階層構造が異なるのでホントやっかい。 特定のフィールドのものだけ取ろうとするならまあいいとして、 全部の履歴を取るならいちいち場合分けをして配列の中身を取り出さないといけません。 もう少し簡単に作ってほしかった。。 ものによって階層が違うのでどうすべきか散々悩んだ結果、 jsonに頑張って書くことでなんとか落ち着きました。 もっとスマートにできるアイディアがあればいいんだけど・・・ ということでそのjsonに規定した内容でだいたいの階層構造が分かると思うので 参考までにここに載せておきます。 "class"とあるフィールドは階層構造になっているということ。 "#num"とあるところは配列になっていて0~の数字が入ります。 "end"は階層構造の最後という目印。(ないのもあるけど便宜上仕方なかったやつ) setting.json "changed_fields" : { "$comment": "#---------------変更フィールド:値によって構造が異なるので注意※[#num]となっている項目は配列の数値が入る", "$comment_default": "#---------------共通", "name" : {"name" : "名称"}, "status" : {"name" : "ステータス"}, "bidModifier" : {"name" : "入札調整比"}, "$comment_ad": "#---------------[ad]用", "responsiveSearchAd.headlines" : { "name" : "広告見出し", "class" : {"#num.text" : "end"} }, "responsiveSearchAd.descriptions" : { "name" : "説明文", "class" : {"#num.text" : "end"} }, "responsiveSearchAd.path1" : {"name" : "パス1"}, "responsiveSearchAd.path2" : {"name" : "パス2"}, "expandedTextAd.headlinePart1" : {"name" : "広告見出し1"}, "expandedTextAd.headlinePart2" : {"name" : "広告見出し2"}, "expandedTextAd.headlinePart3" : {"name" : "拡張テキスト広告"}, "expandedTextAd.description" : {"name" : "説明文1"}, "expandedTextAd.description2" : {"name" : "説明文2"}, "expandedTextAd.path1" : {"name" : "パス1"}, "expandedTextAd.path2" : {"name" : "パス2"}, "finalUrls" : { "name" : "最終ページURL", "class" : {"#num" : "end"} }, "urlCustomParameters" : { "name" : "URLカスタムパラメータ", "class" : {"#num.key" : "end", "#num.value" : "end"} }, "finalMobileUrls" : { "name" : "モバイル用最終ページURL", "class" : {"#num" : "end"} }, "trackingUrlTemplate" : {"name" : "トラッキングテンプレート"}, "finalUrlSuffix" : {"name" : "最終ページURLサフィックス"}, "$comment_campaign": "#---------------[campaign]用", "networkSettings.targetContentNetwork" : {"name" : "ネットワーク設定:Googleディスプレイネットワーク"}, "networkSettings.targetGoogleSearch" : {"name" : "ネットワーク設定:Google検索パートナー"}, "targetCpa.targetCpaMicros" : {"name" : "キャンペーン目標コンバージョン単価"}, "targetSpend.cpcBidCeilingMicros" : {"name" : "上限CPC"}, "targetRoas.targetRoas" : {"name" : "キャンペーン目標費用対効果"}, "manualCpc.enhancedCpcEnabled" : {"name" : "拡張クリック単価"}, "targetImpressionShare.cpcBidCeilingMicros" : {"name" : "上限CPC"}, "targetImpressionShare.location" : {"name" : "広告掲載場所"}, "targetImpressionShare.locationFractionMicros" : {"name" : "目標インプレッションシェア"}, "startDate" : {"name" : "開始日"}, "endDate" : {"name" : "終了日"}, "adServingOptimizationStatus" : {"name" : "広告のローテーション"}, "paymentMode" : {"name" : "支払いモード"}, "advertisingChannelType" : {"name" : "広告チャンネルタイプ"}, "$comment_campaignBudget": "#---------------[campaignBudget]用", "amountMicros" : {"name" : "予算額"}, "$comment_campaignCriterion": "#---------------[campaignCriterion]用", "adSchedule.dayOfWeek" : {"name" : "スケジュール[曜日]"}, "adSchedule.endHour" : {"name" : "スケジュール[終了(時)]"}, "adSchedule.endMinute" : {"name" : "スケジュール[終了(分)]"}, "adSchedule.startHour" : {"name" : "スケジュール[開始(時)]"}, "adSchedule.startMinute" : {"name" : "スケジュール[開始(分)]"}, "$comment_criterion": "#---------------[criterion]用", "ageRange.type" : {"name" : "ユーザー属性(年齢)"}, "gender.type" : {"name" : "ユーザー属性(性別)"}, "incomeRange.type" : {"name" : "ユーザー属性(世帯収入)"}, "parentalStatus.type" : {"name" : "ユーザー属性(親のステータス)"}, "keyword.matchType" : {"name" : "キーワードマッチタイプ"}, "keyword.text" : {"name" : "キーワード"}, "$comment_adGroup": "#---------------[adGroup]用", "targetCpaMicros" : {"name" : "目標コンバージョン単価"}, "cpcBidMicros" : {"name" : "上限クリック単価"}, "cpmBidMicros" : {"name" : "上限CPM"}, "cpvBidMicros" : {"name" : "上限広告視聴単価"}, "targetCpmMicros" : {"name" : "目標インプレッション単価"}, "targetRoas" : {"name" : "目標費用対効果"}, "adRotationMode" : {"name" : "広告のローテーション"}, "targetingSetting.targetRestrictions" : { "name" : "ターゲティングの制限", "class" : { "#num.targetingDimension" : {"name" : "ターゲティングディメンション"}, "#num.bidOnly" : {"name" : "ターゲティング設定"} } }, "$comment_adGroupAd": "#---------------[adGroupAd]用", "ad" : { "name" : "広告詳細", "class" : { "responsiveSearchAd.headlines" : { "name" : "広告見出し", "class" : {"#num.text" : "end"} }, "responsiveSearchAd.descriptions" : { "name" : "説明文", "class" : {"#num.text" : "end"} }, "responsiveSearchAd.path1" : {"name" : "パス1"}, "responsiveSearchAd.path2" : {"name" : "パス2"}, "expandedTextAd.headlinePart1" : {"name" : "広告見出し1"}, "expandedTextAd.headlinePart2" : {"name" : "広告見出し2"}, "expandedTextAd.headlinePart3" : {"name" : "拡張テキスト広告"}, "expandedTextAd.description" : {"name" : "説明文1"}, "expandedTextAd.description2" : {"name" : "説明文2"}, "expandedTextAd.path1" : {"name" : "パス1"}, "expandedTextAd.path2" : {"name" : "パス2"}, "finalUrls" : { "name" : "最終ページURL", "class" : {"#num" : "end"} }, "urlCustomParameters" : { "name" : "URLカスタムパラメータ", "class" : {"#num" : {"key" : "end", "value" : "end"}} }, "finalMobileUrls" : { "name" : "モバイル用最終ページURL", "class" : {"#num" : "end"} }, "trackingUrlTemplate" : {"name" : "トラッキングテンプレート"}, "finalUrlSuffix" : {"name" : "最終ページURLサフィックス"} } }, "$comment_adGroupBidModifier": "#---------------[adGroupBidModifier]用", "device.type" : {"name" : "デバイス"} }, ad_group_adだけは階層の中身が複雑で、入れ子のさらに入れ子になってました。 データなかなか取れなくて苦労したわ・・・ 上記は自分に関係ある内容だけであって、取れるフィールド全てではありません。 FEEDとかはいじってないので、どんな値が来るのかよくわかりません。。 GoogleAdsの方でも割と親切にドキュメントは用意してくれてるんだけど、 情報が散らばっちゃってどこ見ればいいの?って状態に私はなってしまったので、 構造をパッと見で理解しやすくなるんじゃないかな、と。。。 不具合かな?と思われる内容 *clientTypeがGOOGLE_ADS_EDITOR(GoogleAdsEditorで編集したもの)はAPIとしてデータが来ない 全部のデータがあるわけじゃないなあと調べてみたら、EDITORのデータはごっそりありませんでした。 調べてみたら、不具合で対応中? 2021/05/13現在、まだ取れない。。 *キャンペーンの設定で(changeResourceType:Campaign)目標・地域・言語を変更しても APIからデータが来ない。 *キャンペーンの設定で(change_resource_type:campaignCriterion)入札単価調整の数値を入力しても カラデータが来る(たぶんchanged_fieldsはbidModifier) おわりに なんとなく、調べながらも「これほんとに合ってるのかな?」と不安になるようなことが多々あって まだ安定版じゃないのかなあという印象を持ってます。 最初の例に上げた目標コンバージョン価格とか、 よく使われる広告グループの数値系はちゃんとしてるっぽい?ので、 参照するフィールドは限定して、正しそうなものを選んで使っていくのがいいのかなと感じました。 おしまい。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Xdebug のインストール PHP デバッグ Mac Big Sur

Xdeubgのインストールにとてつもなく膨大な時間を費やした。 環境 mac OS Big Sur バージョン 11.3.1 $ brew list | grep php php@7.4 phpmyadmin 結論 ↓どおりにインストールしてエラーを解決しながらやっていくと、Xdebugをインストールできた。 Homebrew で php7.4 + Xdebug をインストール しかし、peclでのインストールにおいてエラー発生。 pecl install xdebug ・・・エラー省略。 asm goto' constructs are not supported yet これは、↓曰く Command Line Tools for xcode (CLT)のバージョンの問題らしい。 https://bugs.php.net/bug.php?id=80939&edit=1 ↓で確かめてみると $ clang --version Apple clang version 11.0.0 (clang-1100.0.33.17) Target: x86_64-apple-darwin19.6.0 Thread model: posix InstalledDir: /Library/Developer/CommandLineTools/usr/bin そこで、 CLTのアップデートを行った。 ちなみに、CLTには2種類あって①システムにインストールされているCLT ②Xcodeのパッケージに埋め込まれているCLT があるとのこと。 brew upgrade でのエラー対処からCommand Line Toolsについてまとめてみる アップデート方法は↑の記事に書かれている通り。 一度システムにインストールされているのCLTを削除。再度インストール。 $ sudo rm -rf /Library/Developer/CommandLineTools $ sudo xcode-select --install 晴れて、バージョンアップに成功。 $clang --version Apple clang version 12.0.5 (clang-1205.0.22.9) Target: x86_64-apple-darwin20.4.0 Thread model: posix InstalledDir: /Library/Developer/CommandLineTools/usr/bin 再度、peclでxdebugをインストールすると、成功。 $ pecl install xdebug ・・・ Build process completed successfully Installing '/usr/local/Cellar/php@7.4/7.4.19/pecl/20190902/xdebug.so' install ok: channel://pecl.php.net/xdebug-3.0.4 Extension xdebug enabled in php.ini Installing '/usr/local/Cellar/php@7.4/7.4.19/pecl/20190902/xdebug.so' の部分をメモって、php.iniに書く。 php.iniの探し方↓ $ /usr/local/opt/php@7.4/bin/php -r "echo phpinfo();" | grep "php.ini" php.ini zend_extension="/usr/local/Cellar/php@7.4/7.4.19/pecl/20190902/xdebug.so" これでやっとVSCodeでのPHPをデバッグできる。 と思ったら、VSCodeでデバッグ開始しても、ブレークポイントで止まらない。 そこで、VSCodeのextensionでインストールしたPHP Debugのドキュメントを見てみると There are other ways to tell Xdebug to connect to a remote debugger, like cookies, query parameters or browser extensions. I recommend remote_autostart (Xdebug v2)/start_with_request (Xdebug v3) because it "just works". There are also a variety of other options, like the port, please see the Xdebug documentation on remote debugging for more information. Please note that the default Xdebug port changed between Xdebug v2 to v3 from 9000 to 9003. The extension still defaults to 9000, so make sure your configuration in launch.json and php.ini match. つまり、「Xdebugのバージョンに合わせて書け」とのこと。(意訳) あと、「Xdebugのバージョンv2からv3に合わせてポート番号が9000から9003に変わった。launch.jsonとphp.ini確かめろよ」とのこと。 筆者の場合だと以下を追記するとブレークポイントで止まるようになった。 php.ini zend_extension="/usr/local/Cellar/php@7.4/7.4.19/pecl/20190902/xdebug.so" [PHP] xdebug.remote_enable=1 xdebug.remote_host=localhost xdebug.remote_autostart=1 xdebug.mode = debug xdebug.start_with_request = yes ←こいつをonにすることでプレー区ポイントで止まった。 ;デフォルトは9003 xdebug.client_port = 9003
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel mimetypesでバリデーション設定したら突破するはずの値が弾かれる

目的 mimetypesのバリデーションルールを設定後にバリデーションを通過するはずの値が弾かれる問題の原因をまとめる 原因 Mimetypeの指定時にスペースを入れてしまっていた。 問題のソース 下記のようにバリデーションルールを記載した。 アプリ名ディレクトリ/todos/app/Http/Requests/TaskRequest.php <?php namespace App\Http\Requests; use Illuminate\Foundation\Http\FormRequest; class TaskRequest 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 [ 'name' => ['required'], 'limit_id' => ['required'], 'file' => [ 'required', 'file', 'image', 'mimetypes: image/jpeg, image/png', ], ]; } } 注目いただきたいソースは'mimetypes: image/jpeg, image/png',の部分であり、Mimetype名の前に半角スペースが空いている。これが原因だった。 問題を解消したソース 下記のようにバリデーションルールを記載した。 アプリ名ディレクトリ/todos/app/Http/Requests/TaskRequest.php <?php namespace App\Http\Requests; use Illuminate\Foundation\Http\FormRequest; class TaskRequest 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 [ 'name' => ['required'], 'limit_id' => ['required'], 'file' => [ 'required', 'file', 'image', 'mimetypes:image/jpeg,image/png', ], ]; } } 上記のように半角スペースを開けずに記載することでバリデーションを突破する事ができた。 参考文献 https://developer.mozilla.org/ja/docs/Web/HTTP/Basics_of_HTTP/MIME_types
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む