- 投稿日:2020-07-08T23:46:14+09:00
【Laravel】PHPテンプレートの利用
書籍のアウトプットとして
ビューについて
本格的なWEBページをHTMLを使って表示内容を記述できる仕組みが必要。
このために用意されているのが「テンプレート」
テンプレートはLaravelのビュー(View)を担当している。
MVCのに基づいたビューは画面表示関連をわかりやすい形で作れるように成なる。アドレスにアクセスし、コントローラはテンプレートを読み込んで表示するが、ただ単にHTMLコードを表示しているわけではない。
レンダリングの考え方
レンダリングとはLaravelがテンプレートを読み込んで情報をはめ込む作業のこと。
Laravelでは以下の2つのテンプレートが用意されている。
手法 説明 PHPのソースコードをそのまま使用する方法 Blade Laravel独自 PHPテンプレートを作る
ここからは実際にテンプレートを作ってみる。
テンプレートの作成
以下の手順で作成。
1. テンプレートファイルをresourcesフォルダ内のviews度言うフォルダの中に作成
2. helloフォルダを作成
3. helloフォルダにindex.phpを作成index.php<html lang="ja"> <head> <meta charset="utf-8"> <title>Hello/Index</title> <style> </style> </head> <body> <h1>Index</h1> <p>this is a sample page with php-template.</p> </body> </html>
2
に関して、テンプレートは各コントローラごとにフォルダを用意し、その中にコントローラで使うテンプレートをまとめておくのが一般。ルートの設定でテンプレートを表示
web.phpに追記
web.phpRoute::get('hello', function () { return view('hello.index'); });その後/helloにアクセスすると画面が表示される。
viewメソッドについて
web.phpでは第2引数のクロージャでviewというメソッドを使用している。
viewは引数にテンプレート名を指定すると、そのテンプレートを読み込んで返す。view('フォルダ名.ファイル名')ここで単に
view('hello')
とすると、viewsフォルダからhelloろ言うファイルを探してしまう。ここでviewは「テンプレートを読み込んでその内容を返す」というわけはない
viewが返すのはテンプレートのレンダリング結果がコンテンツとして設定されているResponseインスタンス。
結果として「テンプレートを読み込んでその内容を返す」用に見えるだけで実際はそのような動きではないことに注意。コントローラでテンプレートを使う
先のルート情報のクロージャで使ったviewをそのままアクションメソッド内で利用するだけ。
HelloControllweクラスのIndexメソッドを修正
public function index() { return view('hello.index'); }ルート情報を修正
web.phpRoute::get('hello', 'HelloController@index');/helloにアクセスると同じ結果になる。
Route::getでviewするか
Route::getで呼び出されたアクションメソッドでviewするかの違い値をテンプレートに渡す
index.phpを修正
index.php<body> <h1>Index</h1> <p><?= $msg;?></p> <p><?= date("Y年n月j日");?></p> </body>index.phpテンプレートはPHPスクリプトであるため、PHPが記述できる。
$msg
に値を渡すためにHelloControllerクラスを修正public function index() { $data=['msg'=>'これはコントローラから渡されたメッセージ']; return view('hello.index',$data); }/helloにアクセスすると値が渡されていることがわかる。
テンプレへの値の受け渡し
先の例ではindexメソッドのviewメソッドを呼び出している。
viewの呼び出しは以下のようにする。return view(テンプレ,配列)第2引数には**配列(連想配列)**が渡されている。
今回は
['msg'=>'これはコントローラから渡されたメッセージ']
を渡した。
これは配列の値(これはコントローラから渡されたメッセージ)がキー(msg)という名前の変数としてテンプレで用意される。
このようにviewの第2引数では配列を渡すと、キーが変数名、値がその変数の値となって渡される。ルートパラメ-タをテンプレに渡す
アクセス時にアドレスに記載した値がそのままテンプレへ表示させるにはどうするか。
これには2つの切り分けをする
- ルートパラメータを受け取る部分
- 値をテンプレに書き出す部分ルートパラメータを受けるにはアクション引数に仮引数を用意し、Route::getでアドレスにパラメータを追記すればいいのだった。
あとはこれをテンプレに渡して表示するだけ。
実際にやってみる。index.php<body> <h1>Index</h1> <p><?=$msg;?></p> <p>ID=<?=$id;?></p>indexメソッドを書き換える
public function index($id='zero') { $data=[ 'msg'=>'これはコントローラから渡されたメッセージ', 'id'=>$id ]; return view('hello.index',$data); }web.phpRoute::get('hello/{id?}', 'HelloController@index');これで/hello/userとアクセスすると、ルートパラメータの値が表示されていることが確認できる。
クエリ文字列の利用
アクセスするアドレスの情報を利用して値を渡す方法のもう一つの方法として、「クエリ文字列」を用いる事ができる。
クエリ文字列はルートパラメ-とは受け取り方が違う。
indexメソッドを書き換える。
public function index(Request $request) { $data=[ 'msg'=>'これはコントローラから渡されたメッセージ', 'id'=>$request->id ]; return view('hello.index',$data); }ここであRequestインスタンスを渡している。渡す値は
$request->$id
のようにして引き渡している。web.phpRoute::get('hello', 'HelloController@index');web.phpはこのように書き換えるが{$id?}が消えている。
ごく一般的なルート情報の記述に戻っている。
そして以下のようにアクセスすると正しく受け取れている。
/hello/?id=sample
ここで?id=sampleのようにしてidというキーにsampleという値をわつぃている。このようにクエリ文字列を使って渡された値は$request->キー名で取り出せる。
キー名とは/hello/?○=sample
の○
のところBladeテンプレ
laravelは独自のBladeテンプレがある。この記述法を書いていく。
Bladeを使う
PHPスクリプトをそのまま使うのは以下のデメリットが有る
- ちょっと書くだけでいいのに
<?php print ○○;?>
と書かなければならない- PHPは<>で表示されHTMLを同じ形式で書くがこれが、HTML作成ツールなどで構造が崩れてしまう事がある。
- ページを分割してレイアウトする機能がない
- すべてHTMLとPHPで手作業でレイアウトするしかない
Bladeはいくつかの機能を持っている。
- テンプレを継承して新たなテンプレを作る。
- レイアウトの一部をセクションとしてはめ込むことでレイアウトが作れる。
テンプレを作る
Bladeのテンプレもresourcesのviewsフォルダの中に作成する。
Bladeテンプレファイルは〇〇.blade.php
という名前にする。
ここではindex.blade.php
という名前で作成する。
では記述していくindex.blade.php<html lang="ja"> <head> <meta charset="utf-8"> <title>Hello/Index</title> <style> body{font-size:16pt;color:#999;} h1{ font-size: 50pt;text-align: right;color:#f6f6f6;margin:-20px 0px -30px 0px;letter-spacing: -4pt; } </style> </head> <body> <h1>Blade/Index</h1> <p>{{$msg}}</p> </body> </html>ポイントは
{{$msg}}
と書いているところ。
Bladeでは{{変数}}
のようにしてテンプレに埋め込む。アクションの修正
次にコントローラのアクションメソッドを修正していく
public function index() { $data=[ 'msg'=>'これはコントローラから渡されたメッセージ' ]; return view('hello.index',$data); }アクションメソッドは変わらない。
web.phpはこのように。web.phpRoute::get('hello', 'HelloController@index');/helloにアクセスすると正しく表示できている。
index.php
とindex.blade.php
今回アクションメソッドで
view('hello.index',...
としているのindex.blade.php
のほうが実行されている。
LaravelではBladeテンプレがあるとそれが優先して読み込まれる。フォームを利用する
フォームを利用してみる
以下のように修正する。index.blade.php<body> <h1>Blade/Index</h1> <p>{{$msg}}</p> <form action="/hello" method="post"> @csrf <input type="text" name="msg"> <input type="submit"> </form> </body>ポイントはこれ
@csrfBladeディレクティブといい、テンプレに決まったコードを生成して書き出す。
CSRF対策について
@csrfはCSRF対策のためのBladeディレクティブ。
CSRFはスクリプトなどから外部からフォームを送信するもので、フォームに大量のコンテンツを送りつけりする。
@csrfはトークンというランダムな非表示フィールドとして追加する。
このトークン値が正しいフォームだけを受け入れるようにする。
こうすることで正しいフォームからの送信かどうかを見分けることができる。LaravelではCSRF対策がなされていないフォームの送信は例外が発生して受付けられないようになっている。
そのため、フォームを利用するときは必ず@csrfをフォームに用意しておく必要がある。アクションの用意
コントローラアクションを用意する。
ここでは2つの処理を書いていく
- /helloへアクセスしたとき
- フォームを送信したとき
以下のように修正する。
public function index() { $data=[ 'msg'=>'名前を入力' ]; return view('hello.index', $data); } public function post(Request $request) { $msg=$request->msg; $data=[ 'msg'=>'あなたは'.$msg.'です。' ]; return view('hello.index', $data); }indexメソッドは/helloにアクセスしたときの処理。
postメソッドはフォームを送信したときの処理
ここでRequestインスタンスを引数に渡してフォームの内容を取得している。$msg=$request->msg;フォームのところに
name="msg"
と指定したのは
$msg=$request->msg;
で取得するため。フォームで送信された値はすべてnameプロパティとして取り出せる。
POSTのルート設定
ルート情報を追記する
web.phpRoute::post('hello', 'HelloController@post');POST送信はRoute::postを設定する。使い方はROoute::getと同じ。
同じアドレスでもPOST,GETのようにアクセスするメソッドが違えば両方ともに使える。
- 投稿日:2020-07-08T23:24:59+09:00
[PHP]パッケージ管理ツールComposerを図で理解する
概要
PHPのパッケージ管理ツールComposerについて図を用いてまとめました。
Composerは既にインストールしている前提で説明します。Composerとは?
PHPのパッケージ管理ツールです。
パッケージ管理ツールとは?
プロジェクトが必要とするライブラリやパッケージを、依存関係を考慮した上で管理してくれるツールです。
依存関係とは?
ライブラリやパッケージには依存関係があります。
例えば以下のようなものです。
(1) ライブラリAを使いたい場合、ライブラリBとライブラリCが必要である
(2) ライブラリAのバージョンが2の場合、ライブラリBのバージョンは3が必要であるこの例でいくと、Composerは
(1) ライブラリAを指定してインストールすると、自動でライブラリBやライブラリCもインストールしてくれる
(2) ライブラリAをバージョン2へアップデートすると、自動でライブラリBのバージョンを3へアップデートしてくれる
ということをしてくれます。ライブラリの指定
プロジェクトに追加したいライブラリを指定するためのファイルがcomposer.jsonです。
composer.jsonには、プロジェクトに必要なライブラリのリストとバージョンを記載します。
このファイルは直接作成&編集するか、以下のようなコマンドで操作することができます。
$ composer init # composer.jsonを作成 $ composer require パッケージ名 # composer.jsonにパッケージを追加ライブラリの読み込み
ライブラリをインストールするためには以下のコマンドを打ちます。
$ composer install実行すると、以下のことが起きます。
- composer.lockが生成される
- ライブラリのソース本体がvendorディレクトリにインストールされる
ただし、プロジェクトに既にcomposer.lockが存在している場合はそちらの情報で優先的にインストールされます。
(チームで開発する場合や、Laravelなどのフレームワークで環境構築した場合など)composer.lockの有無にかかわらず、composer.jsonから再度依存関係を解決してインストールを行いたい場合は以下のコマンドを打ちます。
$ composer updatecomposer.lock
composer.lockには実際にライブラリのどのバージョンがインストールされたかが具体的に記載されます。
チームで開発する場合はこれを利用することによって、開発環境のライブラリによる差分をなくすことができます。
vendor
参考
Composerの導入&使い方(初心者の復習用) - Qiita
composer.json、composer.lockって何なの?という人向けのまとめ - Qiita
Composer は何者か。あるいは install と update の違い。そしてオートロードの仕組み。 | ごみばこいん Blog最後に
Composerおじさんは賢い。ありがとうおじさん。
そのうち余裕があったらJavaScriptのパッケージ管理ツールnpmについてもまとめようと思います。
記事に間違いや不明な点なあればご指摘お願いします。
- 投稿日:2020-07-08T19:38:47+09:00
【Laravel】Bladeでレイアウトを作成する
はじめに
LaravelのBladeテンプレートで使えるレイアウトの「継承」を利用し、複数の「セクション」を組み合わせてレイアウトを作成する機能をまとめます。
図説
extend
最初に記載すべき項目としてレイアウトの継承設定があります。
@extends('layouts.*')部品側のファイルに記載することで、土台側(親)のファイルを読み込んでレイアウトを継承します。
これを書かないとそもページ自体を作ることができないので必須です。sectionとyield
section
@section('content') @endsection@sectionはページで表示するコンテンツの区画を定義する事ができ、同じ名前のyieldにはめ込まれます。
yield
@yield('content')@yieldはコンテンツの配置場場所を定義するもので、同じ名前のsectionが部品側のファイルにある場合コンテンツの内容が表示されます。
titleの様に変数名を渡す場合は@endsectionのような閉じタグを用意する必要がなく@sectionタグだけでコンテンツを定義する事ができます。
parent
@section('sidebar') @parent @endsectionsectionに対応する配置場所の定義はyieldが行いますが、今回「sidebar」にはyieldではなくsectionが用いられています。この場合ははめ込みではなく既にsection内にあった内容を上書きする形になります。
そうすると親のsectionにもともとあった内容が消えてしまうので、親のsection内容を残して表示させたい時は、子のsectionの中に「@parent」ディレクティブを用意してあげる事で、親のsection内容がそこに表示されるようになります。include
@include('名前')@includeはsectionのようにコンテンツとしてではなく、より単純にテンプレートをただはめ込んで表示させたい場合に使用します。なのでサブビューのファイルではコンテンツをsectionで囲う必要がありません。
includeでもって来たビューの内容を「サブビュー」といいます。
- 投稿日:2020-07-08T19:02:06+09:00
Laravel 6で認証機能を入れる
開発環境構築
以下の環境を構築した上で、そのプロジェクトで実行しています。
https://qiita.com/ryuseino/items/e0e3a77245635b7cc101usersテーブル作成
とりあえずLaravelにデフォルトでついてくるMigrationを使ったusersテーブルでやります。
なのでまずはテーブル作成のコマンド実行。php artisan migrateComposerパッケージインストール
以下のコマンドを実行することで認証が簡単に出来るようになります。
composer require laravel/ui "^1.0" --dev php artisan ui vue --auth npm install && npm run devlocalhostを開く
開発環境構築後の確認と同じく、localhostを開いてみるとLOGINとREGISTERというリンクが上部に出ています。
それぞれ極々普通のログインと会員登録の機能になっています。
そんな訳で簡単に認証が作れることが分かりました。
この段階ではまだemailのverifyなどがないので、それらは後で追加する必要がありそうです。参考になりそうなページ
- 投稿日:2020-07-08T18:17:03+09:00
Slim3 Framework×slim-skeleton不使用×twigでプロジェクトを作成する(1. プロジェクト作成~各種設定)
はじめに
今回はslim-skeletonを使用しないSlim3フレームワークとtwigを使用したプロジェクトを作成します。
Slim3フレームワークおすすめチュートリアルで紹介した、
@nunulkさんのチュートリアルをDaniel Opitzさんのやりかたで再現してみるイメージです。
成果物としては@nunulkさんのチュートリアルを通してできるものと同じものができます。
人の褌で相撲を取ってる感がすごいですが、許してください。前提
下記記事で構築した環境を前提とします。
- Windows10にVagrantをを入れてCentOS7をインストールしよう(1、2、3、4、5、6)
- ローカルでLAMP環境を構築しよう(0、1、2、3、4)
私家版 Slim Framework チュートリアル (1、2、3、4、5、6)
@nunulkさんのチュートリアルを一通り。
ここで作成したDBを使いまわします。手順
1. 専用のユーザーを作成
2. プロジェクトディレクトリを作成・slim3インストール
3. 各種設定
4. DocumentRootを変更&表示確認
5. Twigを使ってみよう
6. Loggingしてみよう
7. Controllerを作成しよう
8. PDOを使用してデータベースに接続しよう
9. @nunulkさんのチュートリアルで作成したチケット管理システムをtwigを使って再現しようやってみよう
今回の記事では、手順1~3を行います。
1. 専用のユーザーを作成
PHP Slim3フレームワークのサンプルアプリを作ろう
(2-1. First Application Walkthrough Getting Set Upまで)の
1. 専用のユーザーを作成の手順で専用のユーザーを作成します。2. プロジェクトディレクトリを作成・slim3インストール
slimuserユーザーが作成されると
/home/ディレクトリ内にslimuserディレクトリが作成されます。
その中に以下のプロジェクトディレクトリを作成します。/home/slimuser/projects/slim/SampleApplication以下のコマンドで、slim3をインストールします。
composer require slim/slim:3.*3. 各種設定
SampleApplicationの下に以下のようにディレクトリ・ファイルを作成します。
Creating your first Slim 3 Framework Applicationにある手順に従って設定していきます。ディレクトリ構成. ├── config/ Configuration files │ └── bootstrap.php │ └── container.php │ └── middleware.php │ └── routes.php │ └── settings.php ├── public/ Web server files (DocumentRoot) │ └── .htaccess Apache redirect rules for the front controller │ └── index.php The front controller ├── templates/ Twig templates ├── src/ PHP source code (The App namespace) ├── tmp/ Temporary files (cache and logfiles) ├── vendor/ Reserved for composer(slim3インストール時に自動生成) ├── composer.json slim3インストール時に自動生成 └── composer.lock slim3インストール時に自動生成 ├── .htaccess Internal redirect to the public/ directory └── .gitignore Git ignore rulesFront controller
Apacheのリダイレクトの設定が記述されるファイルです。以下のように記述します。
public/.htaccess# Redirect to front controller RewriteEngine On # RewriteBase / RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^ index.php [QSA,L].htaccessRewriteEngine on RewriteRule ^$ public/ [L] RewriteRule (.*) public/$1 [L]Bootstrap
名前からしてTwitter社が開発したのBootstrapのことかな?と思いましたがどうもそうではない様子。
config/bootstrap.php
に使用する各種設定ファイルについて記述し、
public/index.php
から呼び出しているようです。
config/bootstrap.php
とpublic/index.php
をそれぞれ以下のように記述します。public/index.php<?php /** @var Slim\App $app */ $app = require __DIR__ . '/../config/bootstrap.php'; $app->run();config/bootstrap.php<?php require_once __DIR__ . '/../vendor/autoload.php'; $app = new \Slim\App(['settings' => require __DIR__ . '/../config/settings.php']); require __DIR__ . '/container.php'; require __DIR__ . '/middleware.php'; require __DIR__ . '/routes.php'; return $app;Container
アプリの依存関係の設定を行うファイルです。以下のように記述します。
config/container.php<?php use Slim\Container; /** @var \Slim\App $app */ $container = $app->getContainer(); // Activating routes in a subfolder $container['environment'] = function () { $scriptName = $_SERVER['SCRIPT_NAME']; $_SERVER['SCRIPT_NAME'] = dirname(dirname($scriptName)) . '/' . basename($scriptName); return new Slim\Http\Environment($_SERVER); };Middleware
今の時点でミドルウェアはありません。
config/middleware.php<?php // Slim middlewareRoutes
ルーティングを行うファイルです。以下のように記述します。
config/routes.php<?php use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; $app->get('/', function(ServerRequestInterface $request, ResponseInterface $resp onse) { $response->getBody()->write("It works! This is the default welcome page"); return $response; })->setName('root'); $app->get('/hello/{name}', function(ServerRequestInterface $request, ResponseInterface $response) { $name = $request->getAttribute('name'); $response->getBody()->write("Hello, $name"); return $response; });Configuration
config/settings.php<?php $settings = []; $settings['displayErrorDetails'] = true; $settings['determineRouteBeforeAppMiddleware'] = true; $settings['addContentLengthHeader'] = false; $settings['root'] = dirname(__DIR__); $settings['temp'] = $settings['root'] . '/tmp'; $settings['public'] = $settings['root'] . '/public'; return $settings;Composer
slim3インストール時に自動生成されたcomposer.jsonを以下のように編集します。
composer.json(編集前){ "require": { "slim/slim": "3.*" } }composer.json(編集後){ "require": { "php": ">=5.6", "slim/slim": "3.*" }, "autoload": { "psr-4": { "App\\":"src/" } }, "autoload-dev": { "psr-4": { "App\\Test\\": "tests/" } }, "config": { "sort-packages": true }, "scripts": { "start": "php -S 192.168.33.90:8080 -t public public/index.php", "test": "phpunit" } }
192.168.33.90
部分はご自分の環境に置き換えてください。
composer.jsonを編集した後は以下のコマンドを実行しておきましょう。composer dump-autoload.gitignore
vendorディレクトリはgitにコミットしませんので、以下のように記述します。
.gitignorevendor/ .idea/動作確認
以下のコマンドを実行します。何か記述間違いがあれば、この時点で警告されます。
composer startブラウザで下記のURLを開きます。
It works! This is the default welcome page
と表示されればOKです。http://192.168.33.90:8080/ブラウザで下記のURLを開きます。
Hello, world
と表示されればOKです。http://192.168.33.90:8080/hello/world参考サイト
Creating your first Slim 3 Framework Application
私家版 Slim Framework チュートリアル (1) 〜 特徴と準備編
私家版 Slim Framework チュートリアル (2) 〜 ルーティングと新規作成編
私家版 Slim Framework チュートリアル (3) 〜 表示編
私家版 Slim Framework チュートリアル (4) 〜 編集と削除、ついでにパーシャルビュー編
私家版 Slim Framework チュートリアル (5) 〜 Controllerクラス編
私家版 Slim Framework チュートリアル (6) 〜 テスト編関連ページ
Windows10にVagrantをを入れてCentOS7をインストールしよう
1. VagrantインストールからVagrantfileを設置まで
2. 仮想マシンの操作
3. WinSCP、Tera Termに秘密鍵でログイン
4. WinSCP、Tera Termにrootユーザーでパスワードログイン
5. zip/unzipをインストール
6. Vagrantにて仮想環境を配布ローカルでLAMP環境を構築しよう
0. 事前準備
1. Apacheをインストール
2. MySQLをインストール
3. PHPをインストール
4. ファイアウォールとか停止するComposerをインストール
PHP Slim3フレームワークのサンプルアプリを作ろう
2-1. First Application Walkthrough Getting Set Upまで
Apache
Slim3 Framework×slim-skeleton不使用×twigでプロジェクトを作成する
- 投稿日:2020-07-08T17:36:08+09:00
Slim3フレームワークおすすめチュートリアル
はじめに
お仕事でPHP Slim3フレームワークを使うので、ここ数か月勉強しています。
今回はSlim3フレームワークのおすすめチュートリアルを紹介します。みんなSlimフレームワーク公式ドキュメントはわかりにくいと思っている
日本語で読める、一番わかりやすく網羅的なチュートリアル
日本語で読めるチュートリアルで一番わかりやすく、網羅的なのは
@nunulkさんの私家版 Slim Framework チュートリアル (1) 〜 特徴と準備編から始まる一連の記事です。
鉄板です。Slimフレームワークやりたい方は必読です。
書いてあるコードをそのまま写経すればちゃんと動く親切仕様なので、
私のようなPHP初めてパーソンでも安心!slim-skeleton不使用×twigのチュートリアル
「slim-skeleton使わないで、twigも使うようなサンプルないかなあ」と探したところ、
Daniel OpitzさんのCreating your first Slim 3 Framework Applicationという記事を見つけました。
こちらもなかなかわかりやすいですが、そのまま写経すれば動くコードばかりではなかったので、
チャレンジするなら@nunulkさんのチュートリアルの後が良いと思います。@nunulkさんとDaniel Opitzさんの共通点
@nunulkさんとDaniel Opitzさんの共通点は
「公式ドキュメントがマジでイケてないので、俺がわかりやすいチュートリアルを作ってやるよ!」
という義侠心にあふれたところです。所感
私はPHPはほぼ初めてでSlimから入ったのでよくわかっていませんが、Slim、ちょっと玄人向けというか、
PHPにそこそこ習熟した人が対象のフレームワークなのかもと思いました。
決まりごとが少なくて実装者の裁量が大きいゆえに、
きっちりしたチュートリアルが出しにくいのかもしれない。
@nunulkさんもDaniel Opitzさんも、そこを親切に補ってくれています。
おそらくこの2つのチュートリアルなしでは習得不可能だったと思います。参考サイト
Creating your first Slim 3 Framework Application
私家版 Slim Framework チュートリアル (1) 〜 特徴と準備編
私家版 Slim Framework チュートリアル (2) 〜 ルーティングと新規作成編
私家版 Slim Framework チュートリアル (3) 〜 表示編
私家版 Slim Framework チュートリアル (4) 〜 編集と削除、ついでにパーシャルビュー編
私家版 Slim Framework チュートリアル (5) 〜 Controllerクラス編
私家版 Slim Framework チュートリアル (6) 〜 テスト編
- 投稿日:2020-07-08T17:24:17+09:00
PHP: Starttls でメールの送信
こちらと同じことを PHP で行いました。
Python3: Starttls でメールの送信
hi-ho.ne.jp で試しました。ライブラリーのインストール
composer require "swiftmailer/swiftmailer:^6.0" composer require vlucas/phpdotenv
hi-ho.php#! /usr/bin/php <?php // ------------------------------------------------------------------ // hi-ho.php // // Jul/08/2020 // // ------------------------------------------------------------------ require_once 'vendor/autoload.php'; fputs (STDERR,"*** 開始 ***\n"); $dotenv = Dotenv\Dotenv::createImmutable(__DIR__); $dotenv->load(); $server = $_ENV['SERVER']; $port = $_ENV['PORT']; $usr = $_ENV['USR']; $password = $_ENV['PASSWORD']; $from = $_ENV['FROM']; $to = $_ENV['TO']; print $server . "\n"; print $port . "\n"; date_default_timezone_set('Asia/Tokyo'); $today = date ("Y-m-d"); $now = date( "Y年m月d日 H時i分s秒" ) ; $transport = (new Swift_SmtpTransport($server, 587)) ->setUsername($usr) ->setPassword($password) ; // 3. Swift_Mailer クラスを new する $mailer = new Swift_Mailer($transport); // 4. メッセージの作成 $str_out = ""; $str_out .= 'This is TEST.' . PHP_EOL; $str_out .= 'こんにちは。' . PHP_EOL; $str_out .= '晴れています。' . PHP_EOL; $str_out .= 'Jul/08/2020' . PHP_EOL; $str_out .= 'PM 17:13' . PHP_EOL; $str_out .= $today . PHP_EOL; $str_out .= $now . PHP_EOL; $message = new Swift_Message('Hello from Hi-ho ' . $now); $message->setFrom([$from => 'TEST']); $message->setTo([$to]); $message->setBody($str_out); $result = $mailer->send($message); var_dump($result); fputs (STDERR,"*** 終了 ***\n"); // ------------------------------------------------------------------ ?>.envSERVER = 'hi-ho.mose-mail.jp' PORT = 587 USR = '****@hi-ho.ne.jp' PASSWORD = '****' FROM = '****@hi-ho.ne.jp' TO = 'sample@example.com'実行結果
$ ./hi-ho.php *** 開始 *** hi-ho.mose-mail.jp 587 int(1) *** 終了 ***
- 投稿日:2020-07-08T14:57:30+09:00
Trello投稿時に自社システムに通知する
タスク管理ツールとして大変メジャーなTrelloですが、自社システムと連携したい場合がありますよね。
この記事では以下について実装方法を説明します。
・Trelloでコメントが投稿されたら自社システムに通知機能を実装するために「Trello Webhook API」を使用します。
Webhookとは何ぞや、と普段思っている方もいるかもしれませんが、改めて調べてみたら
「Webアプリケーションでイベントが実行された際、外部サービスにHTTP で通知する仕組み」
とヒットしました。ここで言う「Webアプリケーション」はTrelloのことで「外部サービス」は自社システムですね。
ですからTrelloが提供しているWebhook APIが必要なのです。
使うまでの手順を優しく説明します。1.https://trello.com/app-key にアクセス。
2.「Trello 開発契約」を確認し、「APIキーを表示」をクリック。
3.キーが表示される(このキーは後の手順で使用するため、メモしておいてください)
この画面で「Token」のリンクをクリック。
5.トークンが発行される(このトークンは後の手順で使用するため、メモしておいてください)
6.コメント投稿されたら自社システムに通知したいボードIDを取得します。
コマンドプロンプトやターミナルで以下のコマンドを実行しましょう。curl "https://trello.com/1/members/[ユーザ名]/boards?key=[3で表示されたキー]&token=[5で表示されたトークン]&fields=name"
文字化けしてしまう場合は以下の方法で文字コードを変更してあげましょう。
https://qiita.com/user0/items/a9116acc7bd7b70ecfb0「Trelloへようこそ」「テスト」という2つのボードが表示されました。
ここでは例として「テスト」のボードにしましょう。
「テスト」のidをコピーしておきます。7.次にWebhookを生成します。
ここでもコマンドプロンプトやターミナルで以下のコマンドを実行しましょう。curl -X POST "https://api.trello.com/1/token/[5で表示されたトークン]/webhooks?key=[3で表示されたキー]&callbackURL=[コールバックURL]&idModel=[でコピーしたid]&description=[Webhookの説明]"コールバックURLはTrelloでアクションがあった場合に通知してほしいURLを設定してください。
ちゃんとステータスコード200を返すURLにしてください。8.正常に生成されたらWebhookを確認してあげましょう。
ブラウザで以下のURLにアクセスすると、正常に生成されていることがわかります。
https://trello.com/1/tokens/[5で表示されたトークン]/webhooks/
これで準備は整いました。
該当のボードにて何かアクションがあった際にコールバックURLにリアルタイムで通知がされるようになりました。
あとは自社システム側の処理ですね。Trelloでアクションがあるとこんな感じのデータが飛んできますす。
この各項目に関するリファレンスがなかったので今度時間がある際にまとめたいと思います。
ちょっと解析していただければわかると思います。
PHPの処理側はこんな感じ。
POSTリクエストでかつTrelloからの通知の場合のみ動作するようにしました。function index(){ // trelloからのアクセスのみ受け付ける if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_SERVER['HTTP_X_TRELLO_WEBHOOK'])) { $body = file_get_contents("php://input"); if (!empty($body)) { $bodyArray = json_decode($body, true); // 登録されたコメント // コメント編集時にはここには入らないのでスルー if(!empty($bodyArray['action']['data']['text'])){ $operatorName = $bodyArray['action']['display']['entities']['memberCreator']['text']; // コメントした人 $comment = $bodyArray['action']['data']['text']; // 投稿されたコメント $boardName = $bodyArray['model']['name']; // ボード名 $title = $bodyArray['action']['data']['card']['name']; // カードのタイトル $cardId = $bodyArray['action']['data']['card']['id']; // カードID // 以降の処理はご自由に~ } } } }以上になります。
手順に沿ってやっていただければすぐ実装できますのでぜひやってみてくださいね。
- 投稿日:2020-07-08T14:36:47+09:00
html周りのエラー
メモ代わり
html周り弄ってた時のメモとして。
javascriptやらphpも込み込み(の予定)
都度都度更新してく。javascriptでjsonが読み込めない(404エラーを吐かれる)
原因
知らん!
最初は「jquery使えないせいか?」とか「jsonのパス指定が間違っているか?」とも思ったがそうでもなかったし。
ただ自前のサーバーで全く同じコードでやった時はエラー吐かれなかったからサーバの設定あたりの可能性か?
オチ
jsonファイルをテキスト(.txt)に変換してそれを読み込ませたところ、問題なく動作した。
読み込むコードはこんな感じ(jQuery使用)。sample.jsfunction sample() { $.getJSON("latest_data.txt",(data) => {/* 処理あれやこれや*/}); }500エラー(php)
原因
構文エラーの可能性が高い。
概要箇所をよく見直す事。と昔ののボクが残したメモに書いてあった
前やらかしたやつ
・必要な部分までコメントアウトしてしまった。sample.php<?php for() {内容 //こんな感じ。右の中括弧もコメントアウトされちゃってる→} {内容}//案1:後ろにつける。 {内容/*案2:コメント部分を囲う*/} //案2の方は全体をコメントアウトしたいときに、ここでコメントアウト切れちゃうから個人的にあまりお勧めはしない ?>
- 投稿日:2020-07-08T12:58:36+09:00
【PHP】Blurhashでぼかし画像を生成する
概要
Blurhashを利用して、blur画像(ぼかし画像)を動的に生成します。
用途としては、実際に表示される画像の想像ができるblur画像をプレースホルダーとして表示することで、読み込み時間のUXを改善しようというものです。
Blurhashの準備
公式のGithubリポジトリからソースを入手します。
複数の言語に対応しており、今回はPHPバージョンを利用します。環境の都合でComposerを使用せず、ソースをDLして使います。
「Download ZIP」からzipをDLすることが出来ます。
zipを解凍すると「php-blurhash-master」というディレクトリができます。
使い勝手を考慮して「blurhash」にリネームし、ディレクトリごと好きな場所に置きます。Blurhashを実装
Blurhashで行う処理はエンコードとデコードの2つです。
①オリジナル画像をblur画像化し、短い文字列を生成する(エンコード)
②文字列をblur画像に戻す(デコード)まずは必要なファイルを読み込みます。
Composerを利用していないので、require
で各ファイルを読み込む必要があります。encode.php<?php use kornrunner\Blurhash\Blurhash; use kornrunner\Blurhash\Color; use kornrunner\Blurhash\DC; use kornrunner\Blurhash\AC; use kornrunner\Blurhash\Base83; require_once('blurhash/src/Blurhash.php'); require_once('blurhash/src/Color.php'); require_once('blurhash/src/DC.php'); require_once('blurhash/src/AC.php'); require_once('blurhash/src/Base83.php'); // Composerを利用した場合は下記2行だけでOK // require_once('vendor/autoload.php'); // use kornrunner\Blurhash\Blurhash; // メモリが足りなければ調整 // ini_set('memory_limit', '512M'); : : // 続きの処理
まずはオリジナル画像をblur画像にして文字列にエンコードします。encode.php$file = 'original.png'; $image = imagecreatefromstring(file_get_contents($file)); $width = imagesx($image); $height = imagesy($image); $pixels = []; for ($y = 0; $y < $height; ++$y) { $row = []; for ($x = 0; $x < $width; ++$x) { $index = imagecolorat($image, $x, $y); $colors = imagecolorsforindex($image, $index); $row[] = [$colors['red'], $colors['green'], $colors['blue']]; } $pixels[] = $row; } $components_x = 3; $components_y = 4; $blurhash = Blurhash::encode($pixels, $components_x, $components_y); echo $blurhash; // 出力結果 // LEHV9uae2yk8pyo0adR*.7kCMdnjソースはGithubのサンプルまんまです。
ファイルを渡して処理すると、短い文字列が生成されます。
この文字列をデコードするとblur画像になります。オリジナル画像を渡して動的にエンコード~デコードまで行うと処理に少し時間がかかりました。
そのため、オリジナル画像をエンコードして文字列を保存しておき、表示するタイミングでデコードして画像を表示させる…などといった使い方になると思います。(多分)
次はデコードしてblur画像を表示します。
今回はimgタグで表示させるために、getパラメータでエンコードした文字列を渡します。view.html<img src="decode.php?image=LEHV9uae2yk8pyo0adR*.7kCMdnj">decode.php$blurhash = $_GET['image']; // 生成した文字列を取得 // 画像のサイズを取得(もしくは生成したいサイズを入力) $fileinfo = getimagesize('original.png'); $width = $fileinfo[0]; $height = $fileinfo[1]; $pixels = Blurhash::decode($blurhash, $width, $height); $image = imagecreatetruecolor($width, $height); for ($y = 0; $y < $height; ++$y) { for ($x = 0; $x < $width; ++$x) { [$r, $g, $b] = $pixels[$y][$x]; // if($r > 255) {$r = 255;} // 場合によって追記 // if($g > 255) {$g = 255;} // 場合によって追記 // if($b > 255) {$b = 255;} // 場合によって追記 imagesetpixel($image, $x, $y, imagecolorallocate($image, $r, $g, $b)); } } // 画像を出力 header('Content-Type: image/png'); imagepng($image);これで、
decode.php
に渡した文字列がデコードされ、画像として表示されます。
// 場合によって追記
の3行に関しては、画像によって(例えば真っ白の画像など)RGBの値を超える?エラーが出るため、上限を設定しています。ちなみに、公式ではデコードに関してはJavaScript/TypeScriptを使うのをおすすめしています。
blur画像を保存したい場合
blur画像を保存せずに表示する方法を書きましたが、保存も可能です。
①
decode.php
をブラウザで実行すれば画像が表示されるので、右クリックで保存②最終行を下記に変更すれば、指定した先に保存されます。
// header('Content-Type: image/png'); imagepng($image, '保存先/保存名.png');blur画像をbase64で表示する
blur画像は保存したくないけど、動的にデコード処理をするのが嫌な場合。
画像をbase64にエンコードしてsrcに渡すことで表示することができます。decode.php// decode.phpの最終行を以下に書き換える // header('Content-Type: image/png'); // imagepng($image); // 画像のGDリソースをbase64に変換する ob_start(); imagepng($image); $image_data = ob_get_contents(); ob_end_clean(); $image_data_base64 = base64_encode($image_data); echo $image_data_base64; // 出力結果 // iVBORw0KGgoAAAANSUhEUgAAAeAAAAFACAIAAADrqjgsAAAACXBIWXMAAA7E....
base64に変換したものを保存しておき、下記のように渡すと画像が表示できます。
(ただし文字列が尋常じゃなく長い場合があるので、実装には向かない)view.html<img src="data:image/jpeg;base64,<?= $image_data_base64 ?>" alt="">参考URL
- 投稿日:2020-07-08T10:30:49+09:00
Laravel Eloquantでデータを得ようとしたらエラーが出た話
目的
- idカラムの値を指定してレコードのデータを取得しようとした際にエラーが発生した話をまとめる
実施環境
- ハードウェア環境
項目 情報 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をインストールする 問題までの経緯
モデルファイルを
アプリ名ディレクトリ/app
直下からアプリ名ディレクトリ/app/Models
直下に移動した。(Modelsディレクトリはmkdir
コマンドにて作成した。)Laravelアプリ名ディレクトリで下記コマンドを実行してtinkerを開いた。
$ php artisan tinker下記を実行してuse宣言を行った。
use App\Models\モデルファイル名下記を実行してidカラムが1のレコードのデータを取得しようとした。
$info = モデル名::find(1)問題
- 下記のエラーが発生した。
PHP Fatal error: Cannot declare class App\モデルファイル名, because the name is already in use in /usr/share/nginx/html/Laravelアプリ名/app/Models/モデルファイル名.php on line 7 PHP Stack trace: PHP 1. {main}() /usr/share/nginx/html/Laravelアプリ名/artisan:0 PHP 2. App\Console\Kernel->handle() /usr/share/nginx/html/Laravelアプリ名/artisan:37 PHP 3. Illuminate\Console\Application->run() /usr/share/nginx/html/Laravelアプリ名/vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php:131 PHP 4. Illuminate\Console\Application->run() /usr/share/nginx/html/Laravelアプリ名/vendor/laravel/framework/src/Illuminate/Console/Application.php:93 PHP 5. Illuminate\Console\Application->doRun() /usr/share/nginx/html/Laravelアプリ名/vendor/symfony/console/Application.php:147 PHP 6. Illuminate\Console\Application->doRunCommand() /usr/share/nginx/html/Laravelアプリ名/vendor/symfony/console/Application.php:271 PHP 7. Laravel\Tinker\Console\TinkerCommand->run() /usr/share/nginx/html/Laravelアプリ名/vendor/symfony/console/Application.php:1000 PHP 8. Laravel\Tinker\Console\TinkerCommand->run() /usr/share/nginx/html/Laravelアプリ名/vendor/laravel/framework/src/Illuminate/Console/Command.php:121 PHP 9. Laravel\Tinker\Console\TinkerCommand->execute() /usr/share/nginx/html/Laravelアプリ名/vendor/symfony/console/Command/Command.php:255 PHP 10. Illuminate\Foundation\Application->call() /usr/share/nginx/html/Laravelアプリ名/vendor/laravel/framework/src/Illuminate/Console/Command.php:134 PHP 11. Illuminate\Container\BoundMethod::call() /usr/share/nginx/html/Laravelアプリ名/vendor/laravel/framework/src/Illuminate/Container/Container.php:590 PHP 12. Illuminate\Container\BoundMethod::callBoundMethod() /usr/share/nginx/html/Laravelアプリ名/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:34 PHP 13. Illuminate\Container\Util::unwrapIfClosure() /usr/share/nginx/html/Laravelアプリ名/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:90 PHP 14. Illuminate\Container\BoundMethod::Illuminate\Container\{closure:/usr/share/nginx/html/Laravelアプリ名/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:30-34}() /usr/share/nginx/html/Laravelアプリ名/vendor/laravel/framework/src/Illuminate/Container/Util.php:37 PHP 15. call_user_func_array:{/usr/share/nginx/html/Laravelアプリ名/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:32}() /usr/share/nginx/html/Laravelアプリ名/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:32 PHP 16. Laravel\Tinker\Console\TinkerCommand->handle() /usr/share/nginx/html/Laravelアプリ名/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:32 PHP 17. Psy\Shell->run() /usr/share/nginx/html/Laravelアプリ名/vendor/laravel/tinker/src/Console/TinkerCommand.php:78 PHP 18. Psy\Shell->run() /usr/share/nginx/html/Laravelアプリ名/vendor/psy/psysh/src/Shell.php:316 PHP 19. Psy\Shell->doRun() /usr/share/nginx/html/Laravelアプリ名/vendor/symfony/console/Application.php:147 PHP 20. Psy\Shell->doInteractiveRun() /usr/share/nginx/html/Laravelアプリ名/vendor/psy/psysh/src/Shell.php:341 PHP 21. Psy\ExecutionLoopClosure->execute() /usr/share/nginx/html/Laravelアプリ名/vendor/psy/psysh/src/Shell.php:370 PHP 22. Psy\{closure:/usr/share/nginx/html/Laravelアプリ名/vendor/psy/psysh/src/ExecutionLoopClosure.php:32-100}() /usr/share/nginx/html/Laravelアプリ名/vendor/psy/psysh/src/ExecutionClosure.php:96 PHP 23. Psy\Shell->getInput() /usr/share/nginx/html/Laravelアプリ名/vendor/psy/psysh/src/ExecutionLoopClosure.php:40 PHP 24. Psy\Shell->addCode() /usr/share/nginx/html/Laravelアプリ名/vendor/psy/psysh/src/Shell.php:521 PHP 25. Psy\CodeCleaner->clean() /usr/share/nginx/html/Laravelアプリ名/vendor/psy/psysh/src/Shell.php:829 PHP 26. PhpParser\NodeTraverser->traverse() /usr/share/nginx/html/Laravelアプリ名/vendor/psy/psysh/src/CodeCleaner.php:227 PHP 27. PhpParser\NodeTraverser->traverseArray() /usr/share/nginx/html/Laravelアプリ名/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php:91 PHP 28. PhpParser\NodeTraverser->traverseNode() /usr/share/nginx/html/Laravelアプリ名/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php:223 PHP 29. PhpParser\NodeTraverser->traverseNode() /usr/share/nginx/html/Laravelアプリ名/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php:146 PHP 30. Psy\CodeCleaner\ValidClassNamePass->leaveNode() /usr/share/nginx/html/Laravelアプリ名/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php:153 PHP 31. Psy\CodeCleaner\ValidClassNamePass->validateStaticCallExpression() /usr/share/nginx/html/Laravelアプリ名/vendor/psy/psysh/src/CodeCleaner/ValidClassNamePass.php:93 PHP 32. Psy\CodeCleaner\ValidClassNamePass->ensureMethodExists() /usr/share/nginx/html/Laravelアプリ名/vendor/psy/psysh/src/CodeCleaner/ValidClassNamePass.php:180 PHP 33. Psy\CodeCleaner\ValidClassNamePass->ensureClassOrTraitExists() /usr/share/nginx/html/Laravelアプリ名/vendor/psy/psysh/src/CodeCleaner/ValidClassNamePass.php:271 PHP 34. Psy\CodeCleaner\ValidClassNamePass->traitExists() /usr/share/nginx/html/Laravelアプリ名/vendor/psy/psysh/src/CodeCleaner/ValidClassNamePass.php:255 PHP 35. trait_exists() /usr/share/nginx/html/Laravelアプリ名/vendor/psy/psysh/src/CodeCleaner/ValidClassNamePass.php:375 PHP 36. spl_autoload_call() /usr/share/nginx/html/Laravelアプリ名/vendor/psy/psysh/src/CodeCleaner/ValidClassNamePass.php:375 PHP 37. Composer\Autoload\ClassLoader->loadClass() /usr/share/nginx/html/Laravelアプリ名/vendor/psy/psysh/src/CodeCleaner/ValidClassNamePass.php:375 PHP 38. Composer\Autoload\includeFile() /usr/share/nginx/html/Laravelアプリ名/vendor/composer/ClassLoader.php:322 PHP 39. include() /usr/share/nginx/html/Laravelアプリ名/vendor/composer/ClassLoader.php:444 Symfony\Component\Debug\Exception\FatalErrorException : Cannot declare class App\モデルファイル名, because the name is already in use at /usr/share/nginx/html/Laravelアプリ名/app/Models/モデルファイル名.php:7 3| namespace App; 4| 5| use Illuminate\Database\Eloquent\Model; 6| > 7| class モデルファイル名 extends Model 8| { 9| // 10| } 11| Exception trace: 1 Symfony\Component\Debug\Exception\FatalErrorException::__construct() /usr/share/nginx/html/Laravelアプリ名/vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php:148 2 Illuminate\Foundation\Bootstrap\HandleExceptions::fatalExceptionFromError() /usr/share/nginx/html/Laravelアプリ名/vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php:134 Please use the argument -v to see more details. Whoops\Exception\ErrorException : Cannot declare class App\モデルファイル名, because the name is already in use at /usr/share/nginx/html/Laravelアプリ名/app/Models/モデルファイル名.php:7 3| namespace App; 4| 5| use Illuminate\Database\Eloquent\Model; 6| > 7| class モデルファイル名 extends Model 8| { 9| // 10| } 11| Exception trace: 1 () /usr/share/nginx/html/Laravelアプリ名/vendor/composer/ClassLoader.php:444 2 Composer\Autoload\includeFile() /usr/share/nginx/html/Laravelアプリ名/vendor/composer/ClassLoader.php:322 Please use the argument -v to see more details.問題解決までの経緯
データの取得に使用するモデルファイルを確認した。下記にモデルファイルの内容を記載する。
アプリ名ディレクトリ/app/Models/モデルファイル.php<?php namespace App; use Illuminate\Database\Eloquent\Model; class モデルファイル名 extends Model { // }モデルファイルの設置場所を変更したにもかかわらずモデルファイル内のnamespaceの記載を変更していなかった。
下記の様にモデルファイルを修正した。
アプリ名ディレクトリ/app/Models/モデルファイル.php<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class モデルファイル名 extends Model { // }下記の手順を実施して正常にidが1のレコードのデータを取得できたことが確認できた。
Laravelアプリ名ディレクトリで下記コマンドを実行してtinkerを開く。
$ php artisan tinker下記を実行してuse宣言を行う。
use App\Models\モデルファイル名下記を実行してidカラムが1のレコードのデータを取得した。
$info = モデル名::find(1)
- 投稿日:2020-07-08T09:33:10+09:00
[最新版] PHPでMessaging APIを使ったLINEbotを作る
今回の題
API系の記事はこれで3つ目です!
前回→[PHP] Zoom APIを利用してミーティングを作成する
前々回→[PHP] YouTube APIの利用(動画情報の取得)今回はタイトルの通り、LINEbotを作りましょう!
LINE DevelopersのMessagingAPIというものを利用すれば、自分好みのLINEbotが簡単に作れます。
この記事では、
- おうむ返し
- ボタン
- confirm
- 日付選択アクション
などを作ってみます。
必要なもの
- サーバー
ssl化が必須です。
私はconohaで動かしてますが、ググるとherokuを使った記事を多く見かけました。チャネルシークレットとチャネルアクセストークンの取得
4つの段階に分けて説明していきます。
1. 開発者用のアカウントを作成
以下にアクセスし、LINEのアカウントを使ってログインしてください。
LINE Developers2. プロバイダーの作成
以下のページの左サイドバーにプロバイダーという項目があると思うので選択し、画面中央辺りの「作成」を押してください。
LINE Developers コンソール作成するプロバイダー名を求められるので適当に入力し、「作成」を押したらプロバイダーの作成は完了です!
3. チャネルの作成
プロバイダーの作成後、以下のようなページに飛ばされます。
画像内の赤枠の「Messaging API」を選択してください。
チャネルを作成する画面に飛ぶので、必須項目を全て入力し、「作成」を押したらチャネルの作成は完了です!
4. チャネルシークレットとチャネルアクセストークンの取得
チャネルの作成後、作成したチャネルの設定ページに飛ばされます。
チャネルシークレットとチャネルアクセストークンの取得はどちらもこのページを起点にします。
チャネルアクセストークン
Messaging API設定のタブの下の方に載っています。
初期状態だと何も表示されていませんが、右にある「発行」を押すと表示されます。
これもあとで使うのでコピーしておいてください。
以上でチャネルシークレットとチャネルアクセストークンがGETできました。
Webhook設定
Messaging API設定のタブの中央辺りに欄があるので、リクエストを受け取るURLを設定し、Webhookの利用を有効にします。
botを友達に追加
Messaging API設定のタブの上の辺りにQRコードがあるので読み取って友達に追加しておきましょう。
そろそろコードを書いていきます。
LINE Messaging API SDK for PHPのインストール
composerを使ってインストールします。
$ composer require linecorp/line-bot-sdkLINE Messaging API SDK for PHPのソースコードは以下です。
LINE Messaging API SDK for PHPコードの例
実際に動かしたコードをそのまま載せておきます。
なので、チャネルシークレットとチャネルアクセストークンをセットすればコピペで動きます。1. おうむ返し。
ただテキストを返すだけ!
<?php require('vendor/autoload.php'); use LINE\LINEBot\Constant\HTTPHeader; use LINE\LINEBot\HTTPClient\CurlHTTPClient; use LINE\LINEBot; //先ほど取得したチャネルシークレットとチャネルアクセストークンを以下の変数にセット $channel_access_token = 'XXXXXXXXX'; $channel_secret = 'XXXXXXXXX'; $http_client = new CurlHTTPClient($channel_access_token); $bot = new LINEBot($http_client, ['channelSecret' => $channel_secret]); $signature = $_SERVER['HTTP_' . HTTPHeader::LINE_SIGNATURE]; $http_request_body = file_get_contents('php://input'); $events = $bot->parseEventRequest($http_request_body, $signature); $event = $events[0]; $reply_token = $event->getReplyToken(); $reply_text = $event->getText(); $bot->replyText($reply_token, $reply_text);2. ボタン
<?php require('vendor/autoload.php'); use LINE\LINEBot\Constant\HTTPHeader; use LINE\LINEBot\HTTPClient\CurlHTTPClient; use LINE\LINEBot; use LINE\LINEBot\MessageBuilder\MultiMessageBuilder; use LINE\LINEBot\TemplateActionBuilder\PostbackTemplateActionBuilder; use LINE\LINEBot\MessageBuilder\TemplateMessageBuilder; use LINE\LINEBot\MessageBuilder\TemplateBuilder\ButtonTemplateBuilder; $channel_access_token = 'XXXXXXXXX'; $channel_secret = 'XXXXXXXXX'; $http_client = new CurlHTTPClient($channel_access_token); $bot = new LINEBot($http_client, ['channelSecret' => $channel_secret]); $signature = $_SERVER['HTTP_' . HTTPHeader::LINE_SIGNATURE]; $http_request_body = file_get_contents('php://input'); $events = $bot->parseEventRequest($http_request_body, $signature); $event = $events[0]; $reply_token = $event->getReplyToken(); $yes_button = new PostbackTemplateActionBuilder('はい', 'button=1'); $no_button = new PostbackTemplateActionBuilder('キャンセル', 'button=0'); $actions = [$yes_button, $no_button]; $button = new ButtonTemplateBuilder('タイトル', 'テキスト', '', $actions); $button_message = new TemplateMessageBuilder('タイトル', $button); $message = new MultiMessageBuilder(); $message->add($button_message); $bot->replyMessage($reply_token, $message);ButtonTemplateBuilderの第3引数に画像のURLを渡せば少しおしゃれなボタンができるのでお試しあれ!
3. confirm
<?php require('vendor/autoload.php'); use LINE\LINEBot\Constant\HTTPHeader; use LINE\LINEBot\HTTPClient\CurlHTTPClient; use LINE\LINEBot; use LINE\LINEBot\MessageBuilder\MultiMessageBuilder; use LINE\LINEBot\TemplateActionBuilder\PostbackTemplateActionBuilder; use LINE\LINEBot\MessageBuilder\TemplateBuilder\ConfirmTemplateBuilder; use LINE\LINEBot\MessageBuilder\TemplateMessageBuilder; $channel_access_token = 'XXXXXXXXX'; $channel_secret = 'XXXXXXXXX'; $http_client = new CurlHTTPClient($channel_access_token); $bot = new LINEBot($http_client, ['channelSecret' => $channel_secret]); $signature = $_SERVER['HTTP_' . HTTPHeader::LINE_SIGNATURE]; $http_request_body = file_get_contents('php://input'); $events = $bot->parseEventRequest($http_request_body, $signature); $event = $events[0]; $reply_token = $event->getReplyToken(); $yes_confirm = new PostbackTemplateActionBuilder('はい', 'confirm=1'); $no_confirm = new PostbackTemplateActionBuilder('いいえ', 'confirm=0'); $actions = [$yes_confirm, $no_confirm]; $confirm = new ConfirmTemplateBuilder('メッセージ', $actions); $confirm_message = new TemplateMessageBuilder('confirm', $confirm); $message = new MultiMessageBuilder(); $message->add($confirm_message); $bot->replyMessage($reply_token, $message);日時選択アクション
ボタンやconfirmと合わせて使います。
LINE botは他のAPIと組み合わせて作成することが多いので、以下のコードで日付を送信できるということを覚えておけば何かと役立つと思い載せておきます。
<?php require('vendor/autoload.php'); use LINE\LINEBot\Constant\HTTPHeader; use LINE\LINEBot\HTTPClient\CurlHTTPClient; use LINE\LINEBot; use LINE\LINEBot\MessageBuilder\MultiMessageBuilder; use LINE\LINEBot\TemplateActionBuilder\DatetimePickerTemplateActionBuilder; use LINE\LINEBot\TemplateActionBuilder\PostbackTemplateActionBuilder; use LINE\LINEBot\MessageBuilder\TemplateMessageBuilder; use LINE\LINEBot\MessageBuilder\TemplateBuilder\ButtonTemplateBuilder; $channel_access_token = 'XXXXXXXXX'; $channel_secret = 'XXXXXXXXX'; $http_client = new CurlHTTPClient($channel_access_token); $bot = new LINEBot($http_client, ['channelSecret' => $channel_secret]); $signature = $_SERVER['HTTP_' . HTTPHeader::LINE_SIGNATURE]; $http_request_body = file_get_contents('php://input'); $events = $bot->parseEventRequest($http_request_body, $signature); $event = $events[0]; $reply_token = $event->getReplyToken(); $date_time = new DatetimePickerTemplateActionBuilder('日付を選択', 'storeId=12345', 'datetime'); $no_button = new PostbackTemplateActionBuilder('キャンセル', 'button=0'); $actions = [$date_time, $no_button]; $button = new ButtonTemplateBuilder('タイトル', 'テキスト', '', $actions); $button_message = new TemplateMessageBuilder('タイトル', $button); $message = new MultiMessageBuilder(); $message->add($button_message); $bot->replyMessage($reply_token, $message);ボタンからのリクエストの取得
ユーザーがボタンを押した時のリクエストは以下のコードで配列の形にして取得できます。
$postback_data = $event->getPostbackData(); parse_str($postback_data, $data);まだあるけどキリがないので……とりあえず以上!
最後に
LINE Messaging API SDK for PHPを使うには、記事中で挙げたSDKのソースをしっかり追う必要があり初めは中々に手間です?
今回の記事ではよく使うアクションをそのまま使えるコードを添えて書いたので、もしこれからソースを追おうとしている方などの参考になれば幸いです!少しでも参考になりましたらいいね(LGTM)やコメントなどいただけると嬉しいです!?
良いLINEbotライフを!!参考
LINE Developers APIリファレンス
line-bot-sdk-php
他にもあったのですが、昔、Qiitaで参考にした記事が見つからず……。
- 投稿日:2020-07-08T09:33:10+09:00
[PHP] Messaging APIを使ったLINEbotで色々試してみる
今回の題
API系の記事はこれで3つ目です!
前回→[PHP] Zoom APIを利用してミーティングを作成する
前々回→[PHP] YouTube APIの利用(動画情報の取得)今回はタイトルの通り、LINEbotを作りましょう!
LINE DevelopersのMessagingAPIというものを利用すれば、自分好みのLINEbotが簡単に作れます。
この記事では、
- おうむ返し
- ボタン
- confirm
- 日付選択アクション
などを作ってみます。
必要なもの
- サーバー
ssl化が必須です。
私はconohaで動かしてますが、ググるとherokuを使った記事を多く見かけました。チャネルシークレットとチャネルアクセストークンの取得
4つの段階に分けて説明していきます。
1. 開発者用のアカウントを作成
以下にアクセスし、LINEのアカウントを使ってログインしてください。
LINE Developers2. プロバイダーの作成
以下のページの左サイドバーにプロバイダーという項目があると思うので選択し、画面中央辺りの「作成」を押してください。
LINE Developers コンソール作成するプロバイダー名を求められるので適当に入力し、「作成」を押したらプロバイダーの作成は完了です!
3. チャネルの作成
プロバイダーの作成後、以下のようなページに飛ばされます。
画像内の赤枠の「Messaging API」を選択してください。
チャネルを作成する画面に飛ぶので、必須項目を全て入力し、「作成」を押したらチャネルの作成は完了です!
4. チャネルシークレットとチャネルアクセストークンの取得
チャネルの作成後、作成したチャネルの設定ページに飛ばされます。
チャネルシークレットとチャネルアクセストークンの取得はどちらもこのページを起点にします。
チャネルアクセストークン
Messaging API設定のタブの下の方に載っています。
初期状態だと何も表示されていませんが、右にある「発行」を押すと表示されます。
これもあとで使うのでコピーしておいてください。
以上でチャネルシークレットとチャネルアクセストークンがGETできました。
Webhook設定
Messaging API設定のタブの中央辺りに欄があるので、リクエストを受け取るURLを設定し、Webhookの利用を有効にします。
botを友達に追加
Messaging API設定のタブの上の辺りにQRコードがあるので読み取って友達に追加しておきましょう。
そろそろコードを書いていきます。
LINE Messaging API SDK for PHPのインストール
composerを使ってインストールします。
$ composer require linecorp/line-bot-sdkLINE Messaging API SDK for PHPのソースコードは以下です。
LINE Messaging API SDK for PHPコードの例
実際に動かしたコードをそのまま載せておきます。
なので、チャネルシークレットとチャネルアクセストークンをセットすればコピペで動きます。1. おうむ返し。
ただテキストを返すだけ!
<?php require('vendor/autoload.php'); use LINE\LINEBot\Constant\HTTPHeader; use LINE\LINEBot\HTTPClient\CurlHTTPClient; use LINE\LINEBot; //先ほど取得したチャネルシークレットとチャネルアクセストークンを以下の変数にセット $channel_access_token = 'XXXXXXXXX'; $channel_secret = 'XXXXXXXXX'; $http_client = new CurlHTTPClient($channel_access_token); $bot = new LINEBot($http_client, ['channelSecret' => $channel_secret]); $signature = $_SERVER['HTTP_' . HTTPHeader::LINE_SIGNATURE]; $http_request_body = file_get_contents('php://input'); $events = $bot->parseEventRequest($http_request_body, $signature); $event = $events[0]; $reply_token = $event->getReplyToken(); $reply_text = $event->getText(); $bot->replyText($reply_token, $reply_text);2. ボタン
<?php require('vendor/autoload.php'); use LINE\LINEBot\Constant\HTTPHeader; use LINE\LINEBot\HTTPClient\CurlHTTPClient; use LINE\LINEBot; use LINE\LINEBot\MessageBuilder\MultiMessageBuilder; use LINE\LINEBot\TemplateActionBuilder\PostbackTemplateActionBuilder; use LINE\LINEBot\MessageBuilder\TemplateMessageBuilder; use LINE\LINEBot\MessageBuilder\TemplateBuilder\ButtonTemplateBuilder; $channel_access_token = 'XXXXXXXXX'; $channel_secret = 'XXXXXXXXX'; $http_client = new CurlHTTPClient($channel_access_token); $bot = new LINEBot($http_client, ['channelSecret' => $channel_secret]); $signature = $_SERVER['HTTP_' . HTTPHeader::LINE_SIGNATURE]; $http_request_body = file_get_contents('php://input'); $events = $bot->parseEventRequest($http_request_body, $signature); $event = $events[0]; $reply_token = $event->getReplyToken(); $yes_button = new PostbackTemplateActionBuilder('はい', 'button=1'); $no_button = new PostbackTemplateActionBuilder('キャンセル', 'button=0'); $actions = [$yes_button, $no_button]; $button = new ButtonTemplateBuilder('タイトル', 'テキスト', '', $actions); $button_message = new TemplateMessageBuilder('タイトル', $button); $message = new MultiMessageBuilder(); $message->add($button_message); $bot->replyMessage($reply_token, $message);ButtonTemplateBuilderの第3引数に画像のURLを渡せば少しおしゃれなボタンができるのでお試しあれ!
3. confirm
<?php require('vendor/autoload.php'); use LINE\LINEBot\Constant\HTTPHeader; use LINE\LINEBot\HTTPClient\CurlHTTPClient; use LINE\LINEBot; use LINE\LINEBot\MessageBuilder\MultiMessageBuilder; use LINE\LINEBot\TemplateActionBuilder\PostbackTemplateActionBuilder; use LINE\LINEBot\MessageBuilder\TemplateBuilder\ConfirmTemplateBuilder; use LINE\LINEBot\MessageBuilder\TemplateMessageBuilder; $channel_access_token = 'XXXXXXXXX'; $channel_secret = 'XXXXXXXXX'; $http_client = new CurlHTTPClient($channel_access_token); $bot = new LINEBot($http_client, ['channelSecret' => $channel_secret]); $signature = $_SERVER['HTTP_' . HTTPHeader::LINE_SIGNATURE]; $http_request_body = file_get_contents('php://input'); $events = $bot->parseEventRequest($http_request_body, $signature); $event = $events[0]; $reply_token = $event->getReplyToken(); $yes_confirm = new PostbackTemplateActionBuilder('はい', 'confirm=1'); $no_confirm = new PostbackTemplateActionBuilder('いいえ', 'confirm=0'); $actions = [$yes_confirm, $no_confirm]; $confirm = new ConfirmTemplateBuilder('メッセージ', $actions); $confirm_message = new TemplateMessageBuilder('confirm', $confirm); $message = new MultiMessageBuilder(); $message->add($confirm_message); $bot->replyMessage($reply_token, $message);日時選択アクション
ボタンやconfirmと合わせて使います。
LINE botは他のAPIと組み合わせて作成することが多いので、以下のコードで日付を送信できるということを覚えておけば何かと役立つと思い載せておきます。
<?php require('vendor/autoload.php'); use LINE\LINEBot\Constant\HTTPHeader; use LINE\LINEBot\HTTPClient\CurlHTTPClient; use LINE\LINEBot; use LINE\LINEBot\MessageBuilder\MultiMessageBuilder; use LINE\LINEBot\TemplateActionBuilder\DatetimePickerTemplateActionBuilder; use LINE\LINEBot\TemplateActionBuilder\PostbackTemplateActionBuilder; use LINE\LINEBot\MessageBuilder\TemplateMessageBuilder; use LINE\LINEBot\MessageBuilder\TemplateBuilder\ButtonTemplateBuilder; $channel_access_token = 'XXXXXXXXX'; $channel_secret = 'XXXXXXXXX'; $http_client = new CurlHTTPClient($channel_access_token); $bot = new LINEBot($http_client, ['channelSecret' => $channel_secret]); $signature = $_SERVER['HTTP_' . HTTPHeader::LINE_SIGNATURE]; $http_request_body = file_get_contents('php://input'); $events = $bot->parseEventRequest($http_request_body, $signature); $event = $events[0]; $reply_token = $event->getReplyToken(); $date_time = new DatetimePickerTemplateActionBuilder('日付を選択', 'storeId=12345', 'datetime'); $no_button = new PostbackTemplateActionBuilder('キャンセル', 'button=0'); $actions = [$date_time, $no_button]; $button = new ButtonTemplateBuilder('タイトル', 'テキスト', '', $actions); $button_message = new TemplateMessageBuilder('タイトル', $button); $message = new MultiMessageBuilder(); $message->add($button_message); $bot->replyMessage($reply_token, $message);ボタンからのリクエストの取得
ユーザーがボタンを押した時のリクエストは以下のコードで配列の形にして取得できます。
$postback_data = $event->getPostbackData(); parse_str($postback_data, $data);まだあるけどキリがないので……とりあえず以上!
最後に
LINE Messaging API SDK for PHPを使うには、記事中で挙げたSDKのソースをしっかり追う必要があり初めは中々に手間です?
今回の記事ではよく使うアクションをそのまま使えるコードを添えて書いたので、もしこれからソースを追おうとしている方などの参考になれば幸いです!少しでも参考になりましたらいいね(LGTM)やコメントなどいただけると嬉しいです!?
良いLINEbotライフを!!参考
LINE Developers APIリファレンス
line-bot-sdk-php
他にもあったのですが、昔、Qiitaで参考にした記事が見つからず……。
- 投稿日:2020-07-08T05:36:46+09:00
Laravel $loop変数のプロパティと実行結果
foeach
の$loop変数のプロパティ
$loop ループ変数 プロパティ index インデックス番号 iteration 繰り返し数(1スタート) remaining 残っている要素数 count 配列の総数 first 最初の項目か last 最後の項目か even 偶数回目か odd 奇数回目か depth 入れ子レベル parent 親のループ変数(ネストの入れ子の場合) サンプル
Controller
ViewController.phppublic function foreach_loop() { return view('view.foreach_loop', [ 'weeks' => ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'] ]); }bladeテンプレート
foreach_loop.blade.php<table class="table"> <tr> <th>value</th> <th>index</th> <th>iteration</th> <th>count</th> <th>first</th> <th>last</th> <th>even</th> <th>odd</th> <th>depth</th> </tr> @foreach($weeks as $week) <tr> <td>{{ $week }}</td> <td>{{ $loop->index }}</td> <td>{{ $loop->iteration }}</td> <td>{{ $loop->count }}</td> <td>{{ $loop->first }}</td> <td>{{ $loop->last }}</td> <td>{{ $loop->even }}</td> <td>{{ $loop->odd }}</td> <td>{{ $loop->depth }}</td> </tr> @endforeach </table>実行結果
- 投稿日:2020-07-08T02:35:23+09:00
「WebShellQuickScanner」Linuxサーバの指定フォルダーのPHPファイル中に、WebShellと高リスクファイルを速いて探し出すのクイックチェックツール,そして、検査結果をTelegramにプッシュする。
「WebShellQuickScanner」とは
「WebShellQuickScanner」は、Linuxサーバの指定フォルダーのPHPファイル中に、WebShellと高リスクファイルを速いて探し出すのクイックチェックツール,そして、検査結果をTelegramにプッシュする。
「Telegram」はTelegram Messenger LLPが開発するインスタントメッセージシステムである。詳細はこちら(Telegram - ウィキペディア)をクリックしてください。
この記事は、日本語の使用ドキュメントとして発表されます。
「WebShellQuickScanner」プロジェクトのリポジトリ
Github: DeepSkyFire/WebShellQuickScanner
「WebShellQuickScanner」について
Linuxサーバの指定フォルダーのPHPファイル中に、WebShellと高リスクファイルを速いて探し出すのクイックチェックツール,そして、検査結果をTelegramにプッシュする。
しかし、検出されたファイルは削除されません。だから、これらのファイルをどうするかはあなた自分自身を決断するです。
「WebShellQuickScanner」にクイックスタート
「WebShellQuickScanner」のダウンロード
wget --no-check-certificate https://raw.githubusercontent.com/DeepSkyFire/WebShellQuickScanner/master/src/WebShellScanner.sh && chmod +x WebShellScanner.shクイックチェックをスタート
bash WebShellScanner.sh -p /data/www-data(ターゲットフォルダーを指定する)「WebShellQuickScanner」の使用方法の詳細
- 必要の依存関係
もし、検査結果をTelegramにプッシュしての機能を利用するためには、OSにcURLをインストールするは必要があります。
- 検査結果をTelegramにプッシュする
この機能を利用するためには、まず、Telegramで
@BotFather
に新しいBOTを申し込みします。そして、Telegramで@userinfobot
を使って、自分のアカウントのCHAT_IDを確認してください。注意! 現在、Telegramでは、メッセージに送信できる最大文字数を制限するようになりました。最大文字数は4096文字。もし検査結果の文字数が4096文字を超えると送信失敗となります。その以後、私は新しいプッシュ方法を更新する予定です。*
- ホスト名(Host Name)について
ホスト名を自分で指定することができます。ホスト名を指定しない場合、スクリプトは自動的にOSからデフォルトのホスト名を読み込みます。
- ログファイルの保存について
ログファイルをサーバー中に保存したい場合は、以下の設定のような設定しましょう:
bash WebShellScanner.sh -p /data/www-data -l /home/wwwwlogs注意! ログ保存フォルダーのアドレスの末尾に「/」記号を書かないでください。
- フルデモ
もし、あなたは「/data/www-data」フォルダーを検査し、ログファイルを「/home/wwwlogs」フォルダーに保存し、そして、「MyServer1」のホスト名を指定した、検査結果をTelegramにプッシュするの場合は、以下の設定にような設定しましょう:
bash WebShellScanner.sh -p /data/www-data -t TELEGRAM_BOT_TOKEN -c TELEGRAM_CHAT_ID -n MyServer1 -l /home/wwwwlogs
ヘルプメッセージを表示する
bash WebShellScanner.sh -h定期点検
Linux OSから
crontab -e
を使って、スキャンタスクを設定します。例:
15 4 * * * "/root"/WebShellScanner.sh -p "/data/www-data" -t "TELEGRAM_BOT_TOKEN" -c "TELEGRAM_CHAT_ID" -n "MyServer1" -l "/home/wwwlogs" > /dev/null上記の例では、1日1回、午前4時15分にスキャンタスクが実行される。
パラメータ(変数)の説明
WebShellScanner.sh [-h] [-p <ターゲットフォルダー>] [-t <TELEGRAM BOT TOKEN>] [-c <TELEGRAM CHAT ID>] [-n <ホスト名>] [-l <ログファイルの保存フォルダー>]使用可能なパラメータ:
-h ヘルプメッセージを表示する. オプションパラメータ(変数). -p <ターゲットフォルダー> 検査したいなフォルダー. -t <TELEGRAM BOT TOKEN> Telegram Bot Token. オプションパラメータ(変数). -c <TELEGRAM CHAT ID> Telegram Chat id. オプションパラメータ(変数). -n <HostName> カスタムホスト名. オプションパラメータ(変数). -l <ログファイルの保存フォルダー> ログファイルの保存フォルダー(ログ保存フォルダーのアドレスの末尾に「/」記号を書かないでください). オプションパラメータ(変数).オープンソースライセンス