20210512のPHPに関する記事は15件です。

mb_send_mail(): Unsupported transfer encoding "7bit " - will be regarded as 8bit のエラー対応

先日、下記のサーバーエラーが出て困ったときの対応方法です。 実行環境: CentOS Stream release 8 Apache/2.4.37 PHP 7.4.16 エラー詳細: AH01071: Got error 'PHP message: PHP Warning: mb_send_mail(): Unsupported transfer encoding "7bit " - will be regarded as 8bit 対応方法: 色々確認していたら、メール処理でヘッダーに渡していたpostfixのバージョンがサーバー実機と違うことに気づきました [example@123-45-678-90]$ postconf | grep mail_version mail_version = 3.5.9 milter_macro_v = $mail_name $mail_version 上のコマンドで確認したバージョンに修正します。 // 【ユーザー宛】ヘッダーリスト $headers = [ 'MIME-Version' => '1.0', 'Content-Transfer-Encoding' => '7bit', "Content-Type" => $default_char_set, "Return-Path" => $from_mail, "From" => $from, "CC" => '', "Sender" => $from, "Reply-To" => $to_admin, "Organization" => $display_name, "X-Sender" => $to_admin, 'X-Mailer' => 'Postfix/3.5.9', 'X-Priority' => '3', ]; 上記で mb_send_mail() のエラーも解消しました。コードはやはり、他からコピーしてくるときは注意ですね。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Vagrant + Vitualboxで仮想環境を作る[Mac版]

インストールとBoxの取得 最初に仮想マシンを入れるフォルダを作っておきます。今回はtestCentosという名前で作成しました。 $ mkdir testCentos //仮想マシン用のフォルダ作成 $ cd testCentos //作成したフォルダに移動 Vagrant  https://www.vagrantup.com/downloadsと Virtualbox  https://www.virtualbox.org/ をそれぞれ公式サイトから ダウンロードし、表示されるままインストールを進めます。 vagrant -vとターミナルで打ち込んでVagrant 2.2.15等のバージョンが返ってくればインストールできています。 次にboxを取得します。boxは仮想マシンの雛形のようなものです。 boxのurlは http://www.vagrantbox.es/ からコピーできます。 $ vagrant box add [boxにつけたい名前] [boxのurl] 今回はCentOS 7.0 x64を使ったので $ vagrant box add centos https://github.com/tommy-muehle/puppet-vagrant-boxes/releases/download/1.1.0/centos-7.0-x86_64.box となります。 ==> box: Successfully added box 'centos' (v0) for 'virtualbox'! 成功すると上記の表示が出ます。 $ vagrant box list でboxが追加できてるか確認します。 最後にboxを初期化します。このときに仮想マシンの設定が記述されているVagrantfileが生成されます。 $ vagrant init centos //boxの名前 boxの取得をする前に起動させたり、初期化し忘れているとエラーが出るので注意。 起動と接続 $ vagrant up でvagrantを起動させます。 $ vagrant status で状態を確認し、runningであれば起動できています。 $ vagrant ssh でssh接続し、([Vagrant@localhost ~ ]と表示されてればログインは成功しています。 ApacheとPHPをインストール ここからwebサーバーにアクセスしてブラウザに表示させる為に、webサーバーであるapacheをインストールします。 $ sudo yum -y install httpd を打ちます。 Vagrant@localhost~の@より前の部分がVagrantになっていますが、これだと書き込みができない第三者的なものなので、このままインストールやらフォルダ作成をしようとすると権限がない!と怒られます。 なので先頭にsudoコマンドをつけます。 またはsudo suでrootユーザーに切り替えても同じようにインストールやら書き込みが出来るようになります。 元のユーザーに切り替えるときはsu [切り替えたいユーザー(今回だとvagrant)]で元に戻れます。 $ sudo service httpd start $ sudo systemctl enable httpd.service でサーバーを起動させます。ついでに常時起動するようにしておきます。 次に、ファイアウォールの切断 $ sudo systemctl stop firewalld $ sudo systemctl disable firewalld $ sudo systemctl status firewalld 切断できていれば Active: inactive (dead) と表示されます。 ホストOSとゲストOSとのフォルダ共有の為のプラグインをインストール $ vagrant plugin install vagrant-vbguest $ vagrant plugin list vagrant-vbguest (0.29.0, global)等が返ってくればインストールできています。 $ sudo yum install php PHPをインストール Is this ok [y/d/N]: y 途中これでいですか?と聞かれるのでyを選択。 php -vと打ってバージョン等の表示が返ってくればインストールできています。 ブラウザからページが表示されるか確認 今のままだとアクセスできないのでターミナルからVagrantfileの記述を変更します。 $ vi Vagrantfile  //Vagrantfileを編集 iキーを押してインサートモードに切り替えたら下記の箇所を変更。 # config.vm.network "private_network", ip: "192.168.33.10" //変更前 config.vm.network "private_network", ip: "192.168.33.10"    //変更後 先頭の#を消してコメントアウト状態から有効にします。 次にconfig.vm.synced_folderの設定を変えます。これはホストOSとゲストOSのフォルダを同期するものです。先頭の#を消して、config.vm.synced_folderの後ろにホストOSのパスとゲストOSのパスを指定します。 今回はVagrantfileと同じ階層にdataというフォルダをホスト側で作り、その中にファイルを入れていき、仮想環境上の/var/www/htmlと同期させています。 # config.vm.synced_folder "../data", "/vagrant_data"  //変更前 config.vm.synced_folder "./data", "/var/www/html"  //変更後 編集が終わったらescキー→:wq→enterで上書き保存します。 保存ができたらvagrant reloadで再起動させます。 最後にブラウザに表示する用にdataフォルダの中にindex.phpファイルを作成します。 index.php <?php phpinfo(); ?> 192.168.33.10のアドレスにアクセスして phpinfoが表示されていれば完了です。 使う必要がなくなったらexitでログアウトし、vagrant haltで電源を切って終了です。 最後に PHPの勉強をするにあたってVagrantとVirtualboxを使って仮想環境を作ったのですが、なかなか苦戦したので忘れないうちに備忘録としてまとめようと思いました。 修正などあればコメントでご教示いただけると嬉しいです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

docker+blackfire環境の構築(php)

blackfireとは パフォーマンスプロファイリングサービスです。 関数がどの経路で読み込んでいて、 どのくらい処理に時間がかかり、 どのくらいメモリを使用しているのか、 目視で確認できるので、アプリケーションのパフォーマンス向上などに使用します。 用意するもの docker(念の為最新にしておきましょう) blackfireのアカウント(ここから作れるよ!) chrome(拡張機能も使うので入れておく) 挫けない心 環境を構築していく docker-compose.yml blackfire: image: blackfire/blackfire ports: ["8707"] environment: BLACKFIRE_SERVER_ID: {サーバーキー} BLACKFIRE_SERVER_TOKEN: {サーバートークン} BLACKFIRE_CLIENT_ID: {クライアントキー} BLACKFIRE_CLIENT_TOKEN: {クライアントトークン} サーバーキー・トークン、クライアントキー・トークンは、blackfireのマイページから確認できます。 Dockerfile RUN version=$(php -r "echo PHP_MAJOR_VERSION.PHP_MINOR_VERSION;") \ && curl -A "Docker" -o /tmp/blackfire-probe.tar.gz -D - -L -s https://blackfire.io/api/v1/releases/probe/php/alpine/amd64/$version \ && mkdir -p /tmp/blackfire \ && tar zxpf /tmp/blackfire-probe.tar.gz -C /tmp/blackfire \ && mv /tmp/blackfire/blackfire-*.so $(php -r "echo ini_get ('extension_dir');")/blackfire.so \ && printf "extension=blackfire.so\nblackfire.agent_socket=tcp://blackfire:8707\n" > $PHP_INI_DIR/conf.d/blackfire.ini \ && rm -rf /tmp/blackfire /tmp/blackfire-probe.tar.gz 用意していたDockerfileに追記する形で問題ありません。 また、すでに構築ずみの環境でしたら、buildし直しましょう。 $ docker-compose buide --no-cache $ docker-compose up -d これで環境は問題なくできるはずです。 blackfileの使い方 計測したいページを開きます。(ローカル環境でも大丈夫です。) 拡張機能のblackfire profilerを起動し、profile!ボタンを元気よくクリックすれば計測してくれます。 結構待ちますが、終わったらView Call Graphをクリックで、ページ遷移し詳細がみれます。 使ってみた感想 当環境が、Laravelを使っています。 サービスプロバイダーやミドルウェア、ビジネスロジック、Collection操作などの見直しに便利だったなぁと思いました。 SQLチューニングも行ったのですが、blackfireはあくまでロジックの精査に使用し、SQLに関してはdebugbarなどで確認しました。 日々の開発の中でなかなか最高パフォーマンスを出しながら開発するのも難しいですが、気づいたらめっちゃ遅い!とかなると思うので、タイミング見てパフォーマンスを気にしながら進めるもの重要だなと実感しました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[AWS_13.1]php -vで「No such file or directory」のエラー

環境 MacBook Pro (13-inch, 2016, Four Thunderbolt 3 Ports) macOS 11.3.1(20E241) AWS EC2 t2.micro エラー # php -v -bash: /usr/bin/php: No such file or directory # which php /usr/bin/which: no php in (/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin) どうやら[AWS_13]でPHP既存の削除して、新しいバージョンのPHPを有効化したものの、新しいバージョンそのものはダウンロードできていなかったらしい。 PHPをダウンロードして、確認 # amazon-linux-extras install php7.4 (省略) # php -v PHP 7.4.15 (cli) (built: Feb 11 2021 17:53:39) ( NTS ) Copyright (c) The PHP Group Zend Engine v3.4.0, Copyright (c) Zend Technologies # which php /usr/bin/php
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[AWS_13]PHPのアップデート

環境 AWS EC2 t2.micro PHP 7.2.34 作業内容 PHPを 7.2→7.4へアップデート PHPのアップデート 1.EC2インスタンスへssh接続する ssh -i <秘密鍵ファイル> ec2-user@<パブリックIPアドレス> 2.管理者権限に遷移 sudo su - 3.既存のPHPを削除 yum remove php* 4.確認 # amazon-linux-extras list | grep php 15 php7.2=latest enabled \ 17 lamp-mariadb10.2-php7.2 available \ _ php7.3 available \ _ php7.4 available [ =stable ] _ php8.0 available [ =stable ] 5.既存のPHPをdisableにして、PHP7.4をenableにする。 amazon-linux-extras disable php7.2 amazon-linux-extras enable php7.4 6.確認 # amazon-linux-extras list | grep php _ php7.2 available \ _ lamp-mariadb10.2-php7.2 available \ _ php7.3 available \ 42 php7.4=latest enabled [ =stable ] _ php8.0 available [ =stable ] (追記) 1.PHPのインストールが抜けていたことが発覚し、インストールした。 https://qiita.com/yoshiki_mbp/private/cd39014bb22ea13a303b 2.モジュール等のインストールが漏れていたので、インストールした。 https://qiita.com/yoshiki_mbp/private/482610a32a69d6498914
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Laravel】ログイン時の追加処理

ログイン時に追加処理をするためのメモ。 前提 バージョン:Laravel6 LoginControlerの中身 LoginController.php <?php namespace App\Http\Controllers\Auth; use App\Http\Controllers\Controller; use App\Providers\RouteServiceProvider; use Illuminate\Foundation\Auth\AuthenticatesUsers; class LoginController extends Controller { /* |-------------------------------------------------------------------------- | Login Controller |-------------------------------------------------------------------------- | | This controller handles authenticating users for the application and | redirecting them to your home screen. The controller uses a trait | to conveniently provide its functionality to your applications. | */ use AuthenticatesUsers; /** * Where to redirect users after login. * * @var string */ protected $redirectTo = RouteServiceProvider::HOME; /** * Create a new controller instance. * * @return void */ public function __construct() { $this->middleware('guest')->except('logout'); } } デフォルトの状態ではログインコントローラーは上のようになっている。 今回重要なのはuse AuthenticatesUsers;。ログイン時の処理内容も本体はこのAuthenticatesUsersトレイトの中にある。 AuthenticatesUsersはvendor/laravel/framework/Illuminate/Foundation/Authの中にある。 AuthenticatesUsers.phpから抜粋 public function login(Request $request) { /* 割愛 */ if ($this->attemptLogin($request)) { return $this->sendLoginResponse($request); } /* 割愛 */ } protected function sendLoginResponse(Request $request) { /* 割愛 */ return $this->authenticated($request, $this->guard()->user()) ?: redirect()->intended($this->redirectPath()); } protected function authenticated(Request $request, $user) { // } AuthenticatesUsersの中を見るとloginではログインをする(attemptLogin)ときにsendloginResponseが呼び出されている。 さらにsendloginResponseではauthenticatedとredirect()...が三項演算子?:で比較されている。 つまり、authenticatedを実行してその返り値が存在しない、またはfalseの場合はredirect()...でログイン先のページへと移動する。 このauthenticatedは中身が空なのでLoginController側で上書きすればログイン実行時の処理を追加できる。 なお、$requestはログインフォームの入力値、$userはログインしたユーザーが入る。 返り値があればredirect()...は実行されないので、ユーザーごとにログイン先を変えるといった処理も可能。 注意点として、use Illuminate\Http\Request;も追記しないとLoginController側でRequestが呼び出だせずエラーになってしまう。 サンプル ログイン時の時間を記録する usersテーブルにlogin_atカラムを追加してユーザーごとにログインした時間を記録する。 ①マイグレーション add_login_at_to_users_table.php public function up() { Schema::table('users', function (Blueprint $table) { $table->dateTime('login_at')->nullable(); }); } public function down() { Schema::table('users', function (Blueprint $table) { $table->dropColumn('login_at'); }); } ②コントローラー LoginController.php <?php namespace App\Http\Controllers\Auth; use App\Http\Controllers\Controller; use App\Providers\RouteServiceProvider; use Illuminate\Foundation\Auth\AuthenticatesUsers; use Illuminate\Http\Request; // 追記 /* 割愛 */ protected function authenticated(Request $request, $user) { $user->login_at = now(); $user->save(); }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

あるヤミ金融業者から 10 万円の借金をしたまま、全く返済していない。この業者は、一週間ごとに 5% の利子を借金に加え、さらに借金の 1,000 円未満を切り上げる。 整数 n を入力し、n 週間後の借金の残高を出力せよ

・入力条件 整数 n (0 ≤ n ≤ 100) が1行に与えられる。 n 週間後の返済額を1行に出力する。 ・入力データ 5 ・予想結果 13000 ・補足 1週間毎に借金が増えるので、利息もあがる。 1,000 円未満は切り上げるので、1000001円であれば、残高は101000円となる。 <?php // Your code here! // 演習2 $n = (int)fgets(STDIN); //n週間後 $debt = 100000; //借金 $interest_rate = 5; //利率 // echo ceil($a); for($i=1;$i<=$n;++$i){ echo $i."週間目"."\n"."現在の借金:".$debt."\n"; // 借金と利率から利子を計算 $interest = $debt * ($interest_rate/100); echo '利子'.$interest."\n"; // 千円以下は切り上げ $interest = ceil($interest/1000) * 1000; echo '切り上げした利子'.$interest."\n"; $debt += $interest."\n"; echo $debt."\n"."\n"; } ?>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【php】あるヤミ金融業者から 10 万円の借金をしたまま、全く返済していない。この業者は、一週間ごとに 5% の利子を借金に加え、さらに借金の 1,000 円未満を切り上げる。 整数 n を入力し、n 週間後の借金の残高を出力せよ

・入力条件 整数 n (0 ≤ n ≤ 100) が1行に与えられる。 n 週間後の返済額を1行に出力する。 ・入力データ 5 ・予想結果 13000 ・補足 1週間毎に借金が増えるので、利息もあがる。 1,000 円未満は切り上げるので、1000001円であれば、残高は101000円となる。 <?php // Your code here! // 演習2 $n = (int)fgets(STDIN); //n週間後 $debt = 100000; //借金 $interest_rate = 5; //利率 // echo ceil($a); for($i=1;$i<=$n;++$i){ echo $i."週間目"."\n"."現在の借金:".$debt."\n"; // 借金と利率から利子を計算 $interest = $debt * ($interest_rate/100); echo '利子'.$interest."\n"; // 千円以下は切り上げ $interest = ceil($interest/1000) * 1000; echo '切り上げした利子'.$interest."\n"; $debt += $interest."\n"; echo $debt."\n"."\n"; } ?>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel6で日付ごとにログを出力する方法

Laravelでログを出力する方法とそれを日付ごとに出す方法です。 環境 PHP 7.4.10 Laravel Framework 6.18.40 ログ出力の方法 Log::debug('An informational message.'); 初期状態だと \storage\logs\laravel.log にログが出力されます。 ログを日付ごとに出す方法と設定 config\logging.phpを開く logging.php 'channels' => [ 'stack' => [ 'driver' => 'stack', 'channels' => ['single'], //このsingleの部分をdailyに 'ignore_exceptions' => false, ], single部分をdailyに変えると日付ごとにログが出力されるようになる。 dailyの設定を見てみる logging.php 'daily' => [ 'driver' => 'daily', 'path' => storage_path('logs/laravel.log'), //logの保存場所 'level' => 'debug', //logレベルの変更 'days' => 14, //保存日数 ], 設定を変えたいときはここから変えれる Laravel5.6以降のログの機能をちょっと調べた ファイルを分けて、エラーのみ出力するチャンネルを作成する方法 Laravelのログ出力をエラーログのみ出し分ける リクエストログやSQLログを出したいとき Laravel リクエストログを出力する Laravel SQLの実行クエリログを出力する
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

個人的におすすめしたいプログラムの技術サイト

プログラムを学ぶとき、良質なサイトを探すのにかなりの時間を浪費した。 他の人にはそうなってほしくないので、今まで役立ったサイトを公開する。 なお、強くオススメしたいサイト順に並ばせる。 随時更新予定。 JavaScript (Webで動きを付けたいときに使う有名なアレ) ・JavaSciptチートシート (まとまっていてわかりやすい)  https://jsprimer.net/cheatsheet/ ・JavaScriptの業務スキルレベル 判別表(この記事はだいぶ古いが今でも有用)  https://language-and-engineering.hatenablog.jp/entry/20100111/p1 ・MDNエラーリファレンス  https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Errors ・Excel VBAプログラマーのためのGoogle Apps Script入門  https://www.atmarkit.co.jp/ait/series/5004/ ・JavaScript Minifier(ブックマークレット作成にお世話になった)  https://javascript-minifier.com/ [electron] デスクトップアプリが作れる ・[Electron] 多言語対応する – i18n(jsonで多言語ファイル作ればいい!でもその具体的な方法は?と困ったときにお世話に。)  https://blog.katsubemakito.net/nodejs/electron/electron-i18n [Puppeteer] Web自動 ・Puppeteerで複数のURLはPromise.allで処理したほうが倍以上高速(Web自動化で遊ぶ。セレニウム?それは美味ですかな?)  https://iwb.jp/puppeteer-multiple-url-promise-all-several-times-faster/ [Next.js] Reactを使った自動ルーティングで今はやり ・Next.jsでGoogle Analyticsを使えるようにする  https://panda-program.com/posts/nextjs-google-analytics TypeScript (JavaScriptを型の制約を付けたもの。) ・仕事ですぐに使えるTypeScript(数あるDocの中でもかなり分かりやすいし詳しい。イチオシ)  https://future-architect.github.io/typescript-guide/index.html ・TypeScript Deep Dive 日本語版  https://typescript-jp.gitbook.io/deep-dive/ ・TypeScriptの型入門(食事をとりながらスマホで学習したいときに最適だった)  https://qiita.com/uhyo/items/e2fdef2d3236b9bfe74a#conditional-type%E3%81%AB%E3%82%88%E3%82%8Bdeepreadonlyt ・TypeScriptお試し(コンパイル後のコードはどうなっているのか。そういうのもみれる)  https://www.typescriptlang.org/ja/play?#code/IYGwpgTgLgFARACTCEB7ABAFQJ4AcwDKAxhAJa5RwCUA3EA HTML ・dCodes v2(サイト構築のための部品がいろいろ)  http://www.dcodes.net/2/docs/index.html ・HTML reference.io(各HTMLタグの詳細)  https://htmlreference.io/ C (ポインタで躓きたまえ…!そう囁くんだ…) ・苦しんで覚えるC言語(分かりやすい、面白い)  https://9cguide.appspot.com/index.html ・組込みの門(検索すると出てくるアレ)  https://www.uquest.co.jp/embedded/index.html#outline C# (Cと名前は似ているが互換性はない) ・C# によるプログラミング入門  https://ufcpp.net/study/csharp/ PHP (JavaScriptと構文が似ていてありがたい) ・PHPDoc リファレンス(JSでも使える良質なアノテーション記述法)  https://zonuexe.github.io/phpDocumentor2-ja/references/phpdoc/index.html Python ・note.nkmk.me  https://note.nkmk.me/python/ ・お気楽 Python3 プログラミング超入門  http://www.nct9.ne.jp/m_hiroi/light/pythonb02.html#abc09 ・PyQt5とpython3によるGUIプログラミング:実践編  https://qiita.com/kenasman/items/b9ca3beb25ecf87bfb06#qt-designer%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6 ・Python3チートシート(基本編)  https://qiita.com/1429takahiro/items/710a877b1afb1626334f#%E3%82%AF%E3%83%A9%E3%82%B9%E3%81%AE%E7%B6%99%E6%89%BF ・【機械学習初心者向け】scikit-learn「アルゴリズム・チートシート」の全手法を実装・解説してみた  https://qiita.com/sugulu_Ogawa_ISID/items/e3fc39f2e552f2355209 ・PyQ ドキュメント  https://docs.pyq.jp/index.html ・Python入門  https://www.python.ambitious-engineer.com/introduction-index ・Django(Python)でシステム開発できるようになる記事_入門編  https://qiita.com/Saku731/items/ed64190a12a4498b9446 ・【Pygame入門】ゲームプログラミング【Python】  https://algorithm.joho.info/programming/python/pygame/ Ruby (Railsが優秀過ぎてそればかり持ち上げられているやつ) ・Ruby on Rails チュートリアル 第4版(最新版は有料。)  https://railstutorial.jp/ PowerShell (バッチ処理楽しい) ・今から使う PowerShell  https://www.vwnet.jp/Windows/PowerShell/2018022301/GettingStartedWithPowerSehll-01.htm MarkDown (簡素な記述でHTMlが精製できちゃう凄いヤツ) ・UML超入門(趣味や遊びで読むにはかなりきつい)  http://objectclub.jp/technicaldoc/uml/umlintro1 git (version管理。ゲームのセーブ&ロードと思うと分かりやすい) ・git book(下手に探すよりこのサイト見たほうが理解が早い) *VS Codeなんかでは拡張機能でワンタッチでコマンドが自動実行できるため、いちいち覚える必要すら実はあまりなかったりする。  http://git-scm.com/book/ja/v2 ・【必須】Gitコミットの書き方・作法【prefix/emoji】(プレフィックスはわかりやすいよんb)  https://suwaru.tokyo/%E3%80%90%E5%BF%85%E9%A0%88%E3%80%91git%E3%82%B3%E3%83%9F%E3%83%83%E3%83%88%E3%81%AE%E6%9B%B8%E3%81%8D%E6%96%B9%E3%83%BB%E4%BD%9C%E6%B3%95%E3%80%90prefix-emoji%E3%80%91/ ・今日からはじめるGitHub ~ 初心者がGitをインストールして、プルリクできるようになるまでを解説  https://eh-career.com/engineerhub/entry/2017/01/31/110000#Git%E3%81%A7%E3%81%AF%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E3%81%A7%E9%96%8B%E7%99%BA%E3%82%92%E9%80%B2%E3%82%81%E3%82%8B%E3%81%93%E3%81%A8%E3%81%8C%E3%81%A7%E3%81%8D%E3%82%8B Adobe XD (Webサイトの試作品を作れるアレ。設計を先に決めてないと詰む系) ・Adobe XD でのデザイン、プロトタイプ、共有  https://helpx.adobe.com/jp/xd/user-guide.html/jp/xd/help/adobe-xd-overview.ug.html ・Adobe XDでWebデザインをしよう!画面作成からページ推移までの手順を紹介  https://www.webcreatorbox.com/inspiration/adobe-xd-steps ・Adobe XD でのアートボードの使用  https://helpx.adobe.com/jp/xd/user-guide.html/jp/xd/help/get-started-with-artboards-in-XD.ug.html Docker (お手軽仮想環境。win10ならver 2.5.0.1を使ったほうがエラーが出ない。今のところは。) ・【連載】世界一わかりみが深いコンテナ & Docker入門 〜 (詳しいが、話が難解)  https://tech-lab.sios.jp/archives/18811#i-3 *書籍 ・読まれない名著「人月の神話」を本気で読み込んでみた(まとめ)  https://www.gixo.jp/blog/4978/ プログラミング言語の歴史 ・プログラミング言語年表  https://ja.wikipedia.org/wiki/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E8%A8%80%E8%AA%9E%E5%B9%B4%E8%A1%A8
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【php】与えられた2つの整数 a と b の和の桁数を出力するプログラムを作成して下さい。

・入力条件 複数のデータセットが与えら、各データセットは 1 行に与えられる。 各データセットは2つの整数 a と b が1つのスペースで区切られて与えられる。 入力の終わりまで処理せよ。 ・0 ≤ a, b ≤ 1,000,000 ・データセットの数 ≤ 200 入力ファイル memo.txt 5 7 1 99 1000 999 予想出力結果 2 3 4 <?php $filename = 'memo.txt'; $num = 0; // fopenでファイルを開く('r'は読み込みモードで開く) $fp = fopen($filename, 'r'); while ($num < 3){ // fgetsでファイルを読み込み、変数に格納 $txt = fgets($fp); // explodeで半角空白で分割 $trim_txt = explode(' ',$txt); $trim_1 = $trim_txt[0]; $trim_2 = $trim_txt[1]; $trim_sum = $trim_1 + $trim_2; echo strlen($trim_sum)."\n"; // ファイルを読み込んだ変数を出力 $num += 1; } // fcloseでファイルを閉じる fclose($fp); ?>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS ec2 デプロイ laravel8 php8 mysql8

ほぼ受け売りです。 参考: 公式 LaravelをAWSのEC2へデプロイする手順 laravelをAWS EC2にデプロイする インバウンド HTTP (ポート 80) 接続をインスタンスに許可するセキュリティルールを追加していない場合には、ルールを追加する。 公式の最初のほうに書かれてあるのを参考に。 php8.0をインストール sudo amazon-linux-extras install -y php8.0 sudo yum install php-mbstring php-openssl php-xml unzip Apacheのインストール sudo yum install -y httpd 設定 wabサーバの起動 sudo service httpd start システムがブートするたびにapacheが起動するよう設定 sudo chkconfig httpd on 有効か確認 chkconfig --list httpd ウェブサーバーをテストします。ウェブブラウザで、インスタンスのパブリック DNS アドレス (またはパブリック IP アドレス) を入力します。 Apacheの初期画面が表示されれば成功です。 ec2-user アカウントがこのディレクトリで複数のファイルを操作することを許可するには、ディレクトリの所有権とアクセス許可を変更する必要があります。 ec2-userをapacheグループに追加 sudo usermod -a -G apache ec2-user いったんログアウトして、再度ログイン exit /var/www とそのコンテンツのグループ所有権を apache グループに変更 sudo chown -R ec2-user:apache /var/www グループに、/var/wwwの書き込み許可追加 sudo chmod 2775 /var/www /var/www とサブディレクトのディレクトリ許可を変更 find /var/www -type d -exec sudo chmod 2775 {} \; /var/www とサブディレクトリのファイル許可を変更 find /var/www -type f -exec sudo chmod 0664 {} \; MYSQL8インストール 既存でインストールされている邪魔者を削除 sudo yum remove mariadb-libs sudo rm -rf /var/lib/mysql リポジトリのインストール sudo rpm -ivh https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm MYSQLのインストール cd /usr/lib64 sudo ln libsasl2.so.3 libsasl2.so.2 sudo yum clean all sudo yum -y install mysql-community-server mysql-devel MYSQLの起動 sudo systemctl start mysqld.service sudo systemctl enable mysqld.service 初期パスワードに確認 sudo cat /var/log/mysqld.log | grep 'temporary password' パスワード変更 sudo mysql_secure_installation 再起動 sudo systemctl restart mysqld.service gitをインストール インストール sudo curl -sS https://getcomposer.org/installer | php パスを通す sudo mv composer.phar /usr/local/bin/composer composer自身のインストール curl -sS https://getcomposer.org/installer | php composerコマンドのパスを通す sudo mv composer.phar /usr/local/bin/composer パス確認(/usr/local/bin/composerと表示されればOK) which composer Laravelプロジェクトをgit clone sudo yum install git cd /var/www git clone [URL] Apacheの設定変更 http.confファイルのDocumentRootの変更 Laravelでは、プロジェクト内のpublicディレクトリをドキュメントルートに指定する必要がある sudo vi /etc/httpd/conf/httpd.conf キーボードで「i」を押して入力状態にする DocumentRoot "/var/www/html"の箇所をDocumentRoot "/var/www/プロジェクト名/public"に変更 http.confファイルに以下のDirectoryを追加(.htaccessの有効化) <Directory /var/www/プロジェクト名/public> AllowOverride All </Directory> Escキーを押して次のコマンドを入力(画面左下に入力中のコマンドが表示される) :wq Apacheの設定変更後は、再起動。 sudo service httpd restart パッケージのインストール cd /var/www/[プロジェクトのフォルダ名] composer.jsonファイルがない場合 composer init vendorディレクトリが生成される composer install Laravelプロジェクトの設定 sudo chmod -R 777 /var/www/[プロジェクト名]/storage sudo chmod -R 775 /var/www/[プロジェクト名]/bootstrap/cache config, routeのキャッシュクリア だいたいなんかエラー出たら、これ打っときゃ直る。 php artisan config:cache php artisan route:cache .envの設定 git cloneしたLaravelプロジェクトには.envファイルがないので、 composer insatallで作成された、.env.exampleを使用する cp .env.example .env vi .env APP_URL=http://IPアドレス ←サーバーのIPにする DB_CONNECTION=mysql DB_HOST=←RDSのエンドポイント DB_DATABASE=データベース名 DB_USERNAME=RDS作成時のユーザ名 DB_PASSWORD=設定したパスワード キーを作成し、キャッシュをクリアする php artisan key:generate php artisan config:clear 後は煮るなり焼くなり
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

backlogの更新をデスクトップ通知する by PHP

 backlogの更新を定期的に自動で取得してデスクトップ通知を行うことを目的としていますが、あまり有用な情報が見つからなかったので、まったく最良の方法とは限りません。また、C系やVB系の方が簡潔に実装できる可能性は高そうですが、専らPHPerなのでPHPで書くこともひとつの目的としています。  なお、余裕があればcron等の設定も実装してみたかったところですが、定期的なAPI取得について今回はWindowsのタスクスケジューラを利用します。 開発環境 Windows 10 Pro PHP 7.3.27 実装方法 デスクトップ通知を行う方法として以下の3つを提示します。 Google Chrome拡張機能「Distill Web Monitor」を使う デスクトップ通知処理を別言語で記述する Composerプラグイン「JoliNotif」を導入する(SnoreToast) おおざっぱな手順としては次のように実装していきます。 backlogのAPI設定を行う(キーを発行する) PHPのcURL関数でAPIからレスポンスを取得する 前回取得と比較する。(結果が同じなら通知しない) レスポンス(課題の追加、更新、コメント等)に応じて通知したい内容を編集する デスクトップ通知を行う処理に受け渡す(上記方法の2, 3番目) 作成したファイルをWindowsタスクスケジューラを利用して一定間隔で実行する Distill Web Monitorを利用する場合はタスクスケジューラではなくGoogle Chromeが定期実施を行うため、2以降の手順は不要になります。デメリットもあるので以下で説明します。 1. backlogのAPI設定を行う backlogのAPIについて、詳しくはbacklog APIとはを参照してください。 Backlog API とは 課題,Wiki,ファイルの追加や取得を始め、プロジェクトやユーザーの管理などブラウザ上のBacklogでできる操作の大部分をAPIから行うことができます。詳しくはAPI リストを参照してください。 また、Cross Origin Resource Sharing (CORS) によるブラウザ上でのAjaxを使用したクロスドメイン通信が可能です。 今回は最近の更新の取得APIを利用します。 これはトップページ(ダッシュボード)の「最近の更新」の内容にあたります。 https://xxxxx.backlog.com/api/v2/space/activities?apiKey=****** 「xxxxx」は自身が利用しているbacklogのURLで補完してください。  apiKeyの値についてはbacklogの自分のアイコンから『個人設定』を開き、サイドメニューの『API』からAPIの設定を行います。 なお、APIで取得される文字列はJSON形式です。 Distill Web MonitorでAPIを取得し、差異がある場合に通知する  Distill Web MonitorはGoogle Chrome拡張機能です。自分自身の責任で利用してください。  Distill Web Monitorは前回取得と差異があった場合にデスクトップ通知やメール送信を行ってくれます。特に難しい設定もないため、使いやすいというのがメリットでしょう。  ただ、この機能で取得したJSON文字列を編集できる方法がわかりませんでした。なので、JSON文字列がそのまま通知されてしまいます。  また、Chrome上で取得を実施するため、一時的に最小タブが開かれ、ブラウザ利用時は上部がちらつくのと、『閉じたタブを開く』の利用が困難になる等のデメリットがあります。 2. PHPのcURL関数でAPIからレスポンスを取得する cURLを利用するので、有効にしていない場合はphp.iniの設定を有効にします。 php.ini extension=curl cURLは外部サイトにアクセスして情報を取得するのに利用します。 API(URL)の内容を取得するには以下のように記述します。 backlog_activities.php //API $query_array = ['count'=>10, 'activityTypeId'=>[1,3]]; $http_build_query= http_build_query($query_array); define('API_URL', 'https://xxxxx.backlog.com/api/v2/space/activities?apiKey=******'.'&'.$http_build_query); function getApi($url) { //cURL start $ch = curl_init(); //オプション curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 実行結果を文字列で返す curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // サーバー証明書の検証を行わない //取得 $json = curl_exec($ch); //close curl_close($ch); return $json }  apiKey以外にクエリパラメータで取得内容を指定することが可能です。  countは取得件数、activityTypeIdは配列で、[1:課題の追加][3:課題へのコメント]等がされた場合の更新を取得します。通知したい内容の必要に応じて設定するのがベターでしょう。  その他詳細は最近の更新の取得APIを確認してください。Wikiやファイルの追加・更新のほか、Git関連、プルリクエスト、マイルストーン、ユーザの追加・脱退等の取得が可能です。 3. 前回取得と比較する  ここについてはあまりこだわりもないので、ファイルに保存して比較する形式をとります。 backlog_activities.php define('LOG_FOLDERPATH', __DIR__ . DIRECTORY_SEPARATOR . "log" . DIRECTORY_SEPARATOR); define('PRE_FILEPATH', LOG_FOLDERPATH . "pre.log"); function comparePreData($data) { // $data:今回情報 $pre_data = file_get_contents(PRE_FILEPATH); //前回情報を取得 file_put_contents(PRE_FILEPATH, $data); //今回情報を保持 return ($pre_data != $data); // 前回と同じであればfalse:処理終了 } 4. レスポンスに応じて通知したい内容を編集する 課題が追加・更新された場合はサマリ(summary)と課題の概要説明(description) 課題にコメントがされた場合はサマリ(summary)とコメント(comment->content) 前回取得から複数の通知がある場合は「xx件の通知があります」と通知する メンションされた場合にのみ通知する  といったように、内容によって通知したいものは異なります。このような設定を施したいのであれば、レスポンスのどこを見ればいいか知る必要があります。まとめて「新たな通知があります」等とするのであれば特に気にしなくても問題ありません。最近の更新の取得APIにもレスポンスボディの例は載ってますが、詳しくは説明されていないので、実際に取得してみてみるのが手っ取り早いと思います。  余談ですが、Visual Studio Codeを使っている場合、取得内容をjsonファイルとして保存して「ドキュメントのフォーマット (Shift + Alt + F)」が簡単にできます。  さて、私は次のように通知内容を指定することにしました。 前回取得情報にあたるまで更新情報をループ 更新種別ごとに処理をわける 自分あてのメンションがある場合は通知(未読に限る) それ以外はログに出力  レスポンスのnotificationsは課題追加の場合はdescriptionに、コメントの場合はcommentにメンションがあればその情報が取得できるようです。  たとえば、概要でAさんにメンションした課題に対して、Bさん宛てにメンションしたコメントを送信すると、Bさんの情報のみがnotificationsで取得されていました。これで判断するのが良いと思われます。 ソースコード backlog_activities.php define('MSG_TASK_MODIFY', '[%s] 課題[%s-%s]が%sされました。'); // 1,3,4 define('MSG_ADD_COMMENT', '[%s] 課題[%s-%s]にコメントされました。'); //2 define('MSG_WIKI_MODIFY', '[%s] プロジェクト[%s (%s)]のWikiページ[%s]が%sされました。'); //5,6,7 define('MSG_FILE_MODIFY', '[%s] プロジェクト[%s (%s)]の共有ファイル[%s%s]が%sされました。'); //8,9,10 function content() { // エンコード $data = json_decode($this->json); $pre_data = json_decode($this->pre_json); // 前回取得のidを配列に格納 $pre_ids = []; foreach ($pre_data as $info) { $pre_ids[] = $info->id; } $content = []; // 通知内容 $title = []; // 通知タイトル $callback = []; // コールバック $log = []; // ログ $typeName = [1=>'追加',2=>'更新',4=>'削除', 5=>'追加',6=>'更新',7=>'削除', 8=>'追加',9=>'更新',10=>'削除']; // 最新から順にループ for ($i=0;$i<count($data);$i++) { $info = $data[$i]; // 前回通知に存在したら処理終了 if (in_array($info->id, $pre_ids)) break; $type = $info->type; // 更新種別 $description = $info->content->description; // 概要 $projectKey = $info->project->projectKey; // プロジェクトキー $key_id = $info->content->key_id; // 課題ID $summary = $info->content->summary; // サマリ $projectName = $info->project->name; // プロジェクト名 $contentName = $info->content->name; // type=5,6,7の場合 Wikiページ名, type=8,9,10の場合 ファイル名 $contentDir = $info->content->dir; // type=8,9,10の場合 ファイルディレクトリ $comment = $info->content->comment->content; // type=3の場合 コメント内容 $createdTime = date("Y-m-d H:i:s", strtotime($info->created)); // 通知対象かどうか $isNotify = $this->isNotification($info); // 種別ごとに編集 switch ($type) { case 1: // 課題の追加 if ($isNotify) { $title[] = sprintf('[%s-$s]$s', $projectKey, $key_id, $summary); $content[] = $description; $callback[] = sprintf("start %s/view/%s-%s", BACKLOG_URL, $projectKey, $key_id); } case 2: // 課題の更新 case 4: // 課題の削除 $log[] = sprintf(MSG_TASK_MODIFY, $createdTime, $projectKey, $key_id, $typeName[$type]); break; case 3: // 課題のコメント $log[] = sprintf(MSG_ADD_COMMENT, $createdTime, $projectKey, $key_id); if ($isNotify) { $title[] = sprintf('[%s-$s]$s', $projectKey, $key_id, $summary); $content[] = $comment; $callback[] = sprintf("start %s/view/%s-%s", BACKLOG_URL, $projectKey, $key_id); } break; case 5: // Wikiを追加 case 6: // Wikiを更新 case 7: // Wikiを削除 $log[] = sprintf(MSG_WIKI_MODIFY, $createdTime, $projectName, $projectKey, $contentName, $typeName[$type]); break; case 8: // 共有ファイルを追加 case 9: // 共有ファイルを更新 case 10: // 共有ファイルを削除 $log[] = sprintf(MSG_FILE_MODIFY, $createdTime, $projectName, $projectKey, $contentDir, $contentName, $typeName[$type]); break; case 11: // Subversionコミット case 12: // GITプッシュ case 13: // GITリポジトリ作成 case 14: // 課題をまとめて更新 case 15: // ユーザーがプロジェクトに参加 case 16: // ユーザーがプロジェクトから脱退 case 17: // コメントにお知らせを追加 case 18: // プルリクエストの追加 case 19: // プルリクエストの更新 case 20: // プルリクエストにコメント case 21: // プルリクエストの削除 case 22: // マイルストーンの追加 case 23: // マイルストーンの更新 case 24: // マイルストーンの削除 case 25: // グループがプロジェクトに参加 case 26: // グループがプロジェクトから脱退 default: } } // 最新から取得されているので、逆順(日付が古い方から順)に出力 $this->log(array_reverse($log)); // 通知処理 if (count($content) > 1) { $this->notify("backlog", count($content)."件の更新があります。"); } else if (count($content) == 0) { $this->notify($title[0], $content[0], $callback[0]); } } /** * 通知対象かつ未読の場合true */ function isNotification($_info) { if (count($_info->notifications) == 0) return; foreach ($_info->notifications as $n) { $alreadyRead = $n->alreadyRead; // true:既読, false:未読 $userId = $n->user->userId; if ($userId == NOTIFICATION && $alreadyRead == false) return true; } return false; } function log($_text) { if (is_object($_text)) { ob_start(); var_dump($_text); $text = ob_get_contents(); ob_end_clean(); } else if (is_array($_text)) { foreach($_text as $log) { $this->log($log); } return; } else { $text = $_text; } if (!$text) return; $filename = LOG_FOLDERPATH . date("Ymd") . ".log"; $prelog = file_get_contents($filename); file_put_contents($filename, $text. "\r\n". $prelog); // ログは上方向に更新する } JSONデータに対する単なる編集内容なので省略しますが、必要な方だけ開いてみてください。 ソースコード内のnotifyはデスクトップ通知を行う関数ですが、次で説明します。 5. デスクトップ通知を行う処理に受け渡す  さて、デスクトップ通知の実装ですが、結論から言うとPHPではできません。 あるいは、私が方法を知らない、見つけていないだけかもしれません。知っている方がいたら教えてほしいです。 なので、別で実装してそのファイルを呼び出すことになります。  「JoliNotif」についても結局のところはSnoreToastという通知アプリを利用しているようなので、やっていることは本質的には同じです。What is snoretoast? ①PowerShellで実装する デスクトップ通知に関する処理は知らないので、有識者の力を借りることにする。 検索したところ、PowerShellで実装する方法があったのでこれを参照する。 この記事ではコールバックも実装してくれているので、通知をクリックしてそのままbacklogの課題ページを開きたい人は、これを実装するのがいいかもしれません。 ソースコードは何も変えずに利用しますが、参考記事が消えても困るので記載しておきます。 ソースコード notify.ps1 param( [string]$Prompt = 'メッセージ', [string]$Title = '通知', $CallBack = '' ) Add-Type -AssemblyName System.Windows.Forms, System.Drawing function Show-NotifyIcon { param( [string]$Prompt = 'メッセージ', [string]$Title = '通知', [scriptblock]$CallBack = {} ) [Windows.Forms.NotifyIcon]$notifyIcon = New-Object -TypeName Windows.Forms.NotifyIcon -Property @{ BalloonTipIcon = [Windows.Forms.ToolTipIcon]::Info BalloonTipText = $Prompt BalloonTipTitle = $Title Icon = [Drawing.SystemIcons]::Information Text = $Title Visible = $true } # イベント定義 $notifyIcon.add_BalloonTipClicked( $CallBack ) [int]$timeout = 3 # sec [DateTimeOffset]$finishTime = [DateTimeOffset]::UtcNow.AddSeconds( $timeout ) $notifyIcon.ShowBalloonTip( $timeout ) # そのままだとイベントが走らない&すぐに消えてしまうので適当wait while ( [DateTimeOffset]::UtcNow -lt $finishTime ) { Start-Sleep -Milliseconds 1 } $notifyIcon.Dispose() } $parameters = $MyInvocation.BoundParameters $parameters.CallBack = [scriptblock]::Create( $CallBack ) Show-NotifyIcon @parameters phpからps1ファイルを引数付きで呼び出すにはshell_execで、以下のように記述します。 backlog_activities.php function notify($body, $title, $callback='') { $body = "通知内容"; $title = "通知タイトル"; $callback = "start https://qiita.com/"; shell_exec("powershell.exe Set-ExecutionPolicy -ExecutionPolicy Unrestricted"); // 念のため $script = sprintf('powershell.exe -FILE %s "%s" "%s" "%s"', NOTIFY_FILEPATH, $body, $title, $callback); shell_exec($script); } ②JoliNotifを導入する どうしてもPHPでやってる感が欲しい人向け。 こちらはコールバックができない(やり方がわからない)ので、単純に通知するだけになります。 SnoreToastというアプリを使っているようなので、①のようにshell_execで直接実行しても問題はないように思えますが、割愛します。 手順1. Composer をインストールする 手順2. JoliNotifをいれる composer require "jolicode/jolinotif" 手順3. 実装 backlog_activities.php include __DIR__.'/vendor/autoload.php'; use Joli\JoliNotif\NotifierFactory; use Joli\JoliNotif\Notification; function notify($body, $title) { $body = "通知内容"; $title = "通知タイトル"; $callback = "https://qiita.com/"; $this->notifier = NotifierFactory::create(); $notification = (new Notification()) ->setBody($body) ->setTitle($title) ->setIcon(__DIR__.'/icon.png'); // アイコン ->addOption('url', $callback) // Windowsでは効かないっぽい ; $this->notifier->send($notification); } 6. Windowsタスクスケジューラを設定する  タスクスケジューラに上記ファイルを数分ごとに実行させれば完成ですが、スケジューラからphp.exeを実行させたところ、コマンドプロンプト画面がちらつく現象が発生。  php-win.exeならバックグラウンドでやってくれる・・・と公式にも書いているのですが、何故かうまくいかず。私の設定方法がわるいのかもしれませんが。  とりあえず、次の方法で回避することにしました。 baclog_activities.vbs Set ws = CreateObject("Wscript.Shell") ws.run "php C:\workspace\batch\backlog_activities.php", 0 2行目の最後に記述されている 0 というパラメータは、ウィンドウを非表示にするという設定です。 あとはタスクスケジューラを設定するだけです。 「コントロールパネル」から「管理ツール」を開きます。 「タスク スケジューラ」を開きます。 「操作」の「タスクの作成...」をクリックします。 「全般」の「名前」は任意で設定します。 「トリガー」タブで、実行間隔を好きなように設定してください。 「操作」タブで、「wscript.exe 実行ファイルパス」を設定します。 (画像では1分間になってますが、手動入力で試したところ、最低値の5分で実行されました) これで設定は完了です。 実装結果 最終的に実装した内容を記載しておきます。 ソースコード backlog_activities.php <?php include __DIR__.'/vendor/autoload.php'; use Joli\JoliNotif\NotifierFactory; use Joli\JoliNotif\Notification; define('BACKLOG_URL', "https://******.backlog.com/"); define('API_KEY', "**********************************"); // $http_query = ['count'=>10, 'activityTypeId'=>[1,3]]; $http_query = ['count'=>100]; $http_build_query = http_build_query($http_query); define('API_URL', BACKLOG_URL."api/v2/space/activities?apiKey=".API_KEY."&".$http_build_query); define('LOG_FOLDERPATH', __DIR__ . DIRECTORY_SEPARATOR . "log" . DIRECTORY_SEPARATOR); define('PRE_FILEPATH', LOG_FOLDERPATH . "pre.log"); define('NOTIFY_FILEPATH', __DIR__ . DIRECTORY_SEPARATOR . "notify.ps1"); define('NOTIFICATION', 'xxxxxxxx'); // 通知対象のuserId 個人設定のURLを参照 // https://******.backlog.com/user/xxxxxxxx ←この部分 define('MSG_TASK_MODIFY', '[%s] 課題[%s-%s]が%sされました。'); // 1,3,4 define('MSG_ADD_COMMENT', '[%s] 課題[%s-%s]にコメントされました。'); //2 define('MSG_WIKI_MODIFY', '[%s] プロジェクト[%s (%s)]のWikiページ[%s]が%sされました。'); //5,6,7 define('MSG_FILE_MODIFY', '[%s] プロジェクト[%s (%s)]の共有ファイル[%s%s]が%sされました。'); //8,9,10 class notify { public $notifier; public $json; // APIから取得したJSONデータ public $pre_json; // APIから取得したJSONデータ public $date; // 処理時刻 public function execute() { date_default_timezone_set('Asia/Tokyo'); $this->date = date("Y-m-d H:i:s"); $this->getApi(); if ($this->comparePreData()) { $this->content(); } } /** * ログ出力 */ function log($_text) { if (is_object($_text)) { ob_start(); var_dump($_text); $text = ob_get_contents(); ob_end_clean(); } else if (is_array($_text)) { foreach($_text as $log) { $this->log($log); } return; } else { $text = $_text; } if (!$text) return; $filename = LOG_FOLDERPATH . date("Ymd") . ".log"; $prelog = file_get_contents($filename); file_put_contents($filename, $text. "\r\n". $prelog); // ログは上方向に更新する } /** * デスクトップ通知 */ function notify($_title, $_body, $_callback='') { $body = str_replace(array("\r\n", "\r", "\n", " "), " ",$_body); $title = str_replace(array("\r\n", "\r", "\n", " "), " ",$_title); $script = sprintf('powershell.exe -FILE %s "%s" "%s" "%s"', NOTIFY_FILEPATH, $body, $title, $_callback); return; // JoliNotifでの実装 $this->notifier = NotifierFactory::create(); $notification = (new Notification()) ->setBody($body) ->setTitle($title) ->setIcon(__DIR__.DIRECTORY_SEPARATOR.'backlog-favicon.png'); // ->addOption('url', 'https://google.com') // Windowsでは効かない ; $this->notifier->send($notification); } /** * get api */ function getApi() { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, API_URL); // 取得するURLを指定 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 実行結果を文字列で返す curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // サーバー証明書の検証を行わない $this->json = curl_exec($ch); curl_close($ch); } /** * 前回データと比較 */ function comparePreData() { $this->preJson = file_get_contents(PRE_FILEPATH); //前回情報を取得 file_put_contents(PRE_FILEPATH, $this->json); //今回情報を保持 // 前回通知と同じであれば処理終了 if ($this->preJson == $this->json) { $this->log("[".$this->date."] 通知取得実行"); return false; } return true; } /** * 更新内容を確認 */ function content() { // エンコード $data = json_decode($this->json); $pre_data = json_decode($this->pre_json); // 前回取得のidを配列に格納 $pre_ids = []; foreach ($pre_data as $info) { $pre_ids[] = $info->id; } $content = []; // 通知内容 $title = []; // 通知タイトル $callback = []; // コールバック $log = []; // ログ $typeName = [1=>'追加',2=>'更新',4=>'削除', 5=>'追加',6=>'更新',7=>'削除', 8=>'追加',9=>'更新',10=>'削除']; // 最新から順にループ for ($i=0;$i<count($data);$i++) { $info = $data[$i]; // 前回通知に存在したら処理終了 if (in_array($info->id, $pre_ids)) break; $type = $info->type; // 更新種別 $description = $info->content->description; // 概要 $projectKey = $info->project->projectKey; // プロジェクトキー $key_id = $info->content->key_id; // 課題ID $summary = $info->content->summary; // サマリ $projectName = $info->project->name; // プロジェクト名 $contentName = $info->content->name; // type=5,6,7の場合 Wikiページ名, type=8,9,10の場合 ファイル名 $contentDir = $info->content->dir; // type=8,9,10の場合 ファイルディレクトリ $comment = $info->content->comment->content; // type=3の場合 コメント内容 $createdTime = date("Y-m-d H:i:s", strtotime($info->created)); // 通知対象かどうか $isNotify = $this->isNotification($info); // 種別ごとに編集 switch ($type) { case 1: // 課題の追加 if ($isNotify) { $title[] = sprintf('[%s-$s]$s', $projectKey, $key_id, $summary); $content[] = $description; $callback[] = sprintf("start %s/view/%s-%s", BACKLOG_URL, $projectKey, $key_id); } case 2: // 課題の更新 case 4: // 課題の削除 $log[] = sprintf(MSG_TASK_MODIFY, $createdTime, $projectKey, $key_id, $typeName[$type]); break; case 3: // 課題のコメント $log[] = sprintf(MSG_ADD_COMMENT, $createdTime, $projectKey, $key_id); if ($isNotify) { $title[] = sprintf('[%s-$s]$s', $projectKey, $key_id, $summary); $content[] = $comment; $callback[] = sprintf("start %s/view/%s-%s", BACKLOG_URL, $projectKey, $key_id); } break; case 5: // Wikiを追加 case 6: // Wikiを更新 case 7: // Wikiを削除 $log[] = sprintf(MSG_WIKI_MODIFY, $createdTime, $projectName, $projectKey, $contentName, $typeName[$type]); break; case 8: // 共有ファイルを追加 case 9: // 共有ファイルを更新 case 10: // 共有ファイルを削除 $log[] = sprintf(MSG_FILE_MODIFY, $createdTime, $projectName, $projectKey, $contentDir, $contentName, $typeName[$type]); break; case 11: // Subversionコミット case 12: // GITプッシュ case 13: // GITリポジトリ作成 case 14: // 課題をまとめて更新 case 15: // ユーザーがプロジェクトに参加 case 16: // ユーザーがプロジェクトから脱退 case 17: // コメントにお知らせを追加 case 18: // プルリクエストの追加 case 19: // プルリクエストの更新 case 20: // プルリクエストにコメント case 21: // プルリクエストの削除 case 22: // マイルストーンの追加 case 23: // マイルストーンの更新 case 24: // マイルストーンの削除 case 25: // グループがプロジェクトに参加 case 26: // グループがプロジェクトから脱退 default: } } // 最新から取得されているので、逆順(日付が古い方から順)に出力 $this->log(array_reverse($log)); // 通知処理 if (count($content) > 1) { $this->notify("backlog", count($content)."件の更新があります。"); } else if (count($content) == 0) { $this->notify($title[0], $content[0], $callback[0]); } } /** * 通知対象かつ未読の場合true */ function isNotification($_info) { if (count($_info->notifications) == 0) return; foreach ($_info->notifications as $n) { $alreadyRead = $n->alreadyRead; // true:既読, false:未読 $userId = $n->user->userId; if ($userId == NOTIFICATION && $alreadyRead == false) return true; } return false; } } $notify = new notify(); $notify->execute(); exit; 蛇足 backlogの更新をデスクトップ通知に送るだけですが、割とややこしいことをしている自覚はあります。 もっと簡潔にやる方法は存在している気もしますが、PHPでやりたかったのでご愛嬌ということで。 なお、本記事はQiitaにおける筆者の初投稿になります。 Qiita利用のガイドラインに即してない面等ありましたらご指摘願います。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel6.x Authの導入

Laravel5.8まではLaravelインストール後にphp artisan make:authコマンドを実行するだけでログイン機能を実装することができていたが,6.xからは実装の手順が変わってしまいました。 実装環境 PHP 7.3 Laravel 6.20.26 1. laravel/uiをインストールする Laravel6.xからはlaravel/uiとゆう別のパッケージで管理されるよいうになった。上記コマンドを実行してlaravel/uiをインストールする。 composer require laravel/ui "^1.0" --dev インストールが完了したらuiArtisanコマンドが使用することができる。 2. フロントエンドのスカフォールドをインストールする php artisan ui bootstrap --auth --authオプションをつけることでログイン/ユーザー登録スカフォールドも生成される。他にも php artisan ui vue --authやphp artisan ui react --autuなどもある。 3.Node.js インストール Laravelはフロント開発がしやすいようにLaravel Mixとゆう機能がある。Larave Mixを使用するためにはNodeをインストールしておく必要がある。 sudo yum install nodejs //node.jsのインストール node -v //バージョンが表示されたらインストールできている v10.23.1 sudo yum install npm //npmのインストール npm -v 6.14.10 npmについて npmとはNode.jsで書かれたパッケージを管理、インストールしたりするツール。 Laravel Mixを使用するのにこおnpmが必要になる。 依存パケージをインストール npm install インストールしたパッケージをビルドする。 npm run dev 本番環境の場合 npm run production 4. Authの導入 下記のコマンドを実行すると新規登録、ログイン機能が追加される。 php artisan ui bootstrap --auth
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

phpでTrying to access array offset on value of type null エラーと軽めの対処法

dev環境では起きず、手元のローカル環境でのみ起きていた事象。 phpのバージョンにより発生するもので、mampでphp7.3環境では起きず、7.4では発生しておりました。 エラー名で原因はすぐ見つかりましたが、直し方どうするかな〜とちょっと迷いました。 ◼️原因 特定の変数のデータを取得しようとした際に、 その変数の中身が入っていないにもかかわらずデータをとろうとすると、 7.3以前では nullを返し、 7.4以降では タイトルのエラーが出てしまう状態でした。 //発生の例 $test; //test変数を作成 if($test["hoge"] == "huge"){ //そもそも$testには何も入れていない状態 echo $test["hoge"]; } この場合、タイトルのエラー ◼️Trying to access array offset on value of type null が画面に表示します。 この場合、まずは$testにデータが存在しているかを判定すると良いです。 $test; //test変数を作成 if(isset($test)){ //ここでまず$testにデータが入っているかを判定 if($test["hoge"] == "huge"){ //そもそも$testには何も入れていない状態。なので echo $test["hoge"]; //ここは通りません。 } } ただ、これだとちょっとネストで読みづらいので下記の方法の方がわかりやすいです。 //例 $test; //test変数を作成 if(isset($test) && $test["hoge"] == "huge"){ echo $test["hoge"]; } phpの&&の複数条件式は左側から評価をし、falseとなった時点でその式を抜けます。 この例なら「isset($test)」の時点でfalseなので、次へ進むということになります。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む