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

【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.php
Route::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.php
Route::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.php
Route::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.php
Route::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.php
Route::get('hello', 'HelloController@index');

/helloにアクセスすると正しく表示できている。

index.phpindex.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>

ポイントはこれ

@csrf

Bladeディレクティブといい、テンプレに決まったコードを生成して書き出す。

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.php
Route::post('hello', 'HelloController@post');

POST送信はRoute::postを設定する。使い方はROoute::getと同じ。

同じアドレスでもPOST,GETのようにアクセスするメソッドが違えば両方ともに使える。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[PHP]パッケージ管理ツールComposerを図で理解する

概要

PHPのパッケージ管理ツールComposerについて図を用いてまとめました。
Composerは既にインストールしている前提で説明します。

Composerとは?

PHPのパッケージ管理ツールです。

パッケージ管理ツールとは?

プロジェクトが必要とするライブラリやパッケージを、依存関係を考慮した上で管理してくれるツールです。

依存関係とは?

ライブラリやパッケージには依存関係があります。
例えば以下のようなものです。
(1) ライブラリAを使いたい場合、ライブラリBとライブラリCが必要である
(2) ライブラリAのバージョンが2の場合、ライブラリBのバージョンは3が必要である

この例でいくと、Composerは

(1) ライブラリAを指定してインストールすると、自動でライブラリBやライブラリCもインストールしてくれる
composer_ex1.png

(2) ライブラリAをバージョン2へアップデートすると、自動でライブラリBのバージョンを3へアップデートしてくれる
composer_ex2.png
ということをしてくれます。

ライブラリの指定

プロジェクトに追加したいライブラリを指定するためのファイルがcomposer.jsonです。
composer.jsonには、プロジェクトに必要なライブラリのリストとバージョンを記載します。
Laravelの例

このファイルは直接作成&編集するか、以下のようなコマンドで操作することができます。

$ composer init # composer.jsonを作成
$ composer require パッケージ名 # composer.jsonにパッケージを追加

ライブラリの読み込み

ライブラリをインストールするためには以下のコマンドを打ちます。

$ composer install

実行すると、以下のことが起きます。

  • composer.lockが生成される
  • ライブラリのソース本体がvendorディレクトリにインストールされる

composer_ex3.png

ただし、プロジェクトに既にcomposer.lockが存在している場合はそちらの情報で優先的にインストールされます。
(チームで開発する場合や、Laravelなどのフレームワークで環境構築した場合など)

composer_ex4.png

composer.lockの有無にかかわらず、composer.jsonから再度依存関係を解決してインストールを行いたい場合は以下のコマンドを打ちます。

$ composer update

composer_ex5.png

composer.lock

composer.lockには実際にライブラリのどのバージョンがインストールされたかが具体的に記載されます。
チームで開発する場合はこれを利用することによって、開発環境のライブラリによる差分をなくすことができます。
スクリーンショット 2020-07-07 23.19.49.png

vendor

インストールされたパッケージのソース本体が格納されます。
スクリーンショット 2020-07-07 23.21.14.png

参考

Composerの導入&使い方(初心者の復習用) - Qiita
composer.json、composer.lockって何なの?という人向けのまとめ - Qiita
Composer は何者か。あるいは install と update の違い。そしてオートロードの仕組み。 | ごみばこいん Blog

最後に

Composerおじさんは賢い。ありがとうおじさん。
そのうち余裕があったらJavaScriptのパッケージ管理ツールnpmについてもまとめようと思います。
記事に間違いや不明な点なあればご指摘お願いします。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Laravel】Bladeでレイアウトを作成する

はじめに

LaravelのBladeテンプレートで使えるレイアウトの「継承」を利用し、複数の「セクション」を組み合わせてレイアウトを作成する機能をまとめます。

図説

コメント 2020-07-08 181953.png

extend

最初に記載すべき項目としてレイアウトの継承設定があります。

@extends('layouts.*')

部品側のファイルに記載することで、土台側(親)のファイルを読み込んでレイアウトを継承します。
これを書かないとそもページ自体を作ることができないので必須です。

sectionとyield

section

@section('content')
@endsection

@sectionはページで表示するコンテンツの区画を定義する事ができ、同じ名前のyieldにはめ込まれます。

yield

@yield('content')

@yieldはコンテンツの配置場場所を定義するもので、同じ名前のsectionが部品側のファイルにある場合コンテンツの内容が表示されます。

titleの様に変数名を渡す場合は@endsectionのような閉じタグを用意する必要がなく@sectionタグだけでコンテンツを定義する事ができます。

parent

@section('sidebar')
  @parent
@endsection

sectionに対応する配置場所の定義はyieldが行いますが、今回「sidebar」にはyieldではなくsectionが用いられています。この場合ははめ込みではなく既にsection内にあった内容を上書きする形になります。
そうすると親のsectionにもともとあった内容が消えてしまうので、親のsection内容を残して表示させたい時は、子のsectionの中に「@parent」ディレクティブを用意してあげる事で、親のsection内容がそこに表示されるようになります。

include

@include('名前')

@includeはsectionのようにコンテンツとしてではなく、より単純にテンプレートをただはめ込んで表示させたい場合に使用します。なのでサブビューのファイルではコンテンツをsectionで囲う必要がありません。
includeでもって来たビューの内容を「サブビュー」といいます。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel 6で認証機能を入れる

開発環境構築

以下の環境を構築した上で、そのプロジェクトで実行しています。
https://qiita.com/ryuseino/items/e0e3a77245635b7cc101

usersテーブル作成

とりあえずLaravelにデフォルトでついてくるMigrationを使ったusersテーブルでやります。
なのでまずはテーブル作成のコマンド実行。

php artisan migrate

Composerパッケージインストール

以下のコマンドを実行することで認証が簡単に出来るようになります。

composer require laravel/ui "^1.0" --dev
php artisan ui vue --auth
npm install && npm run dev

localhostを開く

開発環境構築後の確認と同じく、localhostを開いてみるとLOGINとREGISTERというリンクが上部に出ています。
スクリーンショット 2020-07-08 17.07.43.png

それぞれ極々普通のログインと会員登録の機能になっています。
そんな訳で簡単に認証が作れることが分かりました。
この段階ではまだemailのverifyなどがないので、それらは後で追加する必要がありそうです。

参考になりそうなページ

https://readouble.com/laravel/6.x/ja/authentication.html

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Slim3 Framework×slim-skeleton不使用×twigでプロジェクトを作成する(1. プロジェクト作成~各種設定)

はじめに

今回はslim-skeletonを使用しないSlim3フレームワークとtwigを使用したプロジェクトを作成します。
Slim3フレームワークおすすめチュートリアルで紹介した、
@nunulkさんのチュートリアルDaniel Opitzさんのやりかたで再現してみるイメージです。
成果物としては@nunulkさんのチュートリアルを通してできるものと同じものができます。
人の褌で相撲を取ってる感がすごいですが、許してください。

前提

下記記事で構築した環境を前提とします。

  • Windows10にVagrantをを入れてCentOS7をインストールしよう(123456)
  • ローカルでLAMP環境を構築しよう(01234
  • CentOS7にComposerをインストールしよう

  • 私家版 Slim Framework チュートリアル (123456)
    @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 rules

Front controller

Apacheのリダイレクトの設定が記述されるファイルです。以下のように記述します。

public/.htaccess
# Redirect to front controller
RewriteEngine On
# RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L]
.htaccess
RewriteEngine on
RewriteRule ^$ public/ [L]
RewriteRule (.*) public/$1 [L]

Bootstrap

名前からしてTwitter社が開発したのBootstrapのことかな?と思いましたがどうもそうではない様子。
config/bootstrap.phpに使用する各種設定ファイルについて記述し、
public/index.phpから呼び出しているようです。
config/bootstrap.phppublic/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 middleware

Routes

ルーティングを行うファイルです。以下のように記述します。

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にコミットしませんので、以下のように記述します。

.gitignore
vendor/
.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をインストール

CentOS7にComposerをインストールしよう

PHP Slim3フレームワークのサンプルアプリを作ろう

2-1. First Application Walkthrough Getting Set Upまで

Apache

DocumentRootを変更しよう

Slim3 Framework×slim-skeleton不使用×twigでプロジェクトを作成する

1. プロジェクト作成~各種設定
2. DocumentRoot変更~Twigを使用

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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) 〜 テスト編

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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");
// ------------------------------------------------------------------
?>
.env
SERVER = '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)
*** 終了 ***
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Trello投稿時に自社システムに通知する

タスク管理ツールとして大変メジャーなTrelloですが、自社システムと連携したい場合がありますよね。

この記事では以下について実装方法を説明します。
・Trelloでコメントが投稿されたら自社システムに通知

機能を実装するために「Trello Webhook API」を使用します。
Webhookとは何ぞや、と普段思っている方もいるかもしれませんが、改めて調べてみたら
「Webアプリケーションでイベントが実行された際、外部サービスにHTTP で通知する仕組み」
とヒットしました。

ここで言う「Webアプリケーション」はTrelloのことで「外部サービス」は自社システムですね。
ですからTrelloが提供しているWebhook APIが必要なのです。
使うまでの手順を優しく説明します。

1.https://trello.com/app-key にアクセス。

2.「Trello 開発契約」を確認し、「APIキーを表示」をクリック。
image.png

3.キーが表示される(このキーは後の手順で使用するため、メモしておいてください)
この画面で「Token」のリンクをクリック。
image.png

4.アクセス許可画面が表示されるので「許可」をクリック。
image.png

5.トークンが発行される(このトークンは後の手順で使用するため、メモしておいてください)
image.png

6.コメント投稿されたら自社システムに通知したいボードIDを取得します。
コマンドプロンプトやターミナルで以下のコマンドを実行しましょう。

curl "https://trello.com/1/members/[ユーザ名]/boards?key=[3で表示されたキー]&token=[5で表示されたトークン]&fields=name"

image.png
文字化けしてしまう場合は以下の方法で文字コードを変更してあげましょう。
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の説明]"

image.png

コールバックURLはTrelloでアクションがあった場合に通知してほしいURLを設定してください。
ちゃんとステータスコード200を返すURLにしてください。

8.正常に生成されたらWebhookを確認してあげましょう。
ブラウザで以下のURLにアクセスすると、正常に生成されていることがわかります。
https://trello.com/1/tokens/[5で表示されたトークン]/webhooks/
image.png

これで準備は整いました。
該当のボードにて何かアクションがあった際にコールバックURLにリアルタイムで通知がされるようになりました。
あとは自社システム側の処理ですね。

Trelloでアクションがあるとこんな感じのデータが飛んできますす。
image.png

この各項目に関するリファレンスがなかったので今度時間がある際にまとめたいと思います。
ちょっと解析していただければわかると思います。
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

                    // 以降の処理はご自由に~


                }
            }
        }
    }

以上になります。
手順に沿ってやっていただければすぐ実装できますのでぜひやってみてくださいね。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

html周りのエラー

メモ代わり

html周り弄ってた時のメモとして。
javascriptやらphpも込み込み(の予定)
都度都度更新してく。

javascriptでjsonが読み込めない(404エラーを吐かれる)

原因
知らん!
最初は「jquery使えないせいか?」とか「jsonのパス指定が間違っているか?」とも思ったがそうでもなかったし。
ただ自前のサーバーで全く同じコードでやった時はエラー吐かれなかったからサーバの設定あたりの可能性か?
オチ
jsonファイルをテキスト(.txt)に変換してそれを読み込ませたところ、問題なく動作した。
読み込むコードはこんな感じ(jQuery使用)。

sample.js
function sample()
{
    $.getJSON("latest_data.txt",(data) =>
    {/* 処理あれやこれや*/});
}

500エラー(php)

原因
構文エラーの可能性が高い。
概要箇所をよく見直す事。と昔ののボクが残したメモに書いてあった
前やらかしたやつ
・必要な部分までコメントアウトしてしまった。

sample.php
<?php
for()
{内容 //こんな感じ。右の中括弧もコメントアウトされちゃってる→}
{内容}//案1:後ろにつける。
{内容/*案2:コメント部分を囲う*/}
//案2の方は全体をコメントアウトしたいときに、ここでコメントアウト切れちゃうから個人的にあまりお勧めはしない
?>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【PHP】Blurhashでぼかし画像を生成する

概要

Blurhashを利用して、blur画像(ぼかし画像)を動的に生成します。

用途としては、実際に表示される画像の想像ができるblur画像をプレースホルダーとして表示することで、読み込み時間のUXを改善しようというものです。

▼右がblur画像を用いた例
qiita_blur1.png

Blurhashの準備

公式のGithubリポジトリからソースを入手します。
複数の言語に対応しており、今回はPHPバージョンを利用します。

環境の都合でComposerを使用せず、ソースをDLして使います。
「Download ZIP」からzipをDLすることが出来ます。
qiita_blur2.png

zipを解凍すると「php-blurhash-master」というディレクトリができます。
使い勝手を考慮して「blurhash」にリネームし、ディレクトリごと好きな場所に置きます。

Blurhashを実装

Blurhashで行う処理はエンコードとデコードの2つです。

①オリジナル画像をblur画像化し、短い文字列を生成する(エンコード)
②文字列をblur画像に戻す(デコード)

qiita_blur.png

まずは必要なファイルを読み込みます。
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

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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をインストールする

問題までの経緯

  1. モデルファイルをアプリ名ディレクトリ/app直下からアプリ名ディレクトリ/app/Models直下に移動した。(Modelsディレクトリはmkdirコマンドにて作成した。)

  2. Laravelアプリ名ディレクトリで下記コマンドを実行してtinkerを開いた。

    $ php artisan tinker
    
  3. 下記を実行してuse宣言を行った。

    use App\Models\モデルファイル名
    
  4. 下記を実行してidカラムが1のレコードのデータを取得しようとした。

    $info = モデル名::find(1)
    

問題

  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.

問題解決までの経緯

  1. データの取得に使用するモデルファイルを確認した。下記にモデルファイルの内容を記載する。

    アプリ名ディレクトリ/app/Models/モデルファイル.php
    <?php
    
    namespace App;
    
    use Illuminate\Database\Eloquent\Model;
    
    class モデルファイル名 extends Model
    {
        //
    }
    
  2. モデルファイルの設置場所を変更したにもかかわらずモデルファイル内のnamespaceの記載を変更していなかった。

  3. 下記の様にモデルファイルを修正した。

    アプリ名ディレクトリ/app/Models/モデルファイル.php
    <?php
    
    namespace App\Models;
    
    use Illuminate\Database\Eloquent\Model;
    
    class モデルファイル名 extends Model
    {
        //
    }
    
  4. 下記の手順を実施して正常にidが1のレコードのデータを取得できたことが確認できた。

    1. Laravelアプリ名ディレクトリで下記コマンドを実行してtinkerを開く。

      $ php artisan tinker
      
    2. 下記を実行してuse宣言を行う。

      use App\Models\モデルファイル名
      
    3. 下記を実行してidカラムが1のレコードのデータを取得した。

      $info = モデル名::find(1)
      
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[最新版] 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 Developers

2. プロバイダーの作成

以下のページの左サイドバーにプロバイダーという項目があると思うので選択し、画面中央辺りの「作成」を押してください。
LINE Developers コンソール

スクリーンショット 2020-07-08 5.00.01.png

作成するプロバイダー名を求められるので適当に入力し、「作成」を押したらプロバイダーの作成は完了です!
スクリーンショット 2020-07-08 5.12.40.png

3. チャネルの作成

プロバイダーの作成後、以下のようなページに飛ばされます。
画像内の赤枠の「Messaging API」を選択してください。
スクリーンショット 2020-07-08 5.13.55.png

チャネルを作成する画面に飛ぶので、必須項目を全て入力し、「作成」を押したらチャネルの作成は完了です!
スクリーンショット 2020-07-08 5.20.24.png

4. チャネルシークレットとチャネルアクセストークンの取得

チャネルの作成後、作成したチャネルの設定ページに飛ばされます。
チャネルシークレットとチャネルアクセストークンの取得はどちらもこのページを起点にします。
スクリーンショット 2020-07-08 5.42.04.png

  • チャネルシークレット
    チャネル基本設定のタブの下の方に載っています。
    あとで使うのでコピーしておいてください。
    スクリーンショット 2020-07-08 5.48.50.png

  • チャネルアクセストークン
    Messaging API設定のタブの下の方に載っています。
    初期状態だと何も表示されていませんが、右にある「発行」を押すと表示されます。
    これもあとで使うのでコピーしておいてください。
    スクリーンショット 2020-07-08 5.53.32.png

以上でチャネルシークレットとチャネルアクセストークンがGETできました。

Webhook設定

Messaging API設定のタブの中央辺りに欄があるので、リクエストを受け取るURLを設定し、Webhookの利用を有効にします。
スクリーンショット 2020-07-08 9.10.50.png

botを友達に追加

Messaging API設定のタブの上の辺りにQRコードがあるので読み取って友達に追加しておきましょう。

そろそろコードを書いていきます。

LINE Messaging API SDK for PHPのインストール

composerを使ってインストールします。

$ composer require linecorp/line-bot-sdk

LINE 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で参考にした記事が見つからず……。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[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 Developers

2. プロバイダーの作成

以下のページの左サイドバーにプロバイダーという項目があると思うので選択し、画面中央辺りの「作成」を押してください。
LINE Developers コンソール

スクリーンショット 2020-07-08 5.00.01.png

作成するプロバイダー名を求められるので適当に入力し、「作成」を押したらプロバイダーの作成は完了です!
スクリーンショット 2020-07-08 5.12.40.png

3. チャネルの作成

プロバイダーの作成後、以下のようなページに飛ばされます。
画像内の赤枠の「Messaging API」を選択してください。
スクリーンショット 2020-07-08 5.13.55.png

チャネルを作成する画面に飛ぶので、必須項目を全て入力し、「作成」を押したらチャネルの作成は完了です!
スクリーンショット 2020-07-08 5.20.24.png

4. チャネルシークレットとチャネルアクセストークンの取得

チャネルの作成後、作成したチャネルの設定ページに飛ばされます。
チャネルシークレットとチャネルアクセストークンの取得はどちらもこのページを起点にします。
スクリーンショット 2020-07-08 5.42.04.png

  • チャネルシークレット
    チャネル基本設定のタブの下の方に載っています。
    あとで使うのでコピーしておいてください。
    スクリーンショット 2020-07-08 5.48.50.png

  • チャネルアクセストークン
    Messaging API設定のタブの下の方に載っています。
    初期状態だと何も表示されていませんが、右にある「発行」を押すと表示されます。
    これもあとで使うのでコピーしておいてください。
    スクリーンショット 2020-07-08 5.53.32.png

以上でチャネルシークレットとチャネルアクセストークンがGETできました。

Webhook設定

Messaging API設定のタブの中央辺りに欄があるので、リクエストを受け取るURLを設定し、Webhookの利用を有効にします。
スクリーンショット 2020-07-08 9.10.50.png

botを友達に追加

Messaging API設定のタブの上の辺りにQRコードがあるので読み取って友達に追加しておきましょう。

そろそろコードを書いていきます。

LINE Messaging API SDK for PHPのインストール

composerを使ってインストールします。

$ composer require linecorp/line-bot-sdk

LINE 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で参考にした記事が見つからず……。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel $loop変数のプロパティと実行結果

foeachの$loop変数のプロパティ

$loop ループ変数 プロパティ
index インデックス番号
iteration 繰り返し数(1スタート)
remaining 残っている要素数
count 配列の総数
first 最初の項目か
last 最後の項目か
even 偶数回目か
odd 奇数回目か
depth 入れ子レベル
parent 親のループ変数(ネストの入れ子の場合)

サンプル

Controller

ViewController.php
public 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>

実行結果

Screen Shot 0032-07-08 at 5.37.34.png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

「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 <ログファイルの保存フォルダー> ログファイルの保存フォルダー(ログ保存フォルダーのアドレスの末尾に「/」記号を書かないでください). オプションパラメータ(変数).

オープンソースライセンス

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む