- 投稿日:2020-07-30T20:07:48+09:00
[PHP]西暦を和暦に変換する
何度か西暦を和暦に変換する処理を書く機会があったので、
また必要になった時に汎用的に使い回せるよう、関数を作成しました。なお、日本では明治5年12月2日(西暦1872年12月31日)に旧暦(天保暦)を廃止し、その翌日からグレゴリオ暦に移行して明治6年(1873年)1月1日になったため、明治5年以前の日付には対応していません。
※明治5年以前の場合は西暦で返します。/** * 西暦→和暦変換 * * @param string $format 'K':元号 * 'k':元号略称 * 'Q':元号(英語表記) * 'q':元号略称(英語表記) * 'X':和暦年(前ゼロ表記) * 'x':和暦年 * @param string $time 変換対象となる日付(西暦) * * @return string $result 変換後の日付(和暦) */ function to_wareki($format, $time='now') { // 元号一覧 $era_list = [ // 令和(2019年5月1日〜) [ 'jp' => '令和', 'jp_abbr' => '令', 'en' => 'Reiwa', 'en_abbr' => 'R', 'time' => '20190501' ], // 平成(1989年1月8日〜) [ 'jp' => '平成', 'jp_abbr' => '平', 'en' => 'Heisei', 'en_abbr' => 'H', 'time' => '19890108' ], // 昭和(1926年12月25日〜) [ 'jp' => '昭和', 'jp_abbr' => '昭', 'en' => 'Showa', 'en_abbr' => 'S', 'time' => '19261225' ], // 大正(1912年7月30日〜) [ 'jp' => '大正', 'jp_abbr' => '大', 'en' => 'Taisho', 'en_abbr' => 'T', 'time' => '19120730' ], // 明治(1873年1月1日〜) // ※明治5年以前は旧暦を使用していたため、明治6年以降から対応 [ 'jp' => '明治', 'jp_abbr' => '明', 'en' => 'Meiji', 'en_abbr' => 'M', 'time' => '18730101' ], ]; $dt = new DateTime($time); $format_K = ''; $format_k = ''; $format_Q = ''; $format_q = ''; $format_X = $dt->format('Y'); $format_x = $dt->format('y'); foreach ($era_list as $era) { $dt_era = new DateTime($era['time']); if ($dt->format('Ymd') >= $dt_era->format('Ymd')) { $format_K = $era['jp']; $format_k = $era['jp_abbr']; $format_Q = $era['en']; $format_q = $era['en_abbr']; $format_X = sprintf('%02d', $format_x = $dt->format('Y') - $dt_era->format('Y') + 1); break; } } $result = ''; foreach (str_split($format) as $val) { // フォーマットが指定されていれば置換する if (isset(${"format_{$val}"})) { $result .= ${"format_{$val}"}; } else { $result .= $dt->format($val); } } return $result; }作成した関数を使って、和暦に変換してみます。
echo to_wareki('KX年m月d日', '18730101').PHP_EOL; echo to_wareki('kx/n/j', '1914/08/07').PHP_EOL; echo to_wareki('Qx-m-d', '1947-05-16').PHP_EOL; echo to_wareki('m/d/Y(qX) H:i:s', '2016-03-20 12:34:56').PHP_EOL; echo to_wareki('Y(Kx)年n月j日');出力結果は以下の通りです。
明治06年01月01日 大3/8/7 Showa22-05-16 03/20/2016(H28) 12:34:56 2020(令和2)年7月30日和暦変換プログラム自体はとくに目新しさはないですが、色々なフォーマットに対応できるようにしてみました。
もしよかったらぜひ試してみてください。
- 投稿日:2020-07-30T15:38:48+09:00
[PHPStorm]Shelfで並行開発を楽に管理する
はじめに
PHPStormのバージョン管理のヘルパー機能である、
Shelf
の使い方メモです。詳細は公式ドキュメントを参照してください。
→ Gitを使用して複数の機能を同時に処理するPHPStormの使い方シリーズ
作業用フォルダを用意する
まず、今回作業を行うフォルダを用意します。
この記事では、ローカルリポジトリ上で作業を行います。% cd ~/Desktop % mkdir shelf % cd shelfローカルリポジトリを作成します。
% git init % ls -la drwxr-xr-x@ 3 mitsuoka-takahiro staff 96 7 29 21:19 ./ drwx------@ 14 mitsuoka-takahiro staff 448 7 29 21:16 ../ drwxr-xr-x 9 mitsuoka-takahiro staff 288 7 29 21:19 .git/.gitフォルダがあればOK。
PHPStormでGitツールウィンドウを表示する
View > Tool Windows > Git
から開くことができます。
ショートカットはデフォルトで⌘9
に設定されています。このような感じのウィンドウが開きます。
Shelfで並行開発を楽に管理する
Shelfは
git stash
と似た機能で、ブランチをクリーンにすることができます。
変更リストとの親和性が高く、合わせて使うことで開発中のファイルをより便利に管理できます。準備
新しいファイルを3つ追加し、ステージングします。
ステージングするのは、バージョン管理対象ファイルでないとLocal Changesに表示されなからです。% echo hello > a1.txt % echo hello > a2.txt % echo hello > b2.txt % git add .Gitツールウィンドウはこのようになっていると思います。
さらに、変更リスト
add feature A
にa1.txt
とa2.txt
を入れておきます。ファイルをShelfにしまう
Gitツールウィンドウで
b2.txt
を右クリックし、Shelf Changes
を選択します。コミットメッセージを求められるので、
add feature B
と入力し、Shelve Changes
をクリックします。これでShelfに
b2.txt
をしまうことができました。
GitツールウィンドウにShelf
タブが表示され、内容を確認することができます。同時に、作業ブランチ上から
b2.txt
がなくなっていることが確認できます。% git status On branch master No commits yet Changes to be committed: (use "git rm --cached <file>..." to unstage) new file: a1.txt new file: a2.txtShelfからファイルを取り出す
Shelf
タブのadd feature B
を右クリック、Unshelve...
を選択します。ウィンドウが表示されるので、変更せず
Unshelve Changes
をクリックします。
Local Changes
タブに変更リストadd feature B
が追加され、b2.txt
の変更も適用されます。変更リストをShelfにしまう
ファイルだけでなく、既に作成している変更リストをShelfにしまうこともできます。
対象の変更リストを右クリック、Shelve Changes
を選択することで、Shelfに格納されます。まとめ
Shelfを使うことで、変更リストと親和性の高い
git stash
に似た機能を利用することができる。
Shelfにしまったファイルは、ワークツリーから削除されるので、作業ブランチをクリーンに保つことができる。PHPStormの使い方シリーズ
- 投稿日:2020-07-30T14:58:59+09:00
VultrでKUSANAGI Runs on Dockerが動くまで(その2)
前回のおさらい
前回の記事『VultrでKUSANAGI Runs on Dockerが動くまで(その1)』ではVPC環境であるVultrにKUSANAGI RoDをインストールするところまで確認しました。
今回はWordpressを運用しやすくするため、Dockerコンテナの設定を少し変えていきたいと思います。動作環境など
- Ubuntu 20.04
- docker 19.03.12
- docker-compose 1.26.2
$ docker-compose ps Name Command State Ports -------------------------------------------------------------------------------- kusanagi01_certbot certbot --version Up kusanagi01_config docker-entrypoint.sh wp -- ... Up kusanagi01_db docker-entrypoint.sh mysqld Up kusanagi01_ftp /bin/sh -c /docker-entrypo ... Up kusanagi01_httpd /docker-entrypoint.sh /usr ... Up 8080/tcp, 8443/tcp kusanagi01_php /usr/local/bin/docker-entr ... Up修正前のdocker-compose.yaml
プロビジョニング直後はこんな感じになっています。
【主な特徴】
- それぞれのコンテナでDocumentRoot含む必要なファイル類を/home/kusanagiにマウント
- kusanagiボリュームとdatabaseボリュームを永続化
docker-compose.ymlversion: '3' networks: default: driver: bridge driver_opts: com.docker.network.driver.mtu: 9000 shared-network: external: true services: httpd: container_name: kusanagi01_httpd image: primestrategy/kusanagi-nginx:1.17.9-r0 restart: always env_file: - .kusanagi - .kusanagi.httpd volumes: - kusanagi:/home/kusanagi - kusanagi:/etc/letsencrypt - kusanagi:/var/www/html/.well-known ports: - "8080:8080" - "8443:8443" extra_hosts: - "domain.name:127.0.0.1" networks: - shared-network certbot: container_name: kusanagi01_certbot image: certbot/certbot:v1.6.0 restart: always network_mode: "service:httpd" env_file: - .kusanagi.httpd volumes: - kusanagi:/var/www/html/.well-known - kusanagi:/etc/letsencrypt command: - --version ## CONFIG config: container_name: kusanagi01_config restart: always build: context: ./wpcli user: "1000:1001" env_file: - .kusanagi - .kusanagi.wp - .kusanagi.db volumes: - database:/var/run/mysqld - kusanagi:/home/kusanagi command: wp --version php: container_name: kusanagi01_php image: primestrategy/kusanagi-php:7.4.8-r0 restart: always env_file: - .kusanagi - .kusanagi.php - .kusanagi.mail network_mode: "service:httpd" volumes: - database:/var/run/mysqld - kusanagi:/home/kusanagi ## MYSQL db: container_name: kusanagi01_db image: mariadb:10.5.4-focal restart: always user: "999:999" env_file: - .kusanagi.mysql network_mode: "service:httpd" volumes: - database:/var/run/mysqld - database:/var/lib/mysql ## FTPD ftp: container_name: kusanagi01_ftp image: primestrategy/kusanagi-ftpd:1.0.2-r1 restart: always network_mode: "service:httpd" env_file: - .kusanagi - .kusanagi.wp volumes: - kusanagi:/home/kusanagi volumes: kusanagi: database:今回の変更点
以下の点を変更します。
- nginxのログ出力をDockerの標準ログ出力に変更
- PHPのファイルアップロード設定を追加
- 不要なコンテナ(certbot)を停止
変更点1
nginxのログ出力をDockerの標準ログ出力に変更します。
nginxフォルダの中にnginx.confファイルを作成しhttpdコンテナのnginx.confを書き換えます。nginx.confの変更部分のみ記載しておきます。$HOME/kusanagi01/nginx/nginx.conf#error_log /var/log/nginx/error.log warn; error_log /dev/stderr warn; #access_log /var/log/nginx/access.log main; access_log /dev/stdout main;変更点2
デフォルトだと2MB以上のファイルアップロードができないのでPHPのファイルアップロード設定を追加します。
phpフォルダの中にuploads.iniファイルを作成しphpコンテナにuploads.iniを追加します。$HOME/kusanagi01/php/uploads.inifile_uploads = On memory_limit = 256M upload_max_filesize = 64M post_max_size = 64M max_execution_time = 600以下のようなフォルダ構成になります。
/home └$USER ├https-portal ← リバプロサーバー(マルチサイト& Let’s Encrypt対応) │ └docker-compose.yml │ ├kusanagi01 ← KUSANAGI Runs on Docker(WordPressサイト1つ目) │ ├nginx ※追加 │ │ └nginx.conf ※追加 │ ├php ※追加 │ │ └ uploads.ini ※追加 │ └docker-compose.yml │ └kusanagi02 ← KUSANAGI Runs on Docker(WordPressサイト2つ目) └docker-compose.yml変更点3
certbotコンテナが実験中で使われていないので起動しないようにします。
こちらはdocker-compose.ymlファイルで該当箇所をコメントアウトしてしまえばOKです。修正後のdocker-compose.yml(抜粋)
docker-compose.yml#certbot: #container_name: kusanagi01_certbot #image: certbot/certbot:v1.6.0 #restart: always #network_mode: "service:httpd" #env_file: #- .kusanagi.httpd #volumes: #- kusanagi:/var/www/html/.well-known #- kusanagi:/etc/letsencrypt #command: #- --versionコンテナの再作成
構成を変更したのでコンテナを作り直します。エラー無く起動することを確認します。
$ docker-compose down $ docker-compose up -d動作確認
変更が反映されているか確認していきます。
nginxのログ出力先変更
以下のコマンドでDockerのログを表示させWebのアクセスログが出力されることを確認します。
$ docker logs kusanagi01_httpd -fPHPのファイルアップロード設定
phpinfoファイルを作成しコンテナにコピーし動作確認します。コンテナにシェルアクセスして作成してもよいですけどkusanagi-dockerコマンドでコンテナへのファイルコピーができます。
$HOME/content/DocumentRoot/test.php<?php phpinfo() ?>$ cd $HOME/kusanagi01 $ kusanagi-docker config push chown: unknown user/group kusanagi:www ERROR: Failed.ブラウザでtest.phpにアクセスしてuploads.iniで変更した部分が反映されていることを確認しておきましょう。確認が終わったらtest.phpの削除も忘れずに。
VultrでKUSANAGI Runs on Dockerが動くまで(その3)に続きます。
- 投稿日:2020-07-30T14:42:48+09:00
Laravel artisanコマンド 【備忘録】
- 投稿日:2020-07-30T14:26:35+09:00
raspberry pi 4にphpenvをインストール!!
とはいいつつ、基本的には公式サイトに掲載されている#installationを参考にすればOKです。前提パッケージが無い場合コンパイルが失敗するので主にそっちのメモの意味合いが強いです...
前提パッケージ
sudo apt install \ build-essential \ libxml2-dev \ libkrb5-dev \ libonig-dev \ libxslt1-dev \ libtidy-dev \ libzip-dev上記が無いとコンパイル中にコケるので入れておきましょう。上記を実行した上で失敗した場合はエラーログに必要なパッケージが書いてあるので、適宜追加して下さい。そして教えて下さい。追記致します。
phpenvのinstall
Github - phpenv/phpenv#installationを参考にして下さい(投げやり)
トラブルシューティング
- ダウンロードに失敗する場合
- 自宅の回線速度が遅い場合、
openssl
云々という表示が出たりしてタイムアウト、失敗してしまいます。空いている時間帯にもう一度チャレンジしましょう。Stay Homeの影響で固定回線も混雑しているんでしょうか...。- ダウンロードは出来たが、コンパイルに失敗する場合
- コンパイルに必要なパッケージが足りないと思われます。ログを確認後、
apt search
などを駆使してそれっぽいのを入れてみましょう。引用・出典・参考
- 投稿日:2020-07-30T13:35:52+09:00
「 $i = $i++;」が使えないことを知った話
※自分用メモです
はじまり
事の始まりは、実行すると無限ループするfor文から。
内容としては
1.要素数「4」の配列に、乱数(0~9)を利用して値を格納する。
2.格納した内容はループを利用して出力する。
の簡単なものだ。
終了条件がおかしくなっているように思うのでそこを見てみた。この1行である。
for($i=0; $i<=3; $i=$i++)
全くわからなくてTwitter上でアドバイスを求めたところ、一人の先輩からこんなアドバイスをいただいた。
「$i=$i++
は$i++
でいいよ」なぜ
上のアドバイスと一緒に、理由も書いてくれているページを教えてもらった。
なぜ i = i++; としてはいけないか
ここを読んで自分なりに考えた結果、以下のような解釈に至った。
(注:コメントで正確な話を教えていただきました!ありがとうございます!)(「;」といういわゆる副作用完了点という存在を知った前提で)
一度に、
1. iへの代入をしようとした
2. i+1をしようとした
つまり、「iという変数を1つの副作用完了点と副作用完了点の間で2回書き換えようとしたこと」が原因だと解釈した。
つまり、PHPに限らずある副作用完了点から、その次の副作用完了点までの間で1つの変数を複数回書き換えるような動作は認められていないために、ほかの言語でこれ(\$i=$i++)をやってもアウトだと考えた。
- 投稿日:2020-07-30T13:05:22+09:00
PHPでPayPayAPIにリクエスト投げて成功するまで
PayPayAPIにリクエスト投げて成功するまでの記事です
PayPay for Developers
PayPay for Developersで登録してAPI_KEY、API_SECRET、MERCHANT_IDの取得が必要(登録方法は割愛)
sdkインストール
composer require paypayopa/php-sdk
成功したソース
<?php namespace App\Helpers; use PayPay\OpenPaymentAPI\Client; use PayPay\OpenPaymentAPI\Models\CreateQrCodePayload; class PayPay { protected Client $paypayClient; function __construct() { $paypayConfig = \Config::get('paypay'); $this->paypayClient = new Client([ 'API_KEY' => $paypayConfig['API_KEY'], 'API_SECRET' => $paypayConfig['API_SECRET'], 'MERCHANT_ID' => $paypayConfig['MERCHANT_ID'], ], true); //Set True for Production Environment. By Default this is set False for Sandbox Environment. // Creating the payload to create a QR Code, additional parameters can be added basis the API Documentation $payload = new CreateQrCodePayload(); $payload->setMerchantPaymentId("my_payment_id" . \time()); $payload->setCodeType("ORDER_QR"); $amount = [ "amount" => 1, "currency" => "JPY" ]; $payload->setAmount($amount); $payload->setRedirectType('WEB_LINK'); $payload->setRedirectUrl('https://paypay.ne.jp/'); $payload->setUserAgent('Mozilla/5.0 (iPhone; CPU iPhone OS 10_3 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) CriOS/56.0.2924.75 Mobile/14E5239e Safari/602.1'); //================================================================= // Calling the method to create a qr code //================================================================= $response = $this->paypayClient->code->createQRCode($payload); // 処理がうまくいってなかったら抜ける if($response['resultInfo']['code'] !== 'SUCCESS') { return; } // Collectionに変換しておく $QRCodeResponse = collect($response['data']); //================================================================= // Calling the method to get payment details //================================================================= $response = $this->paypayClient->payment->getPaymentDetails($QRCodeResponse['merchantPaymentId']); // 処理がうまくいってなかったら抜ける if($response['resultInfo']['code'] !== 'SUCCESS') { return; } // Collectionに変換しておく $QRCodeDetails = collect($response['data']); //================================================================= // Calling the method to cancel a Payment //================================================================= $response = $this->paypayClient->payment->cancelPayment($QRCodeResponse['merchantPaymentId']); // 処理がうまくいってなかったら抜ける if($response['resultInfo']['code'] !== 'REQUEST_ACCEPTED') { return; } \Log::info(print_r($QRCodeResponse, true)); \Log::info(print_r($QRCodeDetails, true)); \Log::info(print_r($response, true)); } function __destruct() { } }logの内容
[2020-07-30 06:53:42] local.INFO: Illuminate\Support\Collection Object ( [items:protected] => Array ( [codeId] => 04-PKkfM9UDxn13nFfl [url] => https://qr-stg.sandbox.paypay.ne.jp/28180104PKkfM9UDxn13nFfl [expiryDate] => 1596081556 [merchantPaymentId] => my_payment_id_1596093507 [amount] => Array ( [amount] => 1 [currency] => JPY ) [codeType] => ORDER_QR [redirectUrl] => https://paypay.ne.jp/ [redirectType] => WEB_LINK [isAuthorization] => [deeplink] => paypay://payment?link_key=https%3A%2F%2Fqr-stg.sandbox.paypay.ne.jp%2F28180104PKkfM9UDxn13nFfl ) ) [2020-07-30 06:53:42] local.INFO: Illuminate\Support\Collection Object ( [items:protected] => Array ( [status] => CREATED [acceptedAt] => 0 [requestedAt] => 0 ) ) [2020-07-30 06:53:42] local.INFO: Array ( [resultInfo] => Array ( [code] => REQUEST_ACCEPTED [message] => Request accepted [codeId] => 08100001 ) [data] => [transit] => Array ( [0] => HTTP/2 202 [1] => date: Thu, 30 Jul 2020 06:53:42 GMT [2] => content-type: application/json [3] => x-request-id: OPA4CE2D1787C11436F95A9B13DFEDFE3D6 [4] => x-content-type-options: nosniff [5] => x-xss-protection: 1; mode=block [6] => cache-control: no-cache, no-store, max-age=0, must-revalidate [7] => pragma: no-cache [8] => expires: 0 [9] => x-frame-options: DENY [10] => x-rate-limited: 1 [11] => [12] => ) )つまづきポイント
コメント文のミス?
サンプルコードでは
use PayPay\OpenPaymentAPI\Client; $client = new Client([ 'API_KEY' => 'YOUR_API_KEY', 'API_SECRET'=>'YOUR_API_SECRET', 'MERCHANT_ID'=>'YOUR_MERCHANT_ID' ],false); //Set True for Production Environment. By Default this is set False for Sandbox Environment.
//Set True for Production Environment. By Default this is set False for Sandbox Environment.
って書いてるけどtrue
でステージング環境(開発用)になるサンプルソースのミスその1(ペイロード?を作るとき)
サンプルコードでは
// Creating the payload to create a QR Code, additional parameters can be added basis the API Documentation $payload =new PaypaySdkPayload(); $payload->set_merchant_payment_id("my_payment_id"); $payload->set_code_type("ORDER_QR"); $amount = [ "amount" => 1, "currency" => "JPY" ]; $payload->set_amount($amount); $payload->set_redirect_type('WEB_LINK'); $payload->set_redirect_url('https://paypay.ne.jp/'); $payload->set_user_agent('Mozilla/5.0 (iPhone; CPU iPhone OS 10_3 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) CriOS/56.0.2924.75 Mobile/14E5239e Safari/602.1'); // Calling the method to create a qr code $response = $client->code->createQRCode($payload); // Printing if the method call was SUCCESS console.log($response['resultInfo']['code']);こうなってるけど、
PaypaySdkPayload
のようなクラスはない、そしてset_
の関数もないサンプルソースのミスその2(詳細を見るとき)
// Calling the method to get payment details $response = $client->code->getPaymentDetails('<merchantPaymentId>'); // Printing if the method call was SUCCESS, this does not mean the payment was a success console.log($response['resultInfo']['code']); // Printing if the transaction status for the code has COMPLETED/ AUTHORIZED console.log($response['data']['status']);
$client->code->getPaymentDetails('<merchantPaymentId>');
実際は$client->payment->getPaymentDetails('<merchantPaymentId>');
サンプルソースのミスその3(キャンセルするとき)
// Calling the method to cancel a Payment $response = $client->code->cancelPayment('merchantPaymentId'); // Printing if the method call was SUCCESS console.log($response['resultInfo']['code']);
$client->code->getPaymentDetails('<merchantPaymentId>');
実際は$client->payment->getPaymentDetails('<merchantPaymentId>');
および
// Printing if the method call was SUCCESS
って書いてて、ああ上と一緒でSUCCESS
なんだろうなぁって思うかもしれないけど、実際はREQUEST_ACCEPTED
が帰ってきている(ちゃんと読め私w
- 投稿日:2020-07-30T12:19:39+09:00
PHPでClassをrequireせずに使う
Laravelの
request()
とかがどうやって呼ばれてるのかを調べていくうちに辿り着いたのでメモがてら。
Class
は簡単に読み込めるけど、Function
は一筋縄ではいかなさそう。ついでに
Class
に好き勝手プロパティ増やせることも発見した。autoloaderを実装
spl_autoload_registerを使う。Laravelはcomposerが上手いことやってくれてるっぽかった
bootstrap.php<? function regist() { spl_autoload_register(function() { require './Hoge.php'; require './Piyo.php'; }); }使いたいクラス
適当に用意
Hoge.php<? class Hoge { public $hoge; }Piyo.php<? class Piyo { public $piyo; }autoloaderを呼んで使う
ついでに好き勝手にプロパティも生やす
test.php<? require './bootstrap.php'; // ここでクラスをautoloadする regist(); // どこからも呼んでないけど $h = new Hoge; // 生やせる $h->fuga = "aaa"; $h->hogepiyo = "bbb"; // 使える $p = new Piyo; $p->fuga = "aaa"; $p->hogepiyo = "bbb"; var_dump($h, $p); /* 結果 class Hoge#2 (3) { public $hoge => NULL public $fuga => string(3) "aaa" public $hogepiyo => string(3) "bbb" } class Piyo#3 (3) { public $piyo => NULL public $fuga => string(3) "aaa" public $hogepiyo => string(3) "bbb" } */
- 投稿日:2020-07-30T10:39:25+09:00
Laravel 任意のディレクトリ直下にモデルファイルを作成する
目的
- 実務でモデルファイルを作成する時に
アプリ名ディレクトリ/app
に作成することよりもアプリ名ディレクトリ/app/Models
直下に作成することが多いため、方法をまとめる実施環境
- ハードウェア環境
項目 情報 OS macOS Catalina(10.15.5) ハードウェア MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports) プロセッサ 2 GHz クアッドコアIntel Core i5 メモリ 32 GB 3733 MHz LPDDR4 グラフィックス Intel Iris Plus Graphics 1536 MB
- ソフトウェア環境
項目 情報 備考 PHP バージョン 7.4.3 Homwbrewを用いて導入 Laravel バージョン 7.0.8 commposerを用いてこちらの方法で導入→Mac Laravelの環境構築を行う MySQLバージョン 8.0.19 for osx10.13 on x86_64 Homwbrewを用いてこちらの方法で導入→Mac HomebrewでMySQLをインストールする 前提条件
- 実施環境と同じLaravelローカル開発環境が構築されていること。
前提情報
- 特になし
読後感
- モデルファイルを
アプリ名ディレクトリ/app
直下の任意のディレクトリ内に作成することができる。例
アプリ名ディレクトリに移動して下記コマンドを実行する。
$ php artisan make:model app直下のモデルファイルを作成したいディレクトリ名/モデルファイル名具体例
アプリ名ディレクトリ/app/Models
直下にTestというモデルファイルを作成したい時はアプリ名ディレクトリで下記コマンドを実行する。(Modelsディレクトリが存在しない時は自動で作成されてその中にモデルファイルが格納される)$ php artisan make:model Models/Testモデルファイルを移動してエラーが出た話
アプリ名ディレクトリ/app
直下にモデルファイルを作成後に手動でモデルファイルをアプリ名ディレクトリ/app/Models
に移動しただけだと下記の様なエラーが発生する可能性があるので注意する。
- 投稿日:2020-07-30T10:31:41+09:00
phpのフレームワークLaravelを触ってみた。(新規コントローラー作成編)
artisanの利用
ArtisanとはLaravelを構成しているコマンドラインインターフェイスの名前です。
ちなみに読み方は「アルチザン」。
使い方は、php artisan listで一覧を表示してくれます。$ php artisan list Laravel Framework 7.21.0 Usage: command [options] [arguments] Options: -h, --help Display this help message -q, --quiet Do not output any message -V, --version Display this application version --ansi Force ANSI output --no-ansi Disable ANSI output -n, --no-interaction Do not ask any interactive question --env[=ENV] The environment the command should run under -v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug ・ ・ ・ ・ ・ ・ ・ ・※長いので、一部記載。
コントローラの作成
次のコマンドを実行します。
$ php artisan make:controller SampleAppController Controller created successfully. ※これが表示されればちゃんと出来てます。
- 作成されるディレクトリは、こちら
(Laravelアプリディレクトリ)/app/Http/Controllersファイルの中身は、こんな感じです。
app/Http/ControllersSampleAppController.php<?php namespace App\Http\Controllers; use Illuminate\Http\Request; class SampleAppController extends Controller { // }下記の様にindex functionを追加します。
app/Http/ControllersSampleAppController.php<?php namespace App\Http\Controllers; use Illuminate\Http\Request; class SampleAppController extends Controller { //下記のメソッドを追加 public function index() { return view('sampleapp'); } }ルーティングの設定
(Laravelアプリディレクトリ)/routes/web.phpに下記のように追加します。
routes/web.php/* |-------------------------------------------------------------------------- | Web Routes |-------------------------------------------------------------------------- | | Here is where you can register web routes for your application. These | routes are loaded by the RouteServiceProvider within a group which | contains the "web" middleware group. Now create something great! | */ Route::get('/','SampleAppController@index');ビュー作成
(Laravelアプリディレクトリ)/resources/views/にsampleapp.blade.phpを作成します。
resources/views/にsampleapp.blade.php<html> <head> <title>Sample App</title> </head> <body> Sample App Viewです。 </body> </html>動作確認
http://localhost:8000/にアクセスして画面が表示される事を確認します。
- 投稿日:2020-07-30T09:18:11+09:00
PHP 文字化けしないCSVファイル作成
はじめに
色々なところで紹介されているものだと思いますが、
私の環境ではどうしても上手くいかなかった。。。
こんなところで詰まっている場合ではないのに。。。コピペに頼っているから悪い。一から自分で作るしかない!
思い立ち作ったらうまくいった~しかも簡単すぎ!!なんだかんだできたので記事にしてみたいと思います!
※初投稿なのでお手柔らかに。コード
「ファイル名」「データカラム」「データ本体」を渡すと決められたパス先にCSVを作成し、作成したCSVファイルのフルパスを返す関数。
/** * CSVファイルの作成 */ public function createCSV($fileName, $csvColumn, $csvBodyData){ //ファイルフルパス作成 $filePath = 'ファイルパス'.$fileName; //CSVファイル作成 $csvFile = fopen($filePath, 'w'); //CSVを開いても文字化けしないように stream_filter_prepend($csvFile,'convert.iconv.utf-8/cp932'); //カラムを書き込む $row = fputcsv($csvFile, $csvColumn); //データを書き込む foreach($csvBodyData as $csvBody){ fputcsv($csvFile, (array)$csvBody); } //ファイルフルパスを返却 return $filePath; }なんでこんな簡単だったのに悩んだのか。。。
最後に
やはりコードのコピペはダメですね~
理解が大事でそれが一番の近道だと思い知りました。もっと勉強せねば!!!
もっと良い方法あれば教えてください。
あと間違っていたらお願いします。
- 投稿日:2020-07-30T09:18:11+09:00
PHP Excelで文字化けしないCSVファイル作成
はじめに
色々なところで紹介されているものだと思いますが、
私の環境ではどうしても上手くいかなかった。。。
こんなところで詰まっている場合ではないのに。。。コピペに頼っているから悪い。一から自分で作るしかない!
作ったらうまくいった~しかも簡単すぎ!!なんだかんだできたので記事にしてみたいと思います!
※初投稿&PHP歴半年なのでお手柔らかに。コード
「ファイル名」「データカラム」「データ本体」を渡すと決められたパス先にCSVを作成し、作成したCSVファイルのフルパスを返す関数。
/** * CSVファイルの作成 */ public function createCSV($fileName, $csvColumn, $csvBodyData){ //ファイルフルパス作成 $filePath = 'ファイルパス'.$fileName; //CSVファイル作成 $csvFile = fopen($filePath, 'w'); //CSVを開いても文字化けしないように stream_filter_prepend($csvFile,'convert.iconv.utf-8/cp932'); //カラムを書き込む fputcsv($csvFile, $csvColumn); //データを書き込む foreach($csvBodyData as $csvBody){ fputcsv($csvFile, (array)$csvBody); } //ファイルフルパスを返却 return $filePath; }なんでこんな簡単だったのに悩んだのか。。。
最後に
やはりコードのコピペはダメですね~
理解が大事でそれが一番の近道だと思い知りました。もっと勉強せねば!!!
もっと良い方法あれば教えてください。
あと間違っていたらお願いします。
- 投稿日:2020-07-30T03:25:43+09:00
LaravelでFacadeを作ってSlackに通知してみた(Laravel6.xバージョン)
概要
前回の記事から約1年経って、Laravelのバージョンも上がったし、私の知識も少しだけ増えたので書き直してみました。
環境
Laravel:6.18.31
PHP:7.4.6SlackのWebhook URLを取得
SlackにメッセージをPOSTするためのWebhook URLを取得します。
Incoming Webhook を Slack に追加
アプリから取得する場合は、ワークスペースの「App」メニューから検索欄に“Incoming Webhook”と入力して検索してください。
ブラウザで取得する場合は、以下のURLにアクセスしてください。https://slack.com/apps/A0F7XDUAZ--incoming-webhook-
Slack に追加
ボタンをクリック- 通知するチャンネルを選択し、
Incoming Webhook インテグレーションの追加
ボタンをクリック- Webhook URLをコピーする
通知先のチャネルや投稿されるときの名前等は設定画面で登録しておくことができますが、通知するときに指定することもできます。
取得したURLは.envファイルに記載しておきます。
.envSLACK_URL=https://hooks.slack.com/services/XXXXXXXXX/XXXXXXXXX/xxxxxXXxxXxXXxxXXXXXxxまた、Slack 通知用の設定ファイルも用意しておきましょう。
app/config/slack.php<?php return [ // Webhook URL 'url' => env('SLACK_URL'), ];Slack 通知の準備
Slack 通知については公式ドキュメントに記載がありますのでそちらも参考にしてください
Slack 通知チャンネルのインストール
composer require laravel/slack-notification-channel通知クラスの作成
以下のコマンドで Slack 通知クラスを作成します。
php artisan make:notification SlackNotification
app/Notifications/SlackNotification.php
というファイルが作成されますので、Slack 通知用に変更していきます。
via
メソッドが返す配信チャンネルを slack に変更する- SlackMessage クラスのインスタンスを返す
toSlack
メソッドを追加するSlackMessage クラスの
content
メソッドでテキストメッセージを送信することができますが、attachment
メソッドで活用することでより詳細な情報をSlackに送ることができます。app/Notifications/SlackNotification.php<?php namespace App\Notifications; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Notifications\Notification; use Illuminate\Notifications\Messages\SlackMessage; use Illuminate\Notifications\Messages\SlackAttachment; class SlackNotification extends Notification { use Queueable; /** * 通知チャンネル情報 * * @var array */ protected $channel; /** * 通知メッセージ * * @var string */ protected $message; /** * 添付情報 * * @var array */ protected $attachment; /** * 通知インスタンスの作成 * * @return void */ public function __construct($channel = null, $message = null, $attachment = null) { $this->channel = $channel; $this->message = $message; $this->attachment = $attachment; } /** * 通知の配信チャンネルの取得 * * @param mixed $notifiable * @return array */ public function via($notifiable) { return ['slack']; } /** * Slack通知表現を返す * * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\SlackMessage */ public function toSlack($notifiable) { $message = (new SlackMessage) ->from($this->channel['username'], $this->channel['icon']) ->to($this->channel['channel']) ->content($this->message); if (!is_null($this->attachment) && is_array($this->attachment)) { $message->attachment(function ($attachment) { if (isset($this->attachment['title'])) { $attachment->title($this->attachment['title']); } if (isset($this->attachment['content'])) { $attachment->content($this->attachment['content']); } if (isset($this->attachment['field']) && is_array($this->attachment['field'])) { foreach($this->attachment['field'] as $k => $v) { $attachment->field($k, $v); } } }); } return $message; } }Slack通知ファサードの作成
設定ファイルにチャンネル情報を追加
app/config/slack.php<?php return [ // Webhook URL 'url' => env('SLACK_URL'), // チャンネル設定 'default' => 'work', 'channels' => [ 'work' => [ 'username' => '作業通知', 'icon' => ':face_with_rolling_eyes:', 'channel' => 'notice-work', ], 'error' => [ 'username' => 'エラー通知', 'icon' => ':scream:', 'channel' => 'notice-error', ], ], ];Slack通知サービスの作成
以下の処理を実行するためのサービスを作成します。
- Notifiableトレイトを利用する
- 通知先のURLを返す
routeNotificationForSlack
メソッドを追加する- 通知するチャンネルを指定する
channel
メソッドを追加するsend
メソッドで Slack 通知クラスのインスタンスを引数として$this->notify()
を呼び出すapp/Services/SlackService.php<?php namespace App\Services; use Illuminate\Notifications\Notifiable; use App\Notifications\SlackNotification; class SlackService { use Notifiable; /** * 通知チャンネル情報 * * @var array */ protected $channel = null; /** * 通知チャンネルを指定 * * @param array $channnel * @return this */ public function channel($channel) { $this->channel = $channel; return $this; } /** * 通知処理 * * @param string $message * @return void */ public function send($message = null) { if (!isset($this->channel)) { $this->channel(config('slack.channels.' . config('slack.default'))); } $this->notify(new SlackNotification($this->channel, $message)); } /** * Slack通知用URLを指定する * * @return string */ protected function routeNotificationForSlack() { return config('slack.url'); } }ファサードクラスの作成
app/Facades/Slack.php<?php namespace App\Facades\Slack; use Illuminate\Support\Facades\Facade; class Slack extends Facade { protected static function getFacadeAccessor() { return 'slack'; } }サービスプロバイダの作成
以下のコマンドでサービスプロバイダを作成します。
php artisan make:provider SlackServiceProvider
app/Providers/SlackServiceProvider.php
というファイルが作成されますので、register
メソッドにキーとサービスをバインドする初期を記述します。app/Providers/SlackServiceProvider.php<?php namespace App\Providers; use Illuminate\Support\ServiceProvider; class SlackServiceProvider extends ServiceProvider { /** * Register services. * * @return void */ public function register() { $this->app->bind( 'slack', 'App\Services\SlackService' ); } /** * Bootstrap services. * * @return void */ public function boot() { // } }サービスプロバイダとエイリアスを追記する
app/config/app.php'providers' => [ (省略) App\Providers\SlackServiceProvider::class, (省略) ], 'aliases' => [ (省略) 'Slack' => App\Facades\Slack::class, (省略) ],通知処理
以下のように記述すればシステム内のどこからでも Slack への通知が可能です。
// メッセージを送信 \Slack::send('Hello World!'); // チャンネルを指定して送信する場合 \Slack::channel('error')->send('Error!!');おまけ
Tinkerを使えば、画面やコンソールコマンドを用意しなくても動作が確認できます。
php artisan tinker Psy Shell v0.10.4 (PHP 7.4.6 ― cli) by Justin Hileman >>> \Slack::send('Hello World!'); => null >>> exit Exit: Goodbye詳しくはこちらをご確認ください。
サンプルソース