ラベル PHP の投稿を表示しています。 すべての投稿を表示
ラベル PHP の投稿を表示しています。 すべての投稿を表示

2016-11-01

【Stripe】PHPで課金するための基本設定

課金サービスを簡単に組み込めるサービスとして、審査も必要がなくとても手軽な「stripe」に注目しています。
この記事を投稿する少し前まではトップページにはベータ版だとの記述がありましたが現在はそれもなくなり、本格的に日本でもリリースがされたようです。

そこで、今回は stripe で月額課金を利用するために必要な基本的な設定とアクセスキーの取得法を備忘録として投稿したいと思います。



1.まずはアカウントの作成

以下のURLからアカウントを作成しましょう

https://dashboard.stripe.com/register


2.月額課金するプランを作成

メニューリンクの中から「Plans」をクリックし、その後ページ右上にある「New」をクリックします。


以下のようなプラン作成フォームが表示されます。
最低限必要な項目は以下になります。

  1. ID (←プログラム上で利用する識別IDです。)
  2. Name (←課金名。見てわかりやすい名前をつけましょう)
  3. Currency (←通貨。JPYが日本円です。おそらくデフォルトです)
  4. Amount (←課金額。いくら課金するか?です)
  5. Interval (課金する間隔) 
入力したら、「create plan」 をクリックして保存します。


3.アクセスキーを取得する

ページ右上にある「Your Account」の中にある「Account Settings」をクリック。


現れたダイアログの中にある「API Keys」をクリックすると以下のようにアクセスキーが表示されます。

上がテスト用のキー。
下が本番用のキーになります。



以上がAPIに必要な設定&キーの取得になります。

実際にPHPに組み込むためにはライブラリが用意されていますのでそちらをつかうといいでしょう。

https://stripe.com/docs/libraries#php-library
https://github.com/stripe/stripe-php

Laravelを使っている場合はCashierというパッケージが本家Laravelによって提供されていますのでこちらを使う方がいいでしょう。

https://laravel.com/docs/5.3/billing#stripe-configuration


以上になります。

※それにしてもドンドン便利なサービスが増えてきていろいろな事が簡単にできるようになってきています。それだけ可能性が広がっているということなので今後も楽しみですね。^^



2016-09-10

PHPで国コードとその他情報を取得するクラスを公開しました

最近ウェブサイトの開発のご相談を頂く際にグローバルな視点で物事を考えているクライアント様方が増えてきたように思います。

その中で度々懸案事項となっていたことは、国コードを管理できるパッケージがあまり見つからないということでした。(あるのはありましたが、残念ながら日本語/英語の国名、2桁コード、3桁コード、数字コードが揃っているものではありませんでした)

そこで!
今後のことを考え独自に ISO 3166-1 をベースとしたパッケージを作成し、公開しました。
以下よりダウンロード or Composer によるインストールが可能です。

GitHub | SUKOHI/CountryCode

今回はフレームワークのパッケージではなく、純粋なPHPパッケージとしての公開ですので、いろんな環境でご利用いただけると思います。
みなさんのお役にたてたら嬉しいです(^^)


ちなみに、取得できるデータの例としては以下のような感じです。

【日本の例】

国コード(2桁) ・・・ JP
国コード(3桁) ・・・ JPN
数字コード ・・・ 392
国名 ・・・ Japan(英語)、日本(日本語)

実際の使い方はGitHubの方でご覧ください。

※なお、もし英語、日本語以外で国名を翻訳できる方は「assets/csv/country_codes.csv」にデータを追加するだけで新しい言語に対応ができます。よかったら GitHub にて Pull Request していただけるとなお嬉しいです! m_ _m

ではでは〜。
(最近ブログ記事をさぼってしまっているので時間を見つけて更新しなければ!)


2016-05-24

n倍でループ【PHP】

PHPに限らずプログラムで開発をするよく使うものの一つに for() ループがあると思います。
今回はいつもとは少し変わったループの仕方を紹介したいと思います。

通常でしたら、以下のように $i++ インクリメントを使って1ずつ変数を追加していくパターンを使うかと思います。
for($i = 0 ; $i < $count ; $i++) {
    // ここで何かの処理
}

もしくは逆に $i-- を使って変数を減らしていく方法もたまに使うのではないでしょうか。
for($i = 5 ; $i > 0 ; $i--) {
    // ここで何かの処理
}

では、今回は for() ループを nの倍数ずつループさせる方法はどうなるでしょうか。
いろいろな方法があると思いますが、ひとつの答えとしては以下のようなものもあります。
$n = 3;
$count = 15;

for ($i = 0; $i < $count; $i+=$n) {
   echo $i ."\n";
}

実行結果としては、以下になります。
0
3
6
9
12
ではひとつずつ中身を見て行きましょう。


$n = 3
これは何倍ずつループするかです。
つまりループを3、6、9...という形にしたい場合は「3」になります。

$count = 15;
最大値はいくらかになります。
つまり、もし15を含めたい場合は $count = 16; に変更するか
for() 内の $i < $count$i <= $count へ変更する必要があります。

ここまでは通常の for() ループを同じですね。
では次。

for ($i = 0; $i < $count; $i+=$n) {}
  1. $i = 0 ・・・初期値が0
  2. $i < $count ・・・ 最大値
  3. $i+=$n ループのたびに倍数を追加
ここが今回の特徴的な部分です。 
$i++ の代わりに $i+=3 を使ってループ内の変数を倍数にしています。

はい。
短いですが、以上解説でした。


【終わりに】
通常はあまりこのようなループを使うことは無いでしょうし、だとすると「正直可読性悪いんじゃ、、、?」と言われると確かにそのとおりですが、これもひとつのアイデアなのかなと思い紹介してみました。(もしかすると結構使われてるのかな?)

今回は以上です。




2016-05-11

PHPで休日を管理するなら yasumi【サンプルあり】

ウェブサイトの開発を進めているとたまに必要となってくるものに「祝日、休日の取り扱い」があります。
祝日・休日は結構厄介で、最近で言うと「山の日」など新たに制定されたり、突然名前が変わってしまう場合もあるため、これまでは Google Calendar APIから取得をするというのが定石だったかと思います。

ただ、GoogleのAPIは変更が大きく、また廃止されてしまうものも少なくないため最近は極力は使用しないようにしています。

そこで、何か別のアプローチ方法はないかと考えていたところ、とても便利なパッケージを発見したので試してみました。

その名は「Yasumi」です。(←開発者は日本の方っぽいです)
世界各国の言語での翻訳にも対応しているようなので、もちろん日本語の祝日・休日の名前も取得できますよ。


【インストール】
composer を使ってインストールできます。
composer require azuyalabs/yasumi

【使い方】
使い方はとても簡単で、Yasumi::create() の引数に
  1. どこの国の祝日・休日を取得するか
  2. 取得したい祝日・休日は西暦何年か
  3. (オプション)翻訳する言語はどこか
を設定するだけで1年間の全祝日・休日を取得することができます。

use Yasumi\Yasumi;

$holidays = Yasumi::create('Japan', 2016, 'ja_JP');

foreach ($holidays as $holiday) {

   echo $holiday->format('Y-m-d') .': '. $holiday->getName() .'<br>';

}

【サンプル】


ちなみにこのパッケージも将来的にサポートされなくなってしまう可能性はありますがMITライセンスでの公開ですし、この記事を書いている時点で240ものスターがついているのでおそらくGoogle のAPIを利用するよりは安定性は高いと考えています。

いざとなったらPull Request やフォークして使えますしね。

ではでは、今回は以上です。


(休みほしい...笑)



2016-04-21

PHPで画像を扱うならinterventionが便利

PHPでの開発をしているとよく必要になってくる機能の一つに「画像のアップロード」というのがあります。
画像の送信自体は input タグの type file を利用すれば簡単に実行できるのですが、いざ送信された画像のリサイズやトリムなどをしようとするとトタンに計算やらを行う必要がでてきます。

そんな時は intervention の出番です。

intervention は直感的に画像の編集ができるようになっているのでとてもおすすめです。
ということで今日は intervention の記事をお届けしたいとおもいます。


【準備】

intervention は composer でインストールできます。
(ホントに composer は便利ですね^^)

composer require intervention/image


【使い方】

1.まずは画像を読み込みます。

intervention は様々な画像の読み込み方法が用意されていて、以下がその全てになります。

  • ローカル画像のパス
  • 画像のリソース
  • GDのリソース
  • 画像のURL
  • (Laravelの場合は)アップロードされた画像を取得するメソッド

今回は基本的な利用法として画像のパスから読み込む方法を見ていきましょう。

$img = Image::make('example.jpg');

はい。
たったこれだけで画像編集の準備が完了です。

後は、画像の大きさを変更したり様々な編集ができるわけですがここでは基本的なメソッドを紹介します。

・サイズの変更(リサイズ)


$img->resize(300, 200);

横と縦の長さを入力するだけで完了します。
もしどちらかの数値に null を指定した場合は元の長さになります。
つまり、

$img->resize(null, 200);

とした場合、元の画像の横の長さが500pxだったとすると画像のサイズは 500×200 px になります。


・クロップ(切り取り)


$img->crop(100, 100, 25, 25);

crop() は画像の一部を切り取るメソッドです。
引数は、

  1. 切り取る長さ
  2. 切り取る高さ
  3. 切り取りを開始する位置(X座標)・・・任意
  4. 切り取りを開始する位置(Y座標)・・・任意

となります。


・fit(フィット)



$img->fit(500, 360);

fix() メソッドを利用すると画像が指定したサイズいっぱいになるように自動で切り取りとリサイズを行ってくれます。
つまり、 編集後の縦横比が違っている場合は画像の縦か横が切り取られることになります。
(上のサンプル画像は横が切り取られています)


・rotate(回転)


$img->rotate(-45);

rotate() は画像を回転させるメソッドです。
数値にはマイナスも指定できます。


・text(文字を挿入)


text() を利用すると画像の中に文字を挿入することができます。テレビのテロップみたいなものですね。

$img->text('Deep code is beautiful!!', 50, 50);

引数は

  1. 挿入したい文字
  2. X座標
  3. Y座標

ちなみに日本語を利用する場合は以下のようにフォントを指定しないといけません。
また、画像の色を指定したい場合もこのようにクロージャを利用して指定します。

$img->text('ディープ・コーブの景色は感激です!', 10, 25, function($font) {
   $font->file('sazanami-gothic.ttf');
   $font->size(22);
   $font->color('#ee0000');
});


・insert(画像の挿入)

$img->insert('face.jpg');

insert() は画像の中に別の画像を挿入するメソッドです。
サンプルのように好きな位置に別の画像(上のは私の顔写真です)を重ねることができます。
画像にロゴなどを追加したい場合に利用できると思います。

もし画像の中央に挿入したい場合は

$img->insert('face.jpg', 'center');

と「center」を追加するだけでOKで、それ以外にも
  • top-left (default)
  • top
  • top-right
  • left
  • center
  • right
  • bottom-left
  • bottom
  • bottom-right
が利用できます。
また、

$img->insert('face.jpg', 'bottom-right', 10, 10);

とX、Y座標を指定するとその長さの分だけ中央に寄せることもできます。


・opacity(透明化)


$img->opacity(50);

opacity() を使うと画像を透明にすることができます。
数値が100の場合、透明にはなりません。


・save(画像の保存)

$img->save('example.jpg');

もし png や gif などで保存したい場合は「example.png」「example.gif」とすればOKです。
また、以下のようにすることで画像の質を変更することも可能です。
(100が一番質がいい状態です)

$img->save('example.jpg', 60);


・encode(画像の変換)

encode() は画像の形式を変換することができます。
また以下のようにすることで直接画像を表示させることもできます。

header('Content-Type: image/png');
echo $img->encode('png');

ちなみに利用できる画像形式は以下になります。
  • jpg
  • png
  • gif
  • tif
  • bmp
  • data-url

・iptc & exif(画像データ

iptc() と exif() は画像に埋め込まれた文字データを読み取ります。

【IPTC】

1.IPTCの全データを取得
$data = Image::make('public/foo.jpg')->iptc();
2.Copyright だけを取得
$copyright = Image::make('public/foo.jpg')->iptc('Copyright');

【EXIF】

1.EXIFの全データを取得
$data = Image::make('public/foo.jpg')->exif();
2.Model だけを取得
$name = Image::make('public/foo.jpg')->exif('Model');


・width、height、filesize(各種画像のデータ)

echo $img->width();
echo $img->height();
echo $img->filesize();

そのまま、上から

  1. 画像の横幅
  2. 画像の縦幅
  3. ファイルサイズ

を取得することができます。


ということで、今回は便利な画像編集パッケージの intervention の使い方をお届けしました。
今回は紹介できませんでしたが、 intervention には線や丸を書いたりするなど他の機能もありますので興味のある方はぜひトライしてみてください。

ではでは。


2016-04-01

PHPの自動テストcodeception【実行サンプルDL可】

開発を多数こなしていると、やはり感じるのは実行テストというのはなかなか難しいなということです。
というのも、やはりプログラムを組んだ本人はもちろんそれでうまくいくと信じてコードを書いているわけで、残念ながら基本的なバグに気がつかなかったりします。

この辺は前から懸案だったたのですが、「じゃあ自動テストは?」というと人の目でチェックしていないため完璧ではなく、しかも時間がかかり、さらにテストコードすらテストが必要になるんだろ?というのが頭にずっとあったため正直言うと敬遠してきたという経緯があります。

しかし、今回は「デバッグの効率化」という観点から現在人気があり、なおかつとてもシンプルに自動テストができる「Codeception」を体験してみました。
雑感としてはとても好感触です。
今後は納品する際にテストの結果をつけてもいいのかなと考えています。

・・・と、いうことで今回は「Codeception」のインストール〜Acceptance testの基本的な使い方をご紹介します。


【Codeceptionの実行結果サンプル】




【実行環境】
OS: Ubuntu 14.04
言語: PHP 5.6.19


【インストール】
ここではグローバルで利用ができるようにインストールする方法です。
以下のコマンドをターミナルから実行します。

sudo curl -LsS http://codeception.com/codecept.phar -o /usr/local/bin/codecept
sudo chmod a+x /usr/local/bin/codecept

はい。これで codecept コマンドが利用できるはずです。
codecept -v
を実行すると 2.1.7 がインストールされていました。
(ちなみに2016/03/31の時点で2.2 は今ベータ版だそうですので、すぐに正式版が出そうですね。)


【自動テストの開始】
ターミナルでテスト実行したいサイトのルートフォルダへ移動して以下のコマンドを実行します。
codecept bootstrap
これを実行すると、以下が作成されます。

1. codeception.yml
2. testsフォルダ


【Acceptance Test の設定】 

tests/acceptance.suite.yml ファイルを開いてトップページのURLをセットして保存します。
class_name: 
AcceptanceTester
modules:
    enabled:
        - PhpBrowser:
            url: {あなたのチェックしたいサイトのトップURL}
        - \Helper\Acceptance


【自動テストファイルの作成】

codecept generate コマンドを使って個別の自動テストシナリオを作成します。

codecept generate:cept acceptance Welcome

これは、「Welcome」という名前のAcceptance Test(受け入れテスト)をするファイルを作成するという意味になります。
そして、実行後は以下にファイルが作成されますのでここに実際に命令を追加していくことになります。

・tests/acceptance/WelcomeCept.php


では実際の例を見てみましょう。

(実際の例)
$I = new AcceptanceTester($scenario);
$I->wantTo('フォームエラーをチェック');
$I->amOnPage('/form_error');
$I->see('フォームエラーのテスト');
$I->click('送信する');
$I->see('メールアドレスは必須です。');
 見ての通り、シンプルな英語の文法とほぼ同じなのでとても簡単に追加ができます。

1行目はお約束の文章。($Iは「私」のアイです。)
2行目「wanTo」はこのファイルで実行するテストの要約です。実行テスト自体には関係ありません。

3行目からが自動テストの本体になります。具体的には、

amOnPage(): 「/form_error」にアクセス
see(): 「フォームエラーのテスト」という文字があるか確認
click(): 「送信する」ボタンをクリック
see: 「メールアドレスは必須です。」という文字があるか確認

となります。
つまり、チェックの流れとしては、

1. わざとメールアドレスを入力せずに
2. 送信ボタンをクリック
3. エラーが表示

となります。

以上、本当に基本的ですが以下にシンプルかを知ってもらいたかったのでこの辺で終了します。
他にも「DBにデータが存在してるのか?」 といったチェックもできるので興味のある人は以下からチェックしてみてください。

Codeception(英語)
Codeceptionの公式ドキュメントの日本語化(ガイドのみ)


(ちなみに)
この動画はCodeception入門者にはとてもわかり易いと思います。
ホントに便利な時代になりましたよね。



(終わりに)
ふと、クライアントにテスト結果を提出するとき英語じゃやっぱり嫌がられるのかな...?と感じました。
時間ができたら自動翻訳ページ作ってみても面白いかもしれません。
あと、JavaScriptは実行できないのでその辺は Selenium  などとも連携できるようなのでまたトライしてみたいと思います。







2016-03-29

【Blade】Laravelテンプレートの便利な書き方

昨日RedditのPHP板でテンプレートエンジンの話が出ていて興味をもったので、この際、Laravelのテンプレートエンジン「Blade」でできる便利な書き方を(@extends@sectionなどのメインは省いて)3つまとめてみました。




 1.「or」でチェックを省略ができる

もし変数に何も入っていない可能性がある場合、Blade内でPHP記法を使うと以下のようになります。
@if(isset($test))
    {{ $test }}
@else
    変数の中身がありません。
@endif
どの言語でもおなじみの if文ですね。
でもBladeを使うと上の5行がたった1行でできるようになります。
それが「or」です。
{{ $test or '変数の中身がありません。' }}
どうでしょう。
三項演算子を使うと1行でも書けなくはないですが、おそらくこちらの方がデザイン担当の人が見てもわかりやすいんじゃないでしょうか。
もちろん以下のようにいろんな変数名を指定できます。
{{ $blog->title or 'Default' }}


2.「forelse」でもチェックを省略できる

PHPで配列をひとつずつ取り出して計算をする際には for や foreach を使うと思います。
Blade でもこのループの書き方は同じで以下のようになります。
@if($posts->count() > 0)
    @foreach($posts as $post)
        {{ $post->title }}
    @endforeach
@else
    データが見つかりませんでした。
@endif
このケースではDBからデータを取得しているので count() を使ってデータが入っているのかをチェックしています。
なんだか少しゴチャゴチャしていますね。

これがBladeでは以下のように書くこともできます。
@forelse($posts as $post)
    {{ $post->title }}
@empty
    データが見つかりませんでした。
@endforelse
表示がスッキリしました。
「できるだけエラーを出さないためにはできるだけコードを書かないこと」という原則を考えるならこちらの方が断然方がいいですね。
もちろん、 foreach と 同じく、以下のようにインデックスも取得できます。
@forelse($posts as $index => $post)


3.各言語を呼び出す

これは日本語圏の環境では利用する機会は少ないかもしれませんが、翻訳された単語を取得する際、より省略した記述をすることができます。
Laravelでは trans() もしくは Lang::get() という2つの取得法があるため通常は以下のようになります。
{{ trans('validation.accepted') }}
{{ Lang::get('validation.accepted') }}

これがBladeではこう書くことができます。
@lang('validation.accepted')
文字数的にはそこまで差はありませんが、横のヒゲがなくなっているので可読性は上がっていると思います。

以上、短いですがBladeの便利な書き方でした。
ちなみに最近は Twig (←小枝という意味みたいです)という高機能なテンプレートエンジンも人気があるようですが、どうやらPHPのコードを直接追加できならしく、またBladeの方が軽いらしいので、私の場合はもし採用するとしてももう少し先になるかなーと思いました。

(それにしても、PhpStormから直接貼り付けるとコード部分が楽に作成できていいですね。^^)



2016-03-25

【PHP】独自パッケージを composer で使えるようにする方法

以前「Laravel の独自パッケージを作成する「PackageCreator」を公開しました」で書いたように、今回は作成した独自パッケージを公開し、さらに composer でインストールするまでを紹介したいと思います。



手順としては、以下の2点です。

1.Githubへパッケージをアップする 
2.Packagistへパッケージ登録

(※事前準備として、GithubPackagistにアカウント登録し、composer 、git が使えるようにしておいてください。)



それでは、ひとつずつ見ていきましょう。


1. Githubへパッケージをアップする

まずGithub にログインし、独自パッケージ用のレポジトリを作成します。
右上にあるボタンをクリックした時に出てくる「New repository」をクリック。



パッケージ名と説明文を入力、さらに「Initialize this repository with a README」にチェック✔を入れてボタンをクリックすれば完了です。



次にローカル環境でターミナルを開き、cd コマンドをつかって独自パッケージのディレクトリまで移動しましょう。


ここで git の初期化コマンドを実行します。

git init


そして、git pull を使って先ほど Github レポジトリからファイルを取り込みます。

git pull https://github.com/xxxxxxxx/xxxxxxxx.git

※ちなみに、レポジトリの git URLは以下の場所に書かれています。




はい!
これでローカル環境からファイルをアップロードできるようになりました。



続いて composer init を使って composer に必要なファイル「composer.json」を作成しましょう。
以下のコマンドを実行すると、パッケージ名や説明文を聞かれるので入力していきます。
重要なのは以下の3つ。

Package name (<vendor>/<name>)  ・・・ パッケージ名
Description ・・・ パッケージの説明文
License・・・ パッケージのライセンス。後でPackagistで注意されるので^^;

これで composer.json が出来上がります。


ちなみに、もしコマンドラインが好きじゃない人は普通に composer.json を作ってもOKですし、後から変更するのも普通にエディタから変更することができます。


そして、README.md も適宜変更しましょう。
このファイルは markdown という形式で作成する必要があります。(こちらのページがとても便利だと思います。)


さぁ、それではやっと Github へのアップロードです。
実際には以下のようにして行います。

git add .
git commit -m="First commit"
git push https://github.com/xxxxxxxx/xxxxxxxx.git master

この時ログインID, パスワードを聞かれたら入力してください。
アップロードがうまくいっていれば Github ページが変更になっているはずです。


はい!
ここまでがGithubへのアップロード手順です。



(今回は記事が長いね...分けたほうが、良かったね....)



2.Packagistへパッケージ登録

では次に packagist です。
ログインして右上の「submit」から登録ページへ移動し、githubで先ほどつくったページのURLを入力してパッケージを登録します。


これでパッケージが composer からインストールできるようになっているはずです。
実際にはこのような形になります。

composer require sukohi/xxxxxx:dev-master

※sukohi/xxxxx の部分は composer.json の name にかかれている値です。



ちなみに、Github のウェブフックを使えば git push されるたびに自動で packagist も最新版にアップされるのでぜひ設定しておきましょう。
やり方はこんな感じです。

1.まず packagist からトークンを取得します。


2.先ほどつくった Github のパッケージページから setting > Webhooks & services へ移動し、「Add Service」ボタンの中から Packagist を選択します。
すると、以下のようなページが表示されるので先ほど Packagist のユーザー名と取得したAPIトークンを入力しましょう。

これでウェブフックの設定は終了です。


(あと1トピックだけ、、、)


また将来のことを考えると git で 1.0 や 1.0.0などブランチとタグをつかってバージョンを作成しておくといいと思います。
やり方は以下。

(ブランチ)

git branch 1.0
git checkout 1.0
git push https://github.com/xxxxxxxx/xxxxxxxx.git 1.0

(タグ)
git tag 1.0.0
git push https://github.com/xxxxxxxx/xxxxxxxx.git 1.0.0

※もしバクを修正したり新しい機能を追加したらブランチを同じようにpush し、タグを「1.0.1」というのようにバージョンを上げて push しましょう。
ウェブフックを設定しているなら自動で packagist も最新版になっているはずです。


composer でバージョンを指定してインストールするには以下のようにします。

composer require sukohi/xxxxx:1.*

はい!
これで終了です。

独自パッケージを作って公開しておけば、後から同じ作業を省略できますし、もしバグがあれば他のユーザーから教えてもらえるかもしれないのでメリットは多いですよ!

なにより自分のパッケージにスターがついたりするととてもテンションが上がります。
ぜひみなさんもトライしてみてくださいね。
ではでは〜!(^o^)


 (スマホで記事の原案を書くとなぜか記事が長くなるなー)


2016-03-10

【PHP】顔認証の精度をあげるためやったこと

とある開発で画像から顔だけを切り出す必要あったので、いろいろとGoogleさんで探っていたらすでに「php-facedetection」というパッケージを公開している人がいました。

やっぱり世界中には天才的なプログラマがゴロゴロしてるんだなーと関心しつつ、なによりPHPでも画像から顔だけを切り出すことができるという事実にとても感動しました。
デジタルとリアルが融合してる気がしたんですね(笑)

ってことで早速誰かの顔を抽出しよう!
・・・とはならず、まずどうやって(効率的に)顔を検出しているのかが気になってしょうがなかったのでこれもGoogleさんで探ってみました。

するととてもわかりやすく説明してくれている記事を発見!
このページはまるでテレビ番組のように「Viola & Johns」と呼ばれる顔認証テクニックをわかりやすく紹介してくれています。
↓↓↓

サルでもわかる顔検出の原理


この記事を読むと顔が入っている画像には共通のパターンがあって、それを利用することで顔認証をショートカットしているようです。
やっぱり賢い人はすごいねー。

ひと番組楽しんだ感覚を覚えた後、「php-facedetection」を使って実際に顔検出をやってみました。


すごい!

こんなに簡単に画像から顔を抽出するなんて。。
その昔ニュートンが「俺が遠くまで見渡せるのは巨人の肩の上にのっかってるからだぜ」って名言を思い出しましたよ。


しかし!

顔を自動で抽出してくれるのはいいんだけど、画像によってはやっぱり精度がよくなったりする。
というのも、実際には顔じゃないものまで顔として検出してしまうことが少なくなかったから。

…ってことで僕も今いる巨人の肩の上でさらにつま先立ちができるよういろいろと考えてみました。
まず考えたのは、色を使ってフィルターをかける方法です。

この方法は「顔は基本的に肌色なんだから肌色が適度に含まれているものだけ抽出する」というものです。
実際には以下のページを参考にどんな色がどれだけ含まれているかを抽出してみました。

http://stackoverflow.com/questions/3468500/detect-overall-average-color-of-the-picture/3468588#3468588

そして、「肌色が他の色の何%になっているか」を計算して、それがある範囲以内なら「顔」として判断するようにすると期待通り、少しだけ精度が上がりました。
(今回ターゲットにした色は['FFCC99', 'CC9966', 'CC9999', 'FFCCCC']の4つです)


でも、でも、、、それでもまだ顔じゃないものまで検出されてしまう。。。

んー、もうこのまま妥協しようかとも思った瞬間にひとつアイデアが浮かびました。
php-facedetection抽出してくれる顔は、もちろん顔だけじゃなく髪の毛や背景なども含まれています。

じゃあ、「画像の真ん中だけをくり抜いて、そこに肌色ばっかり残ってたらほぼ顔ってことになるんじゃ?」

ってことで早速やってみたらさらに精度があがってほぼたまにしか顔じゃないものを検出しなくなりました。

とまぁ、色を使ってフィルターをかけることで(今のところは)満足がいく精度で顔画像だけを抽出することができました。
めでたしめでたし。^-^

(それでもたまーに顔以外もはいってくるし、そもそもphp-facedetectionは画像につきひとつしか顔を検出できないけどね。。^^;)


どうやら以下のページのように画像から肌色だけを抽出するというアプローチもあるみたいです。
時間ができたらいつか機械学習も含めて勉強してみようかな、、、英語の勉強が終わったら(笑)

https://www.blogger.com/blogger.g?blogID=6545450414259005128#editor/target=post;postID=6012962723697327725


※ちなみに僕の好きなX Japanで顔認証をためしたらギタリストの Pataさんが検出されました。ファンとして早いご回復を切に願っています。m_ _m


2016-01-31

PHPでユーザー管理するならSentinelが便利すぎる!

カナダからの帰国後気持ち的にも少し落ち着いてきたので、ここいらでよく利用しているパッケージの使い方を再度おさらいしようというモチベーションが(なぜか)高まってきました。
そこで、今回は機能が豊富でとても使いやすいユーザー管理パッケージ「Sentinel」をご紹介したいと思います。



【Sentinelの感想】まさにかゆいところに手が届く感謝感激のパッケージです!


1.まずは主な特徴
  • ログイン/ログアウト(当たり前ですけど^-^;)
  • ユーザーに役割をもたせられる
  • パスワードリマインダー機能
  • パスワードを自動で暗号化して保存
  • ユーザー登録時のアクティベーション機能(選択可)
  •  ユーザー名(姓と名)をデフォルトで保存可能
などなど。
あとは私の大好物、Laravelにも対応しています。(バージョン>=5.0)


2.次にインストール

PHPの自動パッケージ管理システム composer でインストールします。
composerは便利すぎて一度使うとやめられませんね(笑)
こんなカンジです。
composer require cartalyst/sentinel "2.0.*"

3-1.初期設定(Laravel)

Laravelで利用するには、app.php の中にある providers へ ServiceProviderを追加。
 'providers' => [  
   Cartalyst\Sentinel\Laravel\SentinelServiceProvider::class,  
 ]  
aliases へ以下3つを追加
  'aliases' => [  
     'Activation' => Cartalyst\Sentinel\Laravel\Facades\Activation::class,  
     'Reminder'  => Cartalyst\Sentinel\Laravel\Facades\Reminder::class,  
     'Sentinel'  => Cartalyst\Sentinel\Laravel\Facades\Sentinel::class,  
 ]  
あとは、データベースにテーブルを作成して完了です。
便利なので migration で一気に作成しましょう。

※注意

DBテーブル名の衝突をさけるためにデフォルトで存在する「users」作成マイグレーションは事前に削除するかプログラム部分をコメントアウトしておきましょう。
私の環境では「2014_10_12_000000_create_users_table.php」でした。

(1)Publish でmigrationファイルをパッケージからコピー
php artisan vendor:publish --provider="Cartalyst\Sentinel\Laravel\SentinelServiceProvider"
(2)Migration 実行
php artisan migrate

3-2.初期設定(Laravel以外)

illuminate/database パッケージがあれば通常のPHPからでも利用できるようです。
(ただし、この部分は検証していません。なにぶんLove Laravelなもので、、、^^;)
composer require illuminate/database
でインストールして以下のように設定をします。

(以下本家ページからの引用)
 // 必要なクラスをインポート
 use Cartalyst\Sentinel\Native\Facades\Sentinel;  
 use Illuminate\Database\Capsule\Manager as Capsule;

 // autoloadを読み込む
 require 'vendor/autoload.php';

 // Eloquent Capsule インスタンスを生成
 $capsule = new Capsule;  
 $capsule->addConnection([  
   'driver'  => 'mysql',  
   'host'   => 'localhost',  
   'database' => 'sentinel',  
   'username' => 'user',  
   'password' => 'secret',  
   'charset'  => 'utf8',  
   'collation' => 'utf8_unicode_ci',  
 ]);  
 $capsule->bootEloquent();  
そして、DBの構造はこんな感じです。
 CREATE TABLE IF NOT EXISTS `activations` (  
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,  
  `user_id` int(10) unsigned NOT NULL,  
  `code` varchar(255) COLLATE utf8_unicode_ci NOT NULL,  
  `completed` tinyint(1) NOT NULL DEFAULT '0',  
  `completed_at` timestamp NULL DEFAULT NULL,  
  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',  
  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',  
  PRIMARY KEY (`id`)  
 );  
 CREATE TABLE IF NOT EXISTS `persistences` (  
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,  
  `user_id` int(10) unsigned NOT NULL,  
  `code` varchar(255) COLLATE utf8_unicode_ci NOT NULL,  
  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',  
  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',  
  PRIMARY KEY (`id`),  
  UNIQUE KEY `persistences_code_unique` (`code`)  
 );  
 CREATE TABLE IF NOT EXISTS `reminders` (  
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,  
  `user_id` int(10) unsigned NOT NULL,  
  `code` varchar(255) COLLATE utf8_unicode_ci NOT NULL,  
  `completed` tinyint(1) NOT NULL DEFAULT '0',  
  `completed_at` timestamp NULL DEFAULT NULL,  
  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',  
  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',  
  PRIMARY KEY (`id`)  
 );  
 CREATE TABLE IF NOT EXISTS `roles` (  
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,  
  `slug` varchar(255) COLLATE utf8_unicode_ci NOT NULL,  
  `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,  
  `permissions` text COLLATE utf8_unicode_ci,  
  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',  
  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',  
  PRIMARY KEY (`id`),  
  UNIQUE KEY `roles_slug_unique` (`slug`)  
 );  
 CREATE TABLE IF NOT EXISTS `role_users` (  
  `user_id` int(10) unsigned NOT NULL,  
  `role_id` int(10) unsigned NOT NULL,  
  `created_at` timestamp NULL DEFAULT NULL,  
  `updated_at` timestamp NULL DEFAULT NULL,  
  PRIMARY KEY (`user_id`,`role_id`)  
 );  
 CREATE TABLE IF NOT EXISTS `throttle` (  
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,  
  `user_id` int(10) unsigned DEFAULT NULL,  
  `type` varchar(255) COLLATE utf8_unicode_ci NOT NULL,  
  `ip` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,  
  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',  
  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',  
  PRIMARY KEY (`id`),  
  KEY `throttle_user_id_index` (`user_id`)  
 );  
 CREATE TABLE IF NOT EXISTS `users` (  
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,  
  `email` varchar(255) COLLATE utf8_unicode_ci NOT NULL,  
  `password` varchar(255) COLLATE utf8_unicode_ci NOT NULL,  
  `permissions` text COLLATE utf8_unicode_ci,  
  `last_login` timestamp NULL DEFAULT NULL,  
  `first_name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,  
  `last_name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,  
  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',  
  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',  
  PRIMARY KEY (`id`),  
  UNIQUE KEY `users_email_unique` (`email`)  
 );  


4.基本的な使い方

さあ、ではやっと実際の使い方です。
おそらくSentinelは直感的に使えると思います。

1.新規ユーザーの追加
 $credentials = [  
   'email'  => 'taro.yamada@example.com',  
   'password' => 'password',  
   'first_name' => '太郎',  // 省略可
   'last_name' => '山田'  // 省略可
 ];  
 $user = Sentinel::registerAndActivate($credentials);  
これだけでOK!
パスワードは自動的に暗号化されているのでセキュリティにも強くなっています。

  • 必要がない場合は「first_name」「last_name」は省略できます。
  •  「メール送信→URLをクリックで本登録」という流れにしたい場合は「6.アクティベーション」を参照してください。

2.ログイン
 $credentials = [  
   'email'  => 'taro.yamada@example.com',  
   'password' => 'password',  
 ];  
 $user = Sentinel::authenticate($credentials);  
もし次からのログインを省略する場合は以下のように第二引数に true をセットします。
 Sentinel::authenticate($credentials, true);   

3.ユーザーの取得

(1)IDから取得
 $user = Sentinel::findById(1);  
(2)メールアドレスから取得
 $credentials = [  
   'login' => 'taro.yamada@example.com',  
 ];  
 $user = Sentinel::findByCredentials($credentials);  
あとは、Persistence code  などからでもユーザーを取得できるようです。


4.ユーザー情報の変更/削除

変更は update() を使います。
 $user = Sentinel::findById(1);  
 $credentials = [  
   'email' => 'new.taro.yamada@example.com',  
   'password' => 'new_password',  
   'first_name' => '二郎',  
   'last_name' => '鈴木'  
 ];  
 $user = \Sentinel::update($user, $credentials);  
削除は delete() です。
 $user = Sentinel::findById(1);  
 $user->delete();  


5.役割の設定

Sentinel では、例えば
  • Aさん → 管理者
  •  Bさん → 一般ユーザー
というようにログインする人たちに役割を設定することができます。

(1)新しい役割を追加する
 $role = Sentinel::getRoleRepository()  
   ->createModel()  
   ->create([  
     'name' => '管理者',  
     'slug' => 'admin'  
  ]);  
(2)役割をユーザーに割り当てる/解除する
 $user = Sentinel::findById(1);  
 $role = Sentinel::findRoleByName('管理者');  
 $role->users()->attach($user);  // 割り当てる  
 $role->users()->detach($user);  // 割り当てを解除する  
(3)役割を取得
 $role = Sentinel::findRoleById(1);  // ID
 $role = Sentinel::findRoleBySlug('admin');  // Slug(ユニークIDみたいなもの)  
 $role = Sentinel::findRoleByName('管理者');  // 役割の名前

6.アクティベーション

サイトによっては、ユーザー登録をするときまず「本登録URL」をメール送信し、そのURLがクリックされた時点で本登録するという流れが必要な場合があると思います。
アクティベーションはこの機能を実現するため利用できます。

(1)本登録コードの取得
 $user = \Sentinel::register([  
   'email'  => $email,  
   'password' => 'password'  
 ]);  
 $activation = \Activation::create($user);  
 $activation_code = $activation->code;  
$activation_code に本登録に必要なコードが入っていますので、このコードを使って
http://example.com/activation/****************************************
のような本登録のURLを作成することができます。

(2)本登録を実行
 $user = Sentinel::findById(1);  
 if (Activation::complete($user, '本登録コード'))  
 {  
   // 本登録完了!
 }  
 else  
 {  
   // 失敗,,,
 }  
※ちなみに本登録していない状態でログインを試みると「NotActivatedException」エラーが帰ってきます。


7.パスワード・リマインダー

ユーザーがパスワードを忘れたときに利用する再発行の機能です。

(1)リマインダー・コードを取得する
 $user = \Sentinel::findById(1);  
 $reminder = \Reminder::create($user);  
 $reminder_code = $reminder->code;  
(2)新パスワードの設定
 $user = Sentinel::findById(1);  
 if ($reminder = Reminder::complete($user, 'リマインダー・コード', '新パスワード'))  
 {  
   // 成功!
 }  
 else  
 {  
   // 失敗,,,
 }  

ということで少し長くなってしまいましたが、Sentinelの主な機能は以上です。他にもまだいくつか機能がありますが、それはまたの機会ということで ^-^
ではでは〜。



Thank you, Cartalyst.
Sentinel is a great package!