tag:blogger.com,1999:blog-65454504142590051282024-03-27T22:12:16.480+09:00Sukohi's tech blog!!Anonymoushttp://www.blogger.com/profile/15645657529148406101noreply@blogger.comBlogger81125tag:blogger.com,1999:blog-6545450414259005128.post-34926797527002558082017-05-29T07:20:00.000+09:002017-05-29T07:20:47.719+09:00Laravel と Google カレンダーを自動で同期現在の開発で、とある日付付きのデータが追加/変更/削除されたら Google Calendar へデータを反映させるという機能を追加しました。<br />
正直 Google Calendar API の部分でハマって時間がかかってしまったので、今後のためにもこの記事で Laravel側のプログラムも含めてまとめておこうと思います。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQ9bxmg5ner0X4_ssjs7AZvR8w0T4CTIVO1F6GhCjOCJ_V6c9PcEAXClVN5aPRX1r2mHphHdfTJbFfvtY8Mrzoz_4na2fNNnApGqdddbH6VtOlGJTz-pPOkMu76LlHPiqrVEoCxX8Doyin/s1600/laravel_n_google_calendar.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="265" data-original-width="500" height="211" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQ9bxmg5ner0X4_ssjs7AZvR8w0T4CTIVO1F6GhCjOCJ_V6c9PcEAXClVN5aPRX1r2mHphHdfTJbFfvtY8Mrzoz_4na2fNNnApGqdddbH6VtOlGJTz-pPOkMu76LlHPiqrVEoCxX8Doyin/s400/laravel_n_google_calendar.png" width="400" /></a></div>
<br />
<b>[開発環境]</b><br />
Laravel: 5.4<br />
<br />
<b>[やりたいこと]</b><br />
日付がついたデータがデータベースに{追加/変更/削除}されたら自動で Google Calendar のイベントを同じく{追加/変更/削除}する。<br />
つまり、DB内のデータと Google Calendar のイベントデータの同期がしたいわけです。<br />
そしてカレンダーをウェブページで表示する。<br />
<br />
<br />
<b>[手順]</b><br />
では、大まかな手順です。<br />
<br />
1.Google Calendar API を使って読み込み、書き込み、削除ができるよう設定する<br />
<br />
2.Laravel に自動実行用のイベント を設定。<br />
<br />
3.カレンダーを表示<br />
<br />
<br />
<span style="font-size: large;"><b>1.Google Calendar API を使って読み込み、書き込み、削除ができるよう設定する</b></span><br />
<br />
最初に必要となるのは API と、これから自動的に操作するカレンダーの設定です。<br />
正直、昔のGoogle API それほど複雑ではなく API KEY を取得して URL に含めるだけでOKでしたが、久しぶりに見たらいろんなアプローチの仕方があって困惑してしまいました。<br />
セキュリティ上が大きな原因でしょうから仕方ないといえば仕方ないですね。<br />
<br />
ということで、 手順です。<br />
<br />
(1) 以下のリンクから Google API でプロジェクトを作成し、サービスアカウントを取得します。<br />
<br />
<a href="https://console.developers.google.com/permissions/serviceaccounts" target="_blank">https://console.developers.google.com/permissions/serviceaccounts</a><br />
<br />
やり方は動画を参照してください。<br />
(設定が完了すると json ファイルが自動でダウンロードが開始になるので適当な場所に保存しておいてください。) <br />
↓↓↓ <br />
<br />
<iframe allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/EWDsR2vmYEc" width="560"></iframe>
<br />
<br />
そしてカレンダーAPI を有効に設定しましょう。<br />
↓↓↓<br />
<br />
<iframe allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/5fiiQc0oBbU" width="560"></iframe>
<br />
<br />
最後にカレンダーの方にカレンダーの書き込み権限を付与します。<br />
そのためにはサービスアカウントを取得した際にダウンロードした json の中に書かれているメールアドレスが必要になるのでテキストエディタなどでファイルを開いてコピーしておきましょう。<br />
<br />
"client_email": "********@************************.iam.gserviceaccount.com",<br />
<br />
ではカレンダー内での設定です。<br />
↓↓↓<br />
<br />
<iframe allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/_gcvTWTHlrQ" width="560"></iframe>
<br />
<br />
モザイクをかけているので少しわかりづらいかもしれませんが、先ほどダウンロードした json ファイルの中の "client_email" にかかれているメールアドレスを入力しています。<br />
つまり、カレンダーの権限を API に付与しているわけですね。<br />
<br />
<br />
さて、これで Google API 側の設定は完了です。<br />
次からは Larave 側への設定になります。<br />
<br />
<br />
<span style="font-size: large;"><b>2.Laravel に自動実行用のイベント を設定。</b></span><br />
<br />
<b>準備1</b>: 実行用のイベントを作る前に Google API を操作できるパッケージをインストールしておきましょう。<br />
<br />
<pre><span style="background-color: #cccccc;">composer require google/apiclient:^2.0</span></pre>
<br />
<b>準備2</b>: ダウンロードした json ファイルを <span style="background-color: #cccccc;">/storage/json/google_api_secret_key.json</span> として設置します。<br />
<br />
<b>準備3</b>:カレンダーID を以下のように .env に追加します。<br />
<br />
<pre style="color: black; font-family: "DejaVu Sans Mono"; font-size: 11.3pt;"><span style="background-color: #cccccc;">GOOGLE_CALENDAR_ID=****************@group.calendar.google.com</span></pre>
<br />
※カレンダー ID の取得は以下の動画を参照してください。<br />
<br />
<iframe allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/9zZXDeS4UWs" width="560"></iframe>
<br />
<br />
さぁ、ここからは実際にプログラムコードを書いていく作業になります。<br />
(ここでもう作業の 50% は完了しています。)<br />
<br />
<br />
では、最初に Google API のインスタンスを作成しましょう。<br />
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"><span style="background-color: #f7faff; color: #660000;"><pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> $key_path = storage_path('app/json/google_api_secret_key.json');
putenv('GOOGLE_APPLICATION_CREDENTIALS='. $key_path);
$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
</code></pre>
</span></pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"></pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;">次にカレンダー API へアクセスできるよう以下のように設定をします。 </pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"><span style="background-color: #f7faff; color: #660000;"><pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> $client->addScope(\Google_Service_Calendar::CALENDAR);
$service = new \Google_Service_Calendar($client);
</code></pre>
</span></pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;">はい。これで API へアクセスする準備は整いました。</span></pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;">ここからはカレンダーイベントの追加、編集、削除について説明をしていきます。</span></pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;">※これは実際の実装ではなくイベント操作の基本編です。</span></pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;">実装については「Laravel の Modelイベント」まで読み飛ばしてください。</span></pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;"><b>
</b></span></pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;"><b>1.カレンダーイベントの追加</b></span></pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"><span style="background-color: #f7faff;">
</span></pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"><span style="background-color: #f7faff;"><span style="background-color: white;">イベントの追加は insert() を使います。</span>
</span></pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"><span style="background-color: #f7faff; color: #660000;"><pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> $calendarId = env('GOOGLE_CALENDAR_ID');
$event = new \Google_Service_Calendar_Event([
'summary' => 'テストイベントの投稿',
'location' => '東京都墨田区押上1丁目1−2',
'description' => '東京スカイツリー・バンジージャンプイベント!',
'start' => [
'dateTime' => '2017-05-16T09:00:00-07:00',
'timeZone' => 'Asia/Tokyo',
],
'end' => [
'dateTime' => '2017-05-16T17:00:00-07:00',
'timeZone' => 'Asia/Tokyo',
]
]);
$new_event = $service->events->insert($calendarId, $event);
</code></pre>
</span></pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;">$calendarId は .env に設定したカレンダーIDになります。</span></pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;">上の例では一日だけのイベントですが2日連続、3日連続などの設定も可能です。</span></pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;">その際は<a href="https://developers.google.com/google-apps/calendar/v3/reference/events/insert" target="_blank">本家のリファレンスページ</a>を参照してください。</span></pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;">
</span></pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;">ちなみに $new_event->getId(); </span></pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;">とするとイベントIDが取得できるので、このIDをDBなどに保存しておくことでこのイベントの変更、削除をすることができます。</span></pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;">
</span></pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;">
</span></pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"><span style="background-color: white;"><b>2.カレンダーイベントの変更</b></span>
<span style="background-color: #f7faff;"></span></pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"><span style="background-color: #f7faff;"><pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> $calendarId = env('GOOGLE_CALENDAR_ID');
$event_id = '******************';
$event = $service->events->get($calendarId, $event_id);
$event->setSummary('変更されたイベント');
$service->events->update($calendarId, $event_id, $event);
</code></pre>
</span>さきほどのイベントIDを使って該当するイベントの内容を変更できます。</pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;">summary だけでなくその他の情報も変更できます。<a href="https://developers.google.com/google-apps/calendar/v3/reference/" target="_blank">リファレンス</a>を参照してください。 </span></pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;">
</span></pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;">※ちなみに変更されたイベント名は以下のように取得します。</span></pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"><span style="background-color: #f7faff;"></span></pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"><span style="background-color: #f7faff;"></span></pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"><span style="background-color: #f7faff;"></span></pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"><span style="background-color: #f7faff;"><pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> echo $event->getDescription();
</code></pre>
</span></pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"><span style="background-color: #f7faff;">
</span></pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"><span style="background-color: white;"><b>3.カレンダーイベントの削除</b></span><span style="background-color: #f7faff; color: #660000;">
</span></pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"><span style="background-color: #f7faff;"><pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> $calendarId = env('GOOGLE_CALENDAR_ID');
$event_id = '******************';
$service->events->delete($calendarId, $event_id);
</code></pre>
</span>これもカレンダーID と イベントID を指定することで削除が可能です。</pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;">
</span></pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;">さぁ、ここまでがカレンダーイベントを操作する基本になります。</span></pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;">ここからは Laravel の Modelイベントでの実装(つまり実践編)です。</span></pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;">
</span></pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;"><b><span style="font-size: large;">Laravel の Modelイベント</span></b></span></pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;">
</span></pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;"><b>1.Modelの追加イベント</b></span></pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;">
</span></pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;">コマンドラインから起動するイベントファイルを作成しましょう。</span></pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;">以下のようにします。</span></pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;">
</span></pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;">php artisan make:event ItemCreated</span></pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;">
</span></pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;">これで app/Events フォルダに ItemCreated.php というファイルが作成されているかと思います。</span></pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;">
</span></pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"><span style="background-color: #f7faff;"><span style="background-color: white;">では中身を開いて実際にイベントを追加してみましょう。</span> </span></pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"><pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> public function __construct(Item $item)
{
$calendarId = env('GOOGLE_CALENDAR_ID');
$event = new \Google_Service_Calendar_Event([
'summary' => $item->summary,
'location' => $item->location,
'description' => $item->description,
'start' => [
'dateTime' => $item->date_start,
'timeZone' => 'Asia/Tokyo',
],
'end' => [
'dateTime' => $item->date_end,
'timeZone' => 'Asia/Tokyo',
]
]);
$service->events->insert($calendarId, $event);
}
</code></pre>
これでイベントのプログラム自体は完了ですが、このイベントを起動するプログラムが準備できていません。</pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;">しかし、さすがの Laravel です。起動は Model に trait と変数を指定するだけで完了します。</span></pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"><span style="background-color: #f7faff;"><span style="background-color: white;">以下のように設定しましょう。</span>
</span></pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"><span style="background-color: #f7faff; color: navy; font-weight: bold;"><pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> class Order extends Model
{
use Notifiable;
/**
* The event map for the model.
*
* @var array
*/
protected $events = [
'created' => ItemCreated::class
];
</code></pre>
</span></pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;">これで、Item テーブルにデータが追加されたら自動で ItemCreated が呼ばれ、その中でイベントがカレンダーに追加されることになります。</span></pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;">このようにイベントを設定しておくとどこでデータを操作をしても忘れずにプログラムを実行してくれるのでとても便利ですね。</span></pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"><span style="background-color: #f7faff;"> </span></pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;"><b>2.Modelの変更イベント</b></span></pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;">
</span></pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;">基本的には追加と代わりませんので簡単な説明だけです。</span></pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"><span style="background-color: #f7faff;">
</span></pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"><span style="background-color: #f7faff;"><span style="background-color: #cccccc;">php artisan make:event ItemUpdated</span></span></pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"><span style="background-color: #f7faff;"></span><span style="background-color: #f7faff;"><span style="background-color: #f7faff; color: navy; font-weight: bold;">
</span></span></pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"><span style="background-color: #f7faff;"><pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> public function __construct(Item $item)
{
$calendarId = env('GOOGLE_CALENDAR_ID');
$event = $service->events->get($calendarId, $item->event_id);
$event->setSummary('変更されたイベント');
$service->events->update($calendarId, $item->event_id, $event);
}
/**
* The event map for the model.
*
* @var array
*/
protected $events = [
'updated' => ItemUpdated::class
];
</code></pre>
</span><span style="background-color: #f7faff;"><span style="background-color: #f7faff; color: navy; font-weight: bold;">
</span></span></pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"><span style="background-color: #f7faff;">
</span></pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;"><b>3.Modelの変更イベント</b></span></pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;"> </span></pre>
<pre style="color: black; font-family: "dejavu sans mono"; font-size: 11.3pt;"><span style="background-color: white;">削除も同じです。</span></pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"><span style="background-color: #f7faff;"> </span></pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"><span style="background-color: #f7faff;"><span style="background-color: #cccccc;">php artisan make:event ItemDeleted</span></span></pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"><span style="background-color: #f7faff;"> </span></pre>
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> public function __construct(Item $item)
{
$calendarId = env('GOOGLE_CALENDAR_ID');
$service->events->delete($calendarId, $item->event_id);
}
/**
* The event map for the model.
*
* @var array
*/
protected $events = [
'deleted' => ItemDeleted::class
];
</code></pre>
<br />
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"></pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;">はい。</pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;">これでModelイベントを利用してカレンダー・イベントを操作してみました。</pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"> </pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;">ちなみにもしイベントを好きなタイミングで起動したい場合は以下のようにします。</pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"></pre>
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> event(new ItemCreated($item));
event(new ItemUpdated($item));
event(new ItemDeleted($item));
</code></pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"></pre>
<br />
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"></pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;">この辺も Lravel のいたれりつくせり感があふれています。</pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"> </pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"></pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"></pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"><span style="font-size: large;"><b>3.カレンダーを表示</b></span></pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"></pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"> </pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;">さぁ、せっかくここまでイベントを設定してきたので、自動操作されるカレンダーを実際にウェブページに表示してみましょう。</pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;">とはいっても、Google カレンダーでは HTMLタグを提供してくれているのでとても簡単に実装することができます。</pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"> </pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;">やりかたは、カレンダーIDを取得したページの「<span class="al-ctx-lbl" id="goog_661786249">このカレンダーを埋め込む</span>」の項目にある HTMLタグをコピー&ペーストするだけです。</pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"></pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;">DBにデータを追加/編集/削除するとリアルタイムで(少し時間がかかる場合もあります)変更されると思います。</pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"> </pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"> </pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;">以上、今回は Google API を使ってデータを同期する方法でした。</pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;">実現するには少し時間がかかるかもしれませんがとても便利な機能なのでぜひチャレンジしてみてください。</pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;"> </pre>
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 11.3pt;">ではでは! </pre>
Anonymoushttp://www.blogger.com/profile/15645657529148406101noreply@blogger.com2tag:blogger.com,1999:blog-6545450414259005128.post-11739659505094089132017-05-22T16:18:00.001+09:002017-05-22T16:18:05.062+09:00Vue + jQuery の弱点に初めて遭遇!このところ Vue.js を使って開発効率が格段に上がってきているのを感じています。しかも以前の <a href="https://sukohi.blogspot.jp/2017/02/vuejs-20-review.html" target="_blank">Vue.js 2.0 を使ってみた9つの感想 </a> でも取り上げましたが、jQuery との衝突が全く無かったので機嫌よく Vue での開発を進めていたのですが、今回初めて衝突というか弱点に遭遇したのでまとめと対処法をお届けしたいと思います。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiS21p82-KCox5xQzFmo7G5Ik7UsXbRjaP_i_GWLy0S0nqTilz4kwdf2a8fj5DMQLaWxFUQoVREk1aa5dscdCG6lTfhvKKRkL7ksKKj9Z1s-QnJODiRKlaJEkm-H1V7gQCfpc_4AgAnpdKX/s1600/vue_n_jquery.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="175" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiS21p82-KCox5xQzFmo7G5Ik7UsXbRjaP_i_GWLy0S0nqTilz4kwdf2a8fj5DMQLaWxFUQoVREk1aa5dscdCG6lTfhvKKRkL7ksKKj9Z1s-QnJODiRKlaJEkm-H1V7gQCfpc_4AgAnpdKX/s400/vue_n_jquery.png" width="400" /></a></div>
<br />
<br />
まずは遭遇した状況から。<br />
jQuery(Bootstrap) を使ったページ内で JavaScript を使って input 内の値を変更しようとしました。(※詳しく言うと、後でも言及する datepicker を使ってテキスト内に日付を入力しようとしてました。また、冗長になるので、<span style="background-color: #cccccc;"> this.input = 'xxxxxx'; </span>を使うのは無しの方向です。)<br />
<br />
私の頭の中では以下のように通常通り<span style="background-color: #cccccc;"> $('#id').val('xxxxx'); </span>を使ってテキストの中身を変更すれば Vue の方でもデータが更新されるものだと思っていました。<br />
しかし、以下のデモのようにテキスト内は変更できるものの、Vue の方では変更は全くないという状況でした。<br />
<br />
<a href="http://demo-laravel52.capilano-fw.com/vue_with_jquery/1" target="_blank">Vue + jQuery の change イベント実験 - 1</a><br />
<br />
<br />
<br />
、、、なぜだろう。<br />
jQuery の val() でデータを変更しても change イベントは呼ばれないというのは知っていました(<a href="http://qiita.com/foo9/items/51ffdaa5305fbc4efa58" target="_blank">参考ページ</a>)が、今回使っているのは vue の v-model なので問題はないはずなのに・・・?<br />
<br />
<br />
そこで少し stackoverflow を探ってみると、vue には $forceUpdate() という強制的にデータを更新する方法があるよ、ということなので以下のページのように実際に試してみました。<br />
<br />
<a href="http://demo-laravel52.capilano-fw.com/vue_with_jquery/2" target="_blank">Vue + jQuery の change イベント実験 - 2</a><br />
<br />
<br />
でも、これもうまくいかない、、、、<br />
クリックを続けているとたまに自動入力されるテキストがちらつくことがあるので、おそらく変更はされたが、$forceUpdate() によって瞬間的に元にもどされてしまっているという状況なのだろう(つまり Vue には伝わっていない)と思いました。<br />
<br />
<br />
またしてもスタート地点に戻ってしまったので、もう一度いろいろとネット上の情報を探ってみると本家 GitHub の Issue で手がかり見つけました。<br />
<br />
<a href="https://github.com/vuejs/Discussion/issues/157" target="_blank">Triggering vuejs on programatical change of element.</a><br />
<br />
<br />
どうやら、jQuery の changeイベントはネイティブの JavaScript のイベントとは別のものなので、もし Vue の変更をやりたいならネイティブイベントを作って dispatch しないといけないということでした。<br />
<br />
そこで、早速以下のようにイベント送出をしてみました。<br />
<br />
<a href="http://demo-laravel52.capilano-fw.com/vue_with_jquery/3" target="_blank">Vue + jQuery の change イベント実験 - 3</a><br />
<br />
<br />
おっ、いけました!<br />
この状態だと直接テキスト入力してもボタンをクリックしても Vue のデータが書き換わるのでリアルタイムに上のテキストも変更されるようになっています。<br />
<br />
へぇ、Vue にはネイティブ JS のイベントが必要だったんですね。<br />
<br />
<br />
では、本題の datepicker を使うにはどうすればいいのでしょうか。<br />
今回は jQuery の changeイベントとのコラボでやってみました。<br />
<br />
<pre style="background-color: white; color: black; font-family: 'DejaVu Sans Mono'; font-size: 9.8pt;"><span style="font-style: italic;">$</span>(<span style="color: green; font-weight: bold;">'.datepicker'</span>).<span style="color: #7a7a43;">datepicker</span>().on(<span style="color: green; font-weight: bold;">'change'</span>, <span style="color: navy; font-weight: bold;">function</span>() {
<span style="color: navy; font-weight: bold;">var </span><span style="color: #458383;">event </span>= <span style="color: #660e7a; font-weight: bold;">document</span>.<span style="color: #7a7a43;">createEvent</span>(<span style="color: green; font-weight: bold;">'HTMLEvents'</span>);
<span style="color: #458383;">event</span>.<span style="color: #7a7a43;">initEvent</span>(<span style="color: green; font-weight: bold;">'input'</span>, <span style="color: navy; font-weight: bold;">true</span>, <span style="color: navy; font-weight: bold;">true</span>);
<span style="font-style: italic;">$</span>(this).get(<span style="color: blue;">0</span>).<span style="color: #7a7a43;">dispatchEvent</span>(<span style="color: #458383;">event</span>);
});</pre>
<br />
実際のテストは以下です。<br />
<br />
<a href="http://demo-laravel52.capilano-fw.com/vue_with_jquery/4" target="_blank">Vue + jQuery の change イベント実験 - 4</a><br />
<br />
<br />
やってみたら分かっていただけると思いますが、テキスト入力(数字しか入力できません)でもカレンダー選択のどちらでも Vue へデータが伝わっていると思います。<br />
<br />
※ちなみに送出するイベントが「input」ではなく「change」の場合だと、これもうまくいきませんでした。<br />
<br />
ということは、この方法を使えば「dispach-native-event」などのクラス名に changeイベントを作っておき、その中でネイティブ・イベントを送出することができるので、サイト全体での対処も比較的楽にできるかと思います。<br />
<br />
<br />
んー、それにしてもこんな形で Vue + jQuery の問題点に遭遇するとは思いませんでした。<br />
でもその他の部分では問題もなく、開発速度も上がり、保守もしやすいと思うので Vue の利用は続けていこうと思います。<br />
<br />
<br />
【あとがき】<br />
<br />
フロントエンド界の活動は近年ホントに活発でそれ自体はとてもいいことなのですが、正直なところをいうとたくさんありすぎてもう少し集約してほしい気はしています。<br />
また、複雑さが年を追うごとにひどくなってきていて、「あれ、なんのためのフレームワークだったけ?開発効率、ほんとにこれで上がってる??」なんてことになってきているなぁ、と pythonプログラミングをしているとよく感じます。<br />
<br />
この間どこかのブログで「3年後も react 使ってると思う? vue 使ってると思う? でも確実に jQuery は使ってるよね?」という趣旨の記事を読みました。<br />
<br />
これには Vue が大好きな僕でも「確かにそれはあるかもー」と思いました。<br />
そんなこんなもあるので、変化の速い(早すぎる)これからのプログラミングは学習コストの低さも重要なファクターの一つになってくるんじゃないかな、と今日出してきた扇風機にあたりながら考えてました。<br />
(もちろん何を専門にするかで変わってくるでしょうけどね。)<br />
<br />
<br />
それはともかく、今年の夏は涼しかったらいいなー(笑)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjeiIhkK22V_5HpI-p749M0I1d2BxcGF0TK7yBGOlQCaKZrtCPH6YmCucrnWrltmPT-Vokcdb1c9IW4WSmhnUOBBVhJK-yHJbyn0esuj9TPnQnfe3ifcIqPMz9OAubTjXBm0TkUNCztIWXy/s1600/39.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="314" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjeiIhkK22V_5HpI-p749M0I1d2BxcGF0TK7yBGOlQCaKZrtCPH6YmCucrnWrltmPT-Vokcdb1c9IW4WSmhnUOBBVhJK-yHJbyn0esuj9TPnQnfe3ifcIqPMz9OAubTjXBm0TkUNCztIWXy/s320/39.png" width="320" /></a></div>
<br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/15645657529148406101noreply@blogger.com0tag:blogger.com,1999:blog-6545450414259005128.post-22842256355440183272017-05-09T12:00:00.000+09:002017-05-09T12:00:12.053+09:00Python でバーコードをスキャン(ソースコード・ダウンロード可)今回は、たくさんの商品画像の中にあるバーコードの内容をプログラムでスキャンして取得&その写真の分類ができるようにしてみたいと思います。<br />
利用するのは次の3つです。<br />
<br />
1.Python(2.7.12)<br />
2.OpenCV2 <br />
3.Zbar<br />
<br />
※実際のコードは <a href="https://github.com/SUKOHI/python-scanning-barcode-image" target="_blank">GitHub</a> からダウンロードできます。 <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQjKQ5XqkDW3yiFKslKW1vdUasjPmJ9zccc9F-35doS4w2p_jSh-LIWpavM-MlSRjm1Z_ydFODy2-hHMG4FgCuUXNnxCJiIzCurnWev10svkEP2A2wHwJAxhytabxc_82xoFkYWkR-zeJK/s1600/barcode1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQjKQ5XqkDW3yiFKslKW1vdUasjPmJ9zccc9F-35doS4w2p_jSh-LIWpavM-MlSRjm1Z_ydFODy2-hHMG4FgCuUXNnxCJiIzCurnWev10svkEP2A2wHwJAxhytabxc_82xoFkYWkR-zeJK/s400/barcode1.jpg" width="300" /></a></div>
<br />
<b><span style="font-size: large;">【準備】</span></b><br />
<br />
まずバーコードをスキャンするには zbar というパッケージが必要になりますのでインストールをしましょう。Ubuntu だと以下のコマンドで zbar をインストールできます。<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> sudo apt-get install libzbar-dev
</code></pre>
そして、python から zbar が使えるようにするため pip でインストールです。<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> pip install zbar
</code></pre>
はい。<br />
これでインストールは完了です。(OpenCVはメジャーなのでインストールは省きます。)<br />
<br />
<span style="font-size: large;"><b>【基本編】</b></span><br />
<br />
では、zbar を使って画像の中にあるバーコードをスキャンする簡単なコードを作っていきましょう。<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> import cv2
import zbar
scanner = zbar.ImageScanner()
scanner.parse_config('enable')
</code></pre>
必要なパッケージをインポートして、zbar のスキャナーを作成します。<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> im = cv2.imread('images/barcode1.jpg')
gray_im = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
</code></pre>
OpenCV でスキャンしたい画像を読み込んでグレースケールに変換します。<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> rows,cols = im.shape[:2]
image = zbar.Image(cols, rows, 'Y800', gray_im.tostring())
scanner.scan(image)
</code></pre>
ここで zbar の image を作成します。<br />
1行目で画像のサイズとさっき作った gray_im をセットして実際にスキャンを開始します。<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> for symbol in image:
print 'Type: %s, Data: %s' % (symbol.type, symbol.data)
</code></pre>
スキャンした結果を表示します。<br />
type には 「qrcode」や「isbn10」などのデータタイプ、そして data には読み取ることができた値が入っています。<br />
<br />
以上が簡単な例でした。<br />
ただ、この例ではバーコードが斜めになっている場合は、検出できないことがあります。<br />
そこで、次の応用編では斜めになったバーコードにも対応できるようにしてみましょう。 <br />
<b><span style="font-size: large;"><br /></span></b>
<b><span style="font-size: large;">【応用編】</span></b><br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> import cv2
import zbar
scanner = zbar.ImageScanner()
scanner.parse_config('enable')
im = cv2.imread('images/barcode2.jpg')
gray_im = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
rows,cols = im.shape[:2]
</code></pre>
ここまでは基本編のおさらいです。<br />
(ちなみに barcode2.jpg ではわざとバーコードがななめになっています。)<br />
<br />
では、ここから斜めになったバーコードに対応するため輪郭を取得していきましょう。<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> ret,threshold_im = cv2.threshold(gray_im, 150, 255, cv2.THRESH_BINARY)
im,contours,hierarchy = cv2.findContours(threshold_im, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
</code></pre>
まず、しきい値を使って画像を白と黒だけに変換します。<br />
そして、findContours() で輪郭を取得します。<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> for contour in </code><code style="color: black; word-wrap: normal;"><code style="color: black; word-wrap: normal;">contours</code>:
rect = cv2.minAreaRect(contour)
center_pt = (int(rect[0][0]), int(rect[0][1]))
w = int(rect[1][0])
h = int(rect[1][1])
angle = int(rect[2])
</code></pre>
次に、取得した contours を for ループで回して一つ一つの長方形を取得しましょう。<br />
minAreaRect がその部分になります。<br />
<br />
rect は 中心座標、横幅、高さ、傾きのデータを持っているのでこれらをわかりやすいようにひとつひとつ変数(center_pt, w, h, angle)に格納していきます。<br />
<br /><pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> M = cv2.getRotationMatrix2D(center_pt, angle, 1)
rotated_im = cv2.warpAffine(im.copy(), M, (cols,rows))
</code></pre>
長方形の傾き(角度)が分かったのでこれを使って画像を回転させましょう。<br />
一行目は行列を作って2行目で回転させた画像を取得しています。<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> zbar_image = zbar.Image(cols, rows, 'Y800', rotated_im.tostring())
scanner.scan(zbar_image)
</code></pre>
そして、さっきと同じく zbar の image をつくります。<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> for symbol in zbar_image:
symbol_type = symbol.type
symbol_data = symbol.data
if(symbol_type not in scanned_data.keys()):
scanned_data[symbol_type] = []
if symbol_data not in scanned_data[symbol_type]:
scanned_data[symbol_type].append(symbol_data)
</code></pre>
for ループで回して、もし scanned_data に type 別の値が入っていなければデータを格納。(←つまり、重複防止ですね)<br />
<br />
これで、 scanned_data の中にスキャンされたバーコードの情報が入っていることになります。<br />
あとは MySQL や JSON にデータを格納するなどして分類結果を保存するなどすればいいでしょう。<br />
<br />
今回は以上です。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyupc4S66VSBoS5HqsrAEZkZiNF4hCvk-nuZFgea4EpfZ5ULDeMSqX9ipuQzFkVCKN6tPb1zpHBMamwX5qFv_LQubkdru32mL1dX-UkOvgYBqhRr2D7PP7MOpySXV84maaTmnzuQPRcQMq/s1600/23.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyupc4S66VSBoS5HqsrAEZkZiNF4hCvk-nuZFgea4EpfZ5ULDeMSqX9ipuQzFkVCKN6tPb1zpHBMamwX5qFv_LQubkdru32mL1dX-UkOvgYBqhRr2D7PP7MOpySXV84maaTmnzuQPRcQMq/s1600/23.png" /></a></div>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/15645657529148406101noreply@blogger.com1tag:blogger.com,1999:blog-6545450414259005128.post-59599672232722624712017-04-28T19:55:00.000+09:002017-04-28T19:55:22.921+09:00Vue.js で年齢をリアルタイム計算(lodashで遅延処理も)久しぶりの更新です。<br />
今人気が上がってきている Vue.js のウォッチャの勉強したので、まとめておこうと思います。<br />
<br />
<a href="http://demo-laravel52.capilano-fw.com/vue_watch" target="_blank">デモページ</a><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3EODWV_RqR3txcl7eiFtuZzTRqK9UaTAiXdXRV830iCC9-vqsi3E8XDkPHwY4zD10EFsEac-XF9UDMHJqe3lUQOQk24LxhtJls8jjZxYvSE9czqsG4fIaf5ob29MTM_v3naG3Mi1zOOR-/s1600/calculator-428294_640.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="263" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3EODWV_RqR3txcl7eiFtuZzTRqK9UaTAiXdXRV830iCC9-vqsi3E8XDkPHwY4zD10EFsEac-XF9UDMHJqe3lUQOQk24LxhtJls8jjZxYvSE9czqsG4fIaf5ob29MTM_v3naG3Mi1zOOR-/s400/calculator-428294_640.jpg" width="400" /></a></div>
<br />
では、まずやり方を以下の2点で説明します。<br />
<br />
1.HTML 部分<br />
2.JavsScript 部分<br />
<br />
<br />
<span style="font-size: large;"><b>1.HTML 部分</b></span><br />
<br />
基本的には <input>タグが2つあるだけです。<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> <input v-model="birthdate">
<input v-model="age">
</code></pre>
<br />
特徴は v-model という Vue の命令が入っているだけです。<br />
そして、この中で指定されている「birthdate」「age」という名前が JavaScript 部分で使う変数名になり、birthdate がウォッチャで監視されることになります。<br />
<br />
<span style="font-size: large;"><b>2.JavaScript 部分</b></span><br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> var vm = new Vue({
el: '#demo',
data: {
birthdate: '',
age: 0
},
watch: {
birthdate: function(val) {
this.age = this.</code><code style="color: black; word-wrap: normal;"><code style="color: black; word-wrap: normal;">calcAge(val);</code>
}
},
methods: {
calcAge: function(birthdate) {
var ageDifMs = Date.now() - birthdate.getTime();
var ageDate = new Date(ageDifMs);
return ageDate.getUTCFullYear() - 1970;
}
}
})
</code></pre>
<br />
<br />
とてもとてもシンプルにしたのでデモページのコードとは違っていますが、内容としては次のようになります。<br />
<br />
1.data 内は、これから必要になる変数。ということで、さきほど HTML 部分で指定した「birthdate」「age」の2つを設置しましょう。v-model を使用しているので変更があったらリアルタイムでこの中身が更新されます。<br />
<br />
2.そして、watch で変数に変化が起こっていないかを監視します。今回は誕生日が変更になったことを知りたいので「birthdate」の中で年齢を計算&変更します。<br />
<br />
<span style="font-size: large;"><b>ちなみに</b></span><br />
<br />
デモページでは <a href="https://lodash.com/" target="_blank">lodash </a>と呼ばれる便利機能をたくさん提供してくれる JavaScript パッケージを使って遅延処理を行っています。(この方が計算してるぞ!感がでるので(笑))<br />
<br />
実際には以下のようにします。<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> _.delay(function(birthdate) {
// ここが0.35秒後に呼ばれる
}, 350, val);
</code></pre>
<br />
そして、指定時間を待っている間は「enteringFlag」を切り替えることで、「計算中...」というテキストを(表示/非表示)しています。<br />
<br />
<br />
<span style="font-size: large;"><b>終わりに</b></span><br />
<br />
状況によって jQuery を使うほうがスマートな場合もありますが、やはり Vue はなにかと便利です。(^^)<br />
ではでは。<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzpp-VsPGUy2ayi1GmCWVV-eBLUZAMhU39uaVsHw6IFE-Jsz3ZUsdUnWV0d3xa-ubuDoTWuZRQiJA1aLLOPk1d_6GSW3Ioge9kcMuy1n0dpNi_-Ddq4s3F5jpec_dLLL5tH08Xb8UEUE9G/s1600/bye.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzpp-VsPGUy2ayi1GmCWVV-eBLUZAMhU39uaVsHw6IFE-Jsz3ZUsdUnWV0d3xa-ubuDoTWuZRQiJA1aLLOPk1d_6GSW3Ioge9kcMuy1n0dpNi_-Ddq4s3F5jpec_dLLL5tH08Xb8UEUE9G/s1600/bye.png" /></a></div>
Anonymoushttp://www.blogger.com/profile/15645657529148406101noreply@blogger.com0tag:blogger.com,1999:blog-6545450414259005128.post-25630115717512861322017-03-23T18:21:00.001+09:002017-03-24T18:39:02.811+09:00機械学習で顔の向きを取得する【scikit-learn】今回、以前投稿した「<a href="http://sukohi.blogspot.jp/2017/01/swap-faces.html" target="_blank">顔の入れ替えを試してみた</a>」で取得した顔データからその顔がどっちを向いているのか(角度)?を取得する必要がでてきたので機械学習の <a href="http://scikit-learn.org/stable/" target="_blank">scikit-learn</a> を使って実現してみました。<br />
元々は人力で公式を作ろうとしてみましたが、数学の基礎知識が乏しい私には難かったため、これを機に以前からずっと気になっていた機械学習を導入することにしました。<br />
<br />
そして、結果としては満足できる精度になりそうになったのでここにその作業の手順を残しておこうと思います。<br />
<br />
追記: joblib は使わず pickle を使うようコードを変更しました。 (2017.03.24)<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaolaIMeSp9bKfkVrffhNVSOZhDYH7ZvKpioDulPBBk89iv4iHB3Oxg7sjKqK9blbcQO1JWFWj1vkcZF8rgH6ikLOgz90HqQ72idQIA6z_Jz-YItE3MjbFldLTL80VdevJiGtR2gUtx8Am/s1600/person-1041904_640.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaolaIMeSp9bKfkVrffhNVSOZhDYH7ZvKpioDulPBBk89iv4iHB3Oxg7sjKqK9blbcQO1JWFWj1vkcZF8rgH6ikLOgz90HqQ72idQIA6z_Jz-YItE3MjbFldLTL80VdevJiGtR2gUtx8Am/s400/person-1041904_640.jpg" width="400" /></a></div>
<br />
<br />
<span style="font-size: large;">【おおまかな手順】</span><br />
<ul>
<li>角度データのある顔画像を用意</li>
<li>顔データを加工して機械学習&結果を保存</li>
<li>学習結果を使って未知の画像から顔の角度を取得</li>
</ul>
<br />
<span style="font-size: large;">【実際の手順】 </span><br />
<br />
まず角度データつきの顔画像を探しました。<br />
機械学習で一番骨が折れるのはデータ収集です。<br />
ある程度の数がないと精度を高めることができないためです。<br />
<br />
ただ、今回はテストということで数は少ないですが以下のページからダウンロードして試してみました。<br />
<br />
<a href="http://www-prima.inrialpes.fr/perso/Gourier/Faces/HPDatabase.html">http://www-prima.inrialpes.fr/perso/Gourier/Faces/HPDatabase.html</a> <br />
<br />
<br />
次にこの画像から学習データとラベルを取得して学習させます。<br />
(今回は顔が左右どちらにどのくらいの角度向いているかを学習させます。)<br />
<br />
<br />
<u>学習データ</u><br />
<br />
データは、以下のような顔の右側と左側の比率を使うことにしました。<br />
<br />
(左のこめかみから鼻までの距離 + 左のほほから鼻までの距離) / (右のこめかみから鼻までの距離 + 右のほほから鼻までの距離)<br />
<br />
※2本ずつの距離を使ったのは縦方向の回転(pitch)の影響が少なくなるのではないかと思ったからです。<br />
<br />
<br />
<u>ラベル</u><br />
<br />
ラベル(学習後、テストデータを入れると取得できる答え)はダウンロードしたファイル名に顔の角度が「+30」や「-45」などの形で含まれているのでこれを正規表現で切り出してそのまま利用します。<br />
<br />
※つまり、ある顔データを入力すると「この顔の角度は+15(左に15度)です」などという形で答えを教えてくれるという形になります。<br />
<br />
<br />
<span style="font-size: large;">【実際のコード】</span><br />
<br />
実際の機械学習コードは以下になります。<br />
<br />
※このコードを使うには 「<a href="http://sukohi.blogspot.jp/2017/01/swap-faces.html" target="_blank">顔の入れ替えを試してみた</a>」 で紹介した dlib の顔検出環境が必要になりますので事前に準備しておく必要があります。<br />
(後で知りましたが、dlib は python のパッケージマネージャーの pip や anaconda で楽に準備できるようですね^^;)<br />
<br />
※ path/to/***** となっている部分は自分の環境に合わせてください。テストした環境は python 2.7.12 です。<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> # -*- coding: utf-8 -*-
import sys
import cv2
import dlib
import glob
import re
import pickle
import numpy as np
from sklearn import svm
def get_distance(landmarks, ids):
id1 = ids[0]
id2 = ids[1]
point1 = landmarks[id1]
point2 = landmarks[id2]
return np.linalg.norm(np.array(point2)-np.array(point1))
def get_face_h_ratio(landmarks):
length1 = get_distance(landmarks, [0,30])
length2 = get_distance(landmarks, [16,30])
length3 = get_distance(landmarks, [4,30])
length4 = get_distance(landmarks, [12,30])
return (length1+length3)/(length2+length4)
predictor = dlib.shape_predictor('/path/to/shape_predictor_68_face_landmarks.dat') # Predictorファイル
detector = dlib.get_frontal_face_detector()
train_angles = []
train_labels = []
for i in range(1,16):
dir_path = '/path/to/head_pose_images/Person%02d/*' % i # ダウンロードした顔画像フォルダ
print dir_path
paths = glob.glob(dir_path)
for path in paths:
m = re.search(r'([\+\-]+([0-9]{1,2}))([\+\-]+([0-9]{1,2}))\.jpg$', path)
if m:
im = cv2.imread(path, cv2.IMREAD_COLOR)
rects = detector(im, 1)
if len(rects) == 0:
continue
landmarks = np.matrix([[p.x, p.y] for p in predictor(im, rects[0]).parts()]) # 顔ポイントを取得
if landmarks is not None:
label = m.group(1) # ファイル名から顔の左右角度を切り出す(yaw)
ratio = get_face_h_ratio(landmarks) # 顔の左右距離から比率を取得
train_angles.append([ratio])
train_labels.append(label)
clf = svm.SVC()
clf.fit(train_angles, train_labels) # 取得したデータで機械学習する
pickle.dump(clf, open('yaw_angles.pkl', 'wb')) # 学習した結果を後でも使えるようにファイル保存
</code></pre>
<br />
このコードを実行すると「yaw_angle.pkl」というファイルが作成されます。<br />
これが学習結果になりますので後で顔角度を取得したい場合は、以下のようにこのファイルをロードして使うことになります。<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> path = 'checking_image.jpg'
im = cv2.imread(path, cv2.IMREAD_COLOR)
rects = detector(im, 1)
if len(rects) == 0:
sys.exit()
landmarks = np.matrix([[p.x, p.y] for p in predictor(im, rects[0]).parts()]) # 顔ポイントを取得
if landmarks is not None:
with open('yaw_angles.pkl', 'rb') as f:
clf = pickle.load(f)
ratio = get_face_h_ratio(landmarks) # 顔の左右距離から比率を取得
pre = clf.predict([ratio])
print pre # 配列で答え(ここでは角度)が返ってきます。
</code></pre>
<br />
※ 注: ここでは import は省略しています。<br />
<br />
以上が今回の機械学習の手順になります。<br />
ただし、途中でも書きましたがこれだけでは学習データが少ないと思いますので他のデータも必要になってくるかと思います。<br />
<br />
それにしても機械学習はすごいですね。<br />
今回は左右の顔の向き(yaw)でしたが、同じようにすることで上下(pitch)も学習できるでしょうし、顔だけでなくインターネット上に無限にあるデータをうまく学習させればいろいろと面白いことができるのではないでしょうか。<br />
<br />
今後は tensorflow の方にもチャレンジしてみたいと思います。<br />
ではまた(^^)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCIGph_K9gULbIZRPyFPKI5rU-tIwwmggKRtCNittVnTyPoKA6Kq9XDP9B2-joOBaMVYishSfi-dNBrGWqH0a1YNvsNzTQBfr7hTsU6WjgRlxAb93sHw4j8E-vtLbxY3kYZDzPYqSqZkym/s1600/9.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="190" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCIGph_K9gULbIZRPyFPKI5rU-tIwwmggKRtCNittVnTyPoKA6Kq9XDP9B2-joOBaMVYishSfi-dNBrGWqH0a1YNvsNzTQBfr7hTsU6WjgRlxAb93sHw4j8E-vtLbxY3kYZDzPYqSqZkym/s320/9.png" width="320" /></a></div>
Anonymoushttp://www.blogger.com/profile/15645657529148406101noreply@blogger.com3tag:blogger.com,1999:blog-6545450414259005128.post-1009692290210282552017-03-13T19:09:00.000+09:002017-03-13T19:09:28.709+09:00テキストだけHTMLから抽出する方法を考えてみた【ソースコード・ダウンロード可】現在の開発でウェブ上のHTMLページから重要なテキストだけを取得する必要がでてきたのでどのようなアプローチがいいのかを考えてみました。<br />
<br />
いろいろなアプローチを試しては失敗をしたのですが、最終的にある程度の精度を出せる方法に行きついたのでここで紹介したいと思います。<br />
<br />
<b><span style="font-size: large;"><br /></span></b>
<b><span style="font-size: large;">【抽出アルゴリズム】</span></b><br />
<br />
実際にはアルゴリズムというほど複雑な方法ではありませんが、結局は「人間の目で見てテキストが密集している部分をグループ化する」というアプローチが功を奏しました。<br />
<br />
流れとしては以下になります。<br />
<ol>
<li>もしテキスト間のHTMLタグが5つ以下なら(つまり近くにあるなら)そのテキストは全てひとつのテキストとして結合させる。</li>
<li>結合したテキストをひとつひとつチェックし、テキストの長さが100以上あれば、それはコンテンツとして残す。</li>
</ol>
文章ではわかりにくいと思いますので、HTML タグの例を見てみましょう。<br />
<br />
(HTML例)<br />
<br />
<div><br />
<div>テキスト1</div><br />
<div>テキスト2</div><br />
<div>テキスト3</div><br />
</div><br />
<br />
<img src="***"><br />
<img src="***"><br />
<img src="***"><br />
<br />
<div><br />
<div>テキスト4</div><br />
</div> <br />
<br />
<br />
<b><span style="font-size: large;">テキストが近いければ結合する</span></b><br />
<br />
まず、「テキスト1」と「テキスト2」 の間には HTML が2つ(</div>と<div>)だけです。<br />
つまり HTML 構造的にいうと距離は「2ステップ」の位置にあるため近いテキストということになります。<br />
なので、この2つのテキストは結合します。<br />
<br />
では、「テキスト3」と「テキスト4」はどうでしょう?<br />
間にあるのは、 <br />
</div></div><img><img><img><div><div><br />
なので7ステップです。<br />
<br />
デフォルトの基準は5ステップ以下なら結合することになっているのでこれは「遠いテキスト」ということで結合はしません。<br />
<br />
これを全てのテキストで実行すると、ほぼ「見た目で近いテキストが集まったグループ」が作成できることになります。<br />
<br />
<br />
<b><span style="font-size: large;">テキストが長ければコンテンツとして抽出する</span></b><br />
<br />
グループ別のテキストが作成できたので次にこのテキストがある程度以上長ければ残し、短ければ重要度が低いと判断し削除します。<br />
<br />
このフィルターを通過したテキストがコンテンツ・テキストということになります。<br />
<br />
<br />
<b><span style="font-size: large;">ただし </span></b><br />
<br />
この方法でもパーフェクトではありません。<br />
また、紹介した方法をする前に <br> タグなどを一時的に退避させるなど HTML の加工が必要になりますのでご注意ください。<br />
<br />
<br />
<b><span style="font-size: large;">ソースコードのダウンロード</span></b><br />
<br />
ということで、このコンテンツ抽出アルゴリズム(細々とした HTML の加工を含んでいます)を PHP クラス「<a href="https://github.com/SUKOHI/Shellless" target="_blank">Shellless</a>」として公開しました。<br />
Github でダウンロードか composer でインストールできるかと思いますのでもし興味がありましたらぜひアクセスしてみてください。<br />
<br />
<a href="https://github.com/SUKOHI/Shellless" target="_blank">https://github.com/SUKOHI/Shellless</a><br />
<br />
<br />
今回は以上です。(^o^)<br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjeiIhkK22V_5HpI-p749M0I1d2BxcGF0TK7yBGOlQCaKZrtCPH6YmCucrnWrltmPT-Vokcdb1c9IW4WSmhnUOBBVhJK-yHJbyn0esuj9TPnQnfe3ifcIqPMz9OAubTjXBm0TkUNCztIWXy/s1600/39.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="314" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjeiIhkK22V_5HpI-p749M0I1d2BxcGF0TK7yBGOlQCaKZrtCPH6YmCucrnWrltmPT-Vokcdb1c9IW4WSmhnUOBBVhJK-yHJbyn0esuj9TPnQnfe3ifcIqPMz9OAubTjXBm0TkUNCztIWXy/s320/39.png" width="320" /></a></div>
<br />
Anonymoushttp://www.blogger.com/profile/15645657529148406101noreply@blogger.com0tag:blogger.com,1999:blog-6545450414259005128.post-24544836460836163022017-02-28T19:10:00.000+09:002017-02-28T19:10:22.728+09:00アフィン変形の他の座標を取得する【Python】前回の「<a href="http://sukohi.blogspot.com/2017/02/python.html" target="_blank"> Python で画像を引っぱるように歪める</a>」に引き続き python を使ったアフィン変形(回転、縮小/拡大、並行移動を一括で行う変形)のお話です。<br />
<br />
アフィン変形は3点を使って回転などをするのですが、数学が苦手な私には「じゃあ、その他の座標はどうやって計算するの?」ということがわかりませんでした。<br />
そこで、今回も備忘録的にこの記事を書きたいと思います。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgypU5VvYG5oXeu9Unyvpw1DfHF1kllMKwiJS9VTug9SA4LvA0aOUMDJgB6du_g5uk3uNSceuatn61tvdNZQStt2vKvK4cQOC5LW1CBZ_soqBdf83oiuamgj9ws6Mihd2J_NG7iYxv-2GZh/s1600/pizza-1081534_640.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="263" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgypU5VvYG5oXeu9Unyvpw1DfHF1kllMKwiJS9VTug9SA4LvA0aOUMDJgB6du_g5uk3uNSceuatn61tvdNZQStt2vKvK4cQOC5LW1CBZ_soqBdf83oiuamgj9ws6Mihd2J_NG7iYxv-2GZh/s400/pizza-1081534_640.jpg" width="400" /></a></div>
<br />
<br />
<b><span style="font-size: large;">まずは</span></b><b><span style="font-size: large;">アフィン変形の使い方(Python)</span></b><br />
<br />
使い方は簡単で、移動前と移動先の3つの点(つまり三角形)を行列にして変形させるだけ。<br />
コードはこんな感じです。<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> import cv2
import numpy as np</code></pre>
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> im = cv2.imread('squares.jpg')
points1 = [[50,50],[150,50],[50,150]]
points2 = [[75,75],[150,50],[50,150]]
M = cv2.getAffineTransform(np.float32(points1), np.float32(points2))
im2 = cv2.warpAffine(im, M, (200,200))
cv2.imwrite('transformed_squares.jpg', im2)
</code></pre>
<br />
(流れ)<br />
1.画像を読み込む<br />
2.移動前の点を決める<br />
3.移動後の点を決める<br />
4.上の2つを使って行列を取得<br />
5.200x200サイズでアフィン変形する<br />
6.画像を保存 <br />
<br />
※つまり、他の2点は同じなので、(50,50) の点を (75,75)に移動させるだけになります。<br />
<br />
<br />
実際に画像は以下になります。<br />
<br />
(変形前) <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPDuFws4i0qh_j0T5wVwpvX36PAmxDv8oJcvXJ4Vyg_1xLrGnMxBEWlFmXIBvR__RmAvl8DiqFjJi5OkYUG3jy3NnNdz5hzbT5vFxoZfXPxXCy1l8MVaqF5ZabEMXvzhkBp-HEKr-igS7g/s1600/squares.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPDuFws4i0qh_j0T5wVwpvX36PAmxDv8oJcvXJ4Vyg_1xLrGnMxBEWlFmXIBvR__RmAvl8DiqFjJi5OkYUG3jy3NnNdz5hzbT5vFxoZfXPxXCy1l8MVaqF5ZabEMXvzhkBp-HEKr-igS7g/s320/squares.jpg" width="320" /></a></div>
<br />
(変換後)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh43IV4AAFXlkPs1lvWtmv59Zkx-fUAgz9WaKIojK1o1AnMqkmt-Kt0MInMGM75_bGEqql3OGSVlZ-pB9f_i3It34hiKZHzsnETmswLyGRjXwhzZY8gOKwOycxlj4dMA_xYrGWJ10zMBoik/s1600/transformed_squares.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh43IV4AAFXlkPs1lvWtmv59Zkx-fUAgz9WaKIojK1o1AnMqkmt-Kt0MInMGM75_bGEqql3OGSVlZ-pB9f_i3It34hiKZHzsnETmswLyGRjXwhzZY8gOKwOycxlj4dMA_xYrGWJ10zMBoik/s320/transformed_squares.jpg" width="320" /></a></div>
<br />
<br />
<span style="font-size: large;"><b>移動した後、その他の点は?</b></span><br />
<br />
さぁ、ではここからが本題です。<br />
先ほど見ていただいた画像の右下に「?」マークと少し大きな赤丸があったかと思います。<br />
この点は変形前は (150,150) の位置にあります。<br />
じゃあ、変形後の座標をどうやって計算したらいいの?を解決する方法です。<br />
<br />
実際のコードはこんな形です。<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> import numpy as np </code></pre>
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> point = np.float32((150,150))
x = </code><code style="color: black; word-wrap: normal;"><code style="color: black; word-wrap: normal;">point[0]</code>
y = </code><code style="color: black; word-wrap: normal;"><code style="color: black; word-wrap: normal;">point[1]</code>
new_x = M[0][0]*x + M[0][1]*y + np.float32(M[0][2])
new_y = M[1][0]*x + M[1][1]*y + np.float32(M[1][2])
print (int(new_x), int(new_y))
</code></pre>
<br />
変形前の点を公式に当てはめるだけでOKです。 <br />
<br />
※ M は上のコードで作った行列になります。<br />
<br />
<br />
<b><span style="font-size: large;">終わりに</span></b><br />
<br />
行列という概念は高校の数学ででくる(らしい)のですが、正直言って今回初見ぐらいの気分でした。<br />
ただ、画像処理にはとても便利なのでやはりきちんと数学(幾何学?)も勉強していこうと思います。<br />
学生の頃は何に役に立つんだ?と思ってましたが、これはとても役に立つし、正直やってて面白いですね。<br />
<br />
新しい発見でした(^o^)<br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqcCXDJTGDl_Ipe7jhhT-hVknvgaD4VpIAys3-JnotAt_23wz2QSQsPcI7kFbTyQx3vXG-NQBdWGvwx82xmNGQ4qDxcLGh43VHgaeNS8xRNX02KFyl7B-cNDEB3sxjl25Au2fGJh-we4JI/s1600/fasdfsd.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqcCXDJTGDl_Ipe7jhhT-hVknvgaD4VpIAys3-JnotAt_23wz2QSQsPcI7kFbTyQx3vXG-NQBdWGvwx82xmNGQ4qDxcLGh43VHgaeNS8xRNX02KFyl7B-cNDEB3sxjl25Au2fGJh-we4JI/s320/fasdfsd.png" width="258" /></a></div>
Anonymoushttp://www.blogger.com/profile/15645657529148406101noreply@blogger.com0tag:blogger.com,1999:blog-6545450414259005128.post-48203053567295283482017-02-24T18:21:00.000+09:002017-05-02T04:43:51.890+09:00Python で画像を引っぱるように歪める最近の開発で python の画像処理を勉強しているのですが、なかなか「引っぱるように画像を歪める」ということができませんでした。<br />
いわゆる gimp でいうところの「対話的歪め」とか iwarp というやつです。 <br />
そして、それを今回なんとか実現することができましたので、備忘録として残しておこうと思います。<br />
<br />
<span style="color: #990000;">(追記) pip でインストールできるようパッケージ化しました</span><br />
<span style="color: #990000;"><span style="color: #990000;">↓</span></span><span style="color: #990000;"><span style="color: #990000;"><span style="color: #990000;">↓</span></span></span><span style="color: #990000;"><span style="color: #990000;"><span style="color: #990000;"><span style="color: #990000;">↓</span></span></span></span><br />
<span style="color: #990000;"><span style="color: #990000;"><span style="color: #990000;"><span style="color: #990000;"> </span></span></span></span><a href="https://github.com/SUKOHI/PiecewiseDistortion" target="_blank">PiecewiseDistortion</a><br />
<br />
<br />
(つまり画像で言うと↓↓↓)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFAVo6QVxT5tvv0hVEwytM5ZSv02LSEw8A2G5IX8d8vSmRTc1IvqQMMJMc2duVb8LN1NxzCdSgMXLkP87dKO1PHGk-5znZJF6AzpdKBkKExEYPG5Sr9mRm6L4_tw40swJBl9Jfd7gskRMY/s1600/lena_distorted.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFAVo6QVxT5tvv0hVEwytM5ZSv02LSEw8A2G5IX8d8vSmRTc1IvqQMMJMc2duVb8LN1NxzCdSgMXLkP87dKO1PHGk-5znZJF6AzpdKBkKExEYPG5Sr9mRm6L4_tw40swJBl9Jfd7gskRMY/s1600/lena_distorted.jpg" /></a></div>
<br />
ということです。<br />
<br />
※ちなみにこの処理には scikit-image を利用するので以下のようにインストールをしておいてください。<br />
<br />
<pre><span style="background-color: #cccccc;"><span class="n">pip</span> <span class="n">install</span> <span class="n">scikit</span><span class="o">-</span><span class="n">image</span></span></pre>
<pre><span class="n"> </span></pre>
<pre><span class="n"> </span></pre>
<br />
<b><span style="font-size: large;">まずは手順</span></b><br />
<br />
手順としては<br />
<br />
<ol>
<li>歪めたい範囲を指定</li>
<li>どこからどこまで移動させたいかを指定</li>
</ol>
とするとやりたいことが実現できました。<br />
<br />
<br />
<b><span style="font-size: large;">実際のコード</span></b><br />
<br />
では実際のコードを紹介します。<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;">import skimage.transform
from PIL import Image
import numpy as np
def distort(file_path, roi_points, from_points, to_points):
im = Image.open(file_path).convert('RGBA')
from_points = np.concatenate((roi_points, from_points))
to_points = np.concatenate((roi_points, to_points))
affin = skimage.transform.PiecewiseAffineTransform()
affin.estimate(to_points, from_points)
im_array = skimage.transform.warp(im, affin)
im_array = np.array(im_array * 255., dtype=np.uint8)
if im_array.shape[2] == 1:
im_array = im_array.reshape((im_array.shape[0],im_array.shape[1]))
warped_im = Image.fromarray(im_array, 'RGBA')
im.paste(warped_im, (0, 0), warped_im)
return im
file_path = 'lena.jpg'
roi_points = [(100,100),(400,100),(400,400),(100,400)]
from_points = [(300,300),(250,250)]
to_points = [(350,350),(200,200)]
im = distort(file_path, roi_points, from_points, to_points)
im.save('lena_distorted.jpg')
</code></pre>
<br />
<br />
(上のコードを実行した結果↓↓↓)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZHG4c4rosTyRjomm1_9NL15Brh_Ig2EO2lHjbFuT-awL99iQ6cUUJcdTY8w0zNpnRJgdK6Q1cd9Xm3fEHu-LU29iacnqKMhSoCbbKv_xv4SADe35Mb5FYhAG4vaoYYEAY_Qvf89hgj3jH/s1600/lena_distorted2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZHG4c4rosTyRjomm1_9NL15Brh_Ig2EO2lHjbFuT-awL99iQ6cUUJcdTY8w0zNpnRJgdK6Q1cd9Xm3fEHu-LU29iacnqKMhSoCbbKv_xv4SADe35Mb5FYhAG4vaoYYEAY_Qvf89hgj3jH/s1600/lena_distorted2.jpg" /></a></div>
<br />
※画像のサイズは 512x512でした。元画像の lenaさんには申し訳ないですがうまくゆがんでいるのがわかるかと思います。<br />
<br />
<br />
<b><span style="font-size: large;">この作業を通じて思ったこと</span></b><br />
<br />
どこかの記事で「プログラミング別収入ランキング」というのを読んだことがあるのですが、たしか python が一位でした。<br />
その時はそうなんだ、ぐらいに思っていたのですがその理由が少し分かった気がします。<br />
つまり、<br />
<br />
<b>python の収入が高いというよりは、python は数学、科学との連携が強みのため、そういった理数系の知識が豊富な開発は収入が高い</b><br />
<br />
ということになるのだと思いました。<br />
やっぱり理数系の知識って必要ですね。<br />
今回久しぶりに sin cos などを使って懐かしい反面、「え!こんな便利に使えるものなんだ!」と思いました。<br />
学校の勉強がいかに面白くなく感じていたか、、、と思う今日このごろです(笑)<br />
<br />
ではでは。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyupc4S66VSBoS5HqsrAEZkZiNF4hCvk-nuZFgea4EpfZ5ULDeMSqX9ipuQzFkVCKN6tPb1zpHBMamwX5qFv_LQubkdru32mL1dX-UkOvgYBqhRr2D7PP7MOpySXV84maaTmnzuQPRcQMq/s1600/23.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyupc4S66VSBoS5HqsrAEZkZiNF4hCvk-nuZFgea4EpfZ5ULDeMSqX9ipuQzFkVCKN6tPb1zpHBMamwX5qFv_LQubkdru32mL1dX-UkOvgYBqhRr2D7PP7MOpySXV84maaTmnzuQPRcQMq/s1600/23.png" /></a></div>
<br />Anonymoushttp://www.blogger.com/profile/15645657529148406101noreply@blogger.com0tag:blogger.com,1999:blog-6545450414259005128.post-63682739416738217972017-02-14T19:07:00.000+09:002017-02-14T19:07:43.763+09:00React.js は SEO に悪いか?最近では React や Angular などの JavaScript フレームワークの開発がとても活発になっていますが、ふと「クライアントサイドでコンテンツを作ってしまったら検索エンジンはページを読み込めないんじゃ?(つまりSEO的にやばいんじゃ?)」と思ったので少し調べてみました。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmfN-zjs4pDuldGx7ocgNb5EZokjdUQ_dt5RN24glHusNcxXRQ31-u4moq_-GtQjpcetg7DmWgegDyeznn58KemN5Ujfn_OrRnk_dQFBP3BobAsReP_StaRMJBs7DaLEM2emOv3x9_rZVm/s1600/search-engine-optimization-586422_640.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="212" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmfN-zjs4pDuldGx7ocgNb5EZokjdUQ_dt5RN24glHusNcxXRQ31-u4moq_-GtQjpcetg7DmWgegDyeznn58KemN5Ujfn_OrRnk_dQFBP3BobAsReP_StaRMJBs7DaLEM2emOv3x9_rZVm/s320/search-engine-optimization-586422_640.jpg" width="320" /></a></div>
<br />
<b><span style="font-size: large;">検索エンジンはJSのレンダリングに対応してる?</span></b> <br />
<br />
<a href="https://medium.freecodecamp.com/seo-vs-react-is-it-neccessary-to-render-react-pages-in-the-backend-74ce5015c0c9#.qwb5reylb" target="_blank">https://medium.freecodecamp.com/seo-vs-react-is-it-neccessary-to-render-react-pages-in-the-backend-74ce5015c0c9#.qwb5reylb</a><br />
<br />
↑<br />
こちらの記事でいろいろな調査を行っているので参考にさせてもらいました。<br />
<br />
まずこの記事では、「SEO業者はJavaScriptは使わずHTMLを使うほうがいい」と言っているがこれは間違っていて、その証拠に Google が公式ブログで投稿したページをあげています。<br />
<br />
内容としては<br />
<br />
<blockquote class="tr_bq">
Times have changed. Today, as long as you're not blocking Googlebot from
crawling your JavaScript or CSS files, we are generally able to <a href="http://googlewebmastercentral.blogspot.com/2014/05/understanding-web-pages-better.html">render and understand your web pages like modern browsers</a>. </blockquote>
<br />
(日本語超意訳) JS とか CSS をブロックしてない限り Google はちゃんとページを読んでるよ。(≒検索エンジンに反映するよ!)<br />
<br />
となっています。<br />
<br />
これは 2015年に投稿されたものですので2017年の現在では当然のように JavaScript & CSS を使ったクライアントサイドのレンダリングにも対応していると考えていいでしょう。<br />
<br />
さらに、個人的な感想でいうと Angular は Google の開発プロジェクトなのでクライアントサイドのレンダリングは重要視していると考えています。<br />
<br />
※ちなみにこの記事には2016/10/25に追記があって、他の人の調査でも Google は問題なくページを読み込んでいることが分かったとしていますが、検索エンジンに反映されるには数日遅れているという結論に達しています。<br />
<br />
<br />
<b><span style="font-size: large;">他の検索エンジンは?</span></b><br />
<br />
では、Google は問題ないとして、Bing や Yahoo など他の検索エンジンはどうなのでしょうか。<br />
正直言って日本の検索エンジンは Google の独占状態(YahooもGoogleの検索結果をもとにしているため)なのであまり他の検索エンジンを考えなくてもいいかもしれませんが以下に彼の調査結果を紹介したいと思います。<br />
<br />
調査の対象になったのは <a href="https://preactjs.com/" target="_blank">Preact</a> と呼ばれるたった 3KB しかない React の軽量版のウェブページです。Preactはいわゆる SPA(Single Page Application) なので、もし Google のクローラーが JavaScript を理解できていなければ検索エンジンに表示されることはないということになります。<br />
<br />
※ちなみにPreact は今回初めて知りました。実際アクセスすればよくわかりますがホントに超高速で表示してくれます。少し今後の展望を考えてしまいました。(^^)<br />
<br />
<br />
結果は以下のとおりです。<br />
<br />
<ul>
<li><a href="https://www.google.co.jp/search?q=site:preactjs.com&gws_rd=cr&ei=MdKiWNqMI8ui0gSh54CoCA" target="_blank">Google</a></li>
<li><a href="http://www.bing.com/search?q=site%3Apreactjs.com" target="_blank">Bing</a></li>
<li><a href="https://de.search.yahoo.com/search?p=site%3Apreactjs.com&fr=yfp-t-911" target="_blank">Yahoo(海外の)</a></li>
<li><a href="https://duckduckgo.com/?q=site%3Apreactjs.com&t=h_&ia=web" target="_blank">DuckDuckGo(初めて知りました)</a> </li>
</ul>
<br />
ご覧いただけるとわかると思いますが、問題なくインデックスされています。<br />
<br />
ただし、一点だけインデックスされていない検索エンジンがあったようで、それが「<a href="http://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=0&rsv_idx=1&tn=baidu&wd=site%3Apreactjs.com&rsv_pq=95cb9d6800010ec6&rsv_t=6911YYLRspihOnU5UaDpw8Yo%2FPGDwlfONvdplHywgiMlqY198%2BLvxU6yzwI&rqlang=cn&rsv_enter=1&rsv_sug3=17&rsv_sug2=0&inputT=37643&rsv_sug4=37643" target="_blank">Baido(百度)</a>」です。<br />
<br />
そのため、現時点では Baido へのインデックスが必須であるなら従来通りサーバーサイドでのレンダリングをするべきでしょう。<br />
<br />
<br />
<b><span style="font-size: large;">個人的な結論</span></b><br />
<br />
Google をはじめ、クライアントサイドでのレンダリングも問題ないようなので、SEOに関しては気にする必要はなさそうです。<br />
しかも、我々が持っているスマートフォンなどの機会がよりハイスペックになってきているため、クライアントサイドでのレンダリングは時代にかなったテクニックだとも思います。<br />
ホントに高速表示が可能ですしね。<br />
<br />
ということで、今回は以上です。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjeiIhkK22V_5HpI-p749M0I1d2BxcGF0TK7yBGOlQCaKZrtCPH6YmCucrnWrltmPT-Vokcdb1c9IW4WSmhnUOBBVhJK-yHJbyn0esuj9TPnQnfe3ifcIqPMz9OAubTjXBm0TkUNCztIWXy/s1600/39.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="314" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjeiIhkK22V_5HpI-p749M0I1d2BxcGF0TK7yBGOlQCaKZrtCPH6YmCucrnWrltmPT-Vokcdb1c9IW4WSmhnUOBBVhJK-yHJbyn0esuj9TPnQnfe3ifcIqPMz9OAubTjXBm0TkUNCztIWXy/s320/39.png" width="320" /></a></div>
Anonymoushttp://www.blogger.com/profile/15645657529148406101noreply@blogger.com0tag:blogger.com,1999:blog-6545450414259005128.post-28070480465743919452017-02-03T20:46:00.000+09:002017-02-03T20:46:59.400+09:00Vue.js 2.0 を使ってみた9つの感想これまで、ウェブサイト開発にはメインで Bootstrp(つまり jQuery) を利用していたので、最近よく聞くようになった React、Angular、それから今回感想を書く Vue.js は敬遠していました。<br />
なぜなら、コードがどこかで衝突するんじゃないかと敬遠していたからです。<br />
<br />
ただ、最近の盛り上がりを見るとそうもいっていられないな、と思い今回メインとして Vue 2.0 を試してみましたのでその感想をまとめておきたいと思います。<br />
<br />
<br />
<br />
<u>1.速い!!</u><br />
<br />
とにかく初めて Vue を使ったときに感じたのが「速い!」でした。<br />
元々 jQuery でも遅いとは感じたことはなかったのですが、Vue はさらに快適なリアクションをしてくると感じました。<br />
特にループでコンテンツを量産する場合では速いですね。<br />
<br />
<br />
<u>2.簡単!</u><br />
<br />
フレームワークなりプログラミング言語なり、新しいものを採用するときにどうしても避けられないのが「学習コスト」です。<br />
みんながいいと言ってるから便利なのは間違いないんだろうけど、一から勉強するには時間がかかってしまうのはときに大きなハードルになります。<br />
<br />
でも、Vue ならそんな心配は不要だと思います。<br />
正直私も一連の YouTube 動画を見ただけですぐに使いはじめることができました。<br />
<br />
※ちなみに以下が YouTube 動画のリスト(英語)です。<br />
<br />
<a href="https://www.youtube.com/channel/UC6kwT7-jjZHHF1s7vCfg2CA/search?query=vue" target="_blank">動画の一覧</a><br />
<br />
<br />
<u>3.メンテナンスがしやすい</u><br />
<br />
書いたコードが jQuery よりもすっきりするのでメンテナンスもしやすいですね。<br />
<br />
<br />
<u>4.サーバーからのサイズが(少しだけ)減る</u><br />
<br />
通常 PHP などでコンテンツを作成すると フルに HTML を作成する必要があるため、ループする内容が多いときなどは特にページのサイズが大きくなってしまいます。<br />
<br />
でも、Vue を利用するとループする部分は実際にページを見る PC やスマートフォンで作成してくれるのでサイズが比較的少なくなり、これも速さに貢献できる部分だと思います。<br />
<br />
最近のスマートフォンはハイスペックになってきているので時代にも合っているんじゃないでしょうか。<br />
<br />
<br />
<u>5.jQuery との衝突がなかった</u><br />
<br />
まだそこまで Vue での開発経験があるわけではないので、今後何か問題がおこる可能性はありますが、今のところ全く衝突はありませんでした。<br />
<br />
実際に開発した例では bootstrap を利用していたので Ajax 部分や タブの切り替えなどは jQuery を利用していましたが快適に開発を進めることができました。<br />
<br />
<u><br /></u>
<u>6.デザイナーさんにもわかりやすい</u><br />
<br />
例えば、Vue を使って画像データのバインディングをする場合は<br />
<br />
<img :src="{{ url }}"><br />
という風に通常の HTML と同じようにパッと見ただけでわかりやすい書き方になっています。<br />
おそらくデザイナーさんにもわかりやすいので使いやすいんじゃないでしょうか。<br />
<br />
<br />
<u>7.単体で動く</u><br />
<br />
以前 React を使ったことがあり React もいいなとは思っていたのですが、書き始めるまでにBabel を用意するなどの必要がありました(今は違う?)。でも Vue は単体でシンプルに動きますし、cdn も用意されているのでとても簡単に開発を始められます。<br />
<br />
<br />
<u>8.Laravel に採用されている</u><br />
<br />
まだ実際には使ってはいませんが Laravel には Vue Component という機能があり、より Vue との統合がしやすくなっています。<br />
私は Laravel Lover ですのでここもプラス要素ですね。<br />
<br />
<br />
<u>9.日本語のドキュメントも用意されている </u><br />
<br />
やっぱり複雑なことを学ぶには母国語が一番です。<br />
<br />
<br />
【結論】<br />
<br />
とても Vue は便利で使いやすいです。<br />
ですので、今後の開発でも積極的に利用したいと思いました。 <br />
<br />
また、バージョンがまだ2ということなので、今後開発が進むと、より便利な機能が追加されるかもしれません。<br />
<br />
みなさんも興味があったらぜひ使ってみてはいかがでしょうか。<br />
ではではー!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAUa_h7WsKCLSGsFP3GN3ENCETgj9WhgEW5QgzGu1Clqqaj8uwP6t6Yhg0ipY9wY8opLVa-mCxCRicI_L5exQmBL-Ygfz9JwBW6zmwmqOMrbTavv-pTuLQElwyhL9R0JBbTWK9DIGceN5K/s1600/%25E3%2583%2580%25E3%2582%25A6%25E3%2583%25B3%25E3%2583%25AD%25E3%2583%25BC%25E3%2583%2589+%25287%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAUa_h7WsKCLSGsFP3GN3ENCETgj9WhgEW5QgzGu1Clqqaj8uwP6t6Yhg0ipY9wY8opLVa-mCxCRicI_L5exQmBL-Ygfz9JwBW6zmwmqOMrbTavv-pTuLQElwyhL9R0JBbTWK9DIGceN5K/s320/%25E3%2583%2580%25E3%2582%25A6%25E3%2583%25B3%25E3%2583%25AD%25E3%2583%25BC%25E3%2583%2589+%25287%2529.png" width="286" /></a></div>
<br />
Anonymoushttp://www.blogger.com/profile/15645657529148406101noreply@blogger.com0tag:blogger.com,1999:blog-6545450414259005128.post-2977589981095913122017-01-24T18:14:00.000+09:002017-01-25T00:01:16.647+09:00顔の入れ替えを試してみた【Ubuntu】 <div style="text-align: left;">
ふとしたきっかけで画像の顔だけを入れ替える(正確にはある画像の顔を別の人の顔にする)というプログラムが公開されているのを知ったので、いつも利用しているPCにインストールして試してみました。</div>
<div style="text-align: left;">
思ったより簡単にインストールできたので興味のある方はぜひ試してみてください。<br />
<br />
【実行環境】 Ubuntu 16.04 </div>
<div style="text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjH5_Jxljdfs05aWw95XbAPSmS9VCquXWPUfz7X6v33TqyrZDWoGGX-nYu-4imjz5sfEYipXidSOC3oR0sfq38_ZTGPqCvzWnZIHKlW6dFukgU9OuE8xQtqZePQ-zsYf9-TPnP_-tBrHK1l/s1600/mona-lisa-1846976_640.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="296" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjH5_Jxljdfs05aWw95XbAPSmS9VCquXWPUfz7X6v33TqyrZDWoGGX-nYu-4imjz5sfEYipXidSOC3oR0sfq38_ZTGPqCvzWnZIHKlW6dFukgU9OuE8xQtqZePQ-zsYf9-TPnP_-tBrHK1l/s400/mona-lisa-1846976_640.jpg" width="400" /></a></div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
※顔の入れ替えにはPythonが利用されています。もしPythonがインストールされていない場合はインストールしておいてください。<br />
<br /></div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
<b>【手順1】 </b>まず、メインとなるPythonプログラムは <a href="https://github.com/matthewearl/faceswap" target="_blank">GitHub</a> で公開されています。</div>
<div style="text-align: left;">
そのため、まずこのプログラムを以下のようにしてダウンロードしましょう。</div>
<div style="text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiP-iaGPRbJ9hJrKtiAQpggHw-PMx5S4OV3rselCsUtWlhJuCoU42iArT6yL5JrMftbo_AKpxqpfv-unZ9GUTKbmOe11lWiAUS8OJbXbisL_v09NKtMjKnb0tWTDBsubKUD_RyKfFVYVnm0/s1600/1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="262" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiP-iaGPRbJ9hJrKtiAQpggHw-PMx5S4OV3rselCsUtWlhJuCoU42iArT6yL5JrMftbo_AKpxqpfv-unZ9GUTKbmOe11lWiAUS8OJbXbisL_v09NKtMjKnb0tWTDBsubKUD_RyKfFVYVnm0/s400/1.png" width="400" /></a></div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
ダウンロードしたら適当な場所に展開しましょう。</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
<b>【手順2】</b> そして、ついでにもうひとつダウンロードする必要があるので以下のようにGitHubのリンク(SourceForge)からダウンロードして中身を展開しておきます。</div>
<div style="text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjexPkOX8YGamB35EjTzYLBaQco-Pekfo7vxFCRvYa-SqIk5MVzO97yGt7XZEijWfO_6taF2hXi4rPTVV63OqZtO6P0QrUoZzb92mNCRkePp4JFBJUMou8Z2y6borv7arrkM8bnb-tzkSRK/s1600/Screenshot+from+2017-01-24+05-12-27.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="141" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjexPkOX8YGamB35EjTzYLBaQco-Pekfo7vxFCRvYa-SqIk5MVzO97yGt7XZEijWfO_6taF2hXi4rPTVV63OqZtO6P0QrUoZzb92mNCRkePp4JFBJUMou8Z2y6borv7arrkM8bnb-tzkSRK/s400/Screenshot+from+2017-01-24+05-12-27.png" width="400" /></a></div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
<b>【手順3】</b> 以下のURLへアクセスし、ページ中央からdlib C++ Libraryをダウンロード、これも展開しておきましょう。</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
<a href="http://dlib.net/" target="_blank">http://dlib.net/</a></div>
<div style="text-align: left;">
</div>
<div style="text-align: left;">
</div>
<div style="text-align: left;">
</div>
<div style="text-align: left;">
</div>
<div style="text-align: left;">
</div>
<div style="text-align: left;">
</div>
<div style="text-align: left;">
</div>
<div style="text-align: left;">
</div>
<div style="text-align: left;">
</div>
<div style="text-align: left;">
</div>
<div style="text-align: left;">
</div>
<div style="text-align: left;">
</div>
<div style="text-align: left;">
</div>
<div style="text-align: left;">
</div>
<div style="text-align: left;">
</div>
<div style="text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-Zfctj13ZbNFgNRwTlNUtqfNumlJxy1AmHAQGIlj0ms0vNnxyTN-BbaSxPCngbH0ehA5xplDQN_C8MMDGX9tMLNhyy9uyuOsP981cuiypBXQAlzEQCh-iILdCImcxIOO9kqY5WqmSrAo0/s1600/2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="304" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-Zfctj13ZbNFgNRwTlNUtqfNumlJxy1AmHAQGIlj0ms0vNnxyTN-BbaSxPCngbH0ehA5xplDQN_C8MMDGX9tMLNhyy9uyuOsP981cuiypBXQAlzEQCh-iILdCImcxIOO9kqY5WqmSrAo0/s400/2.png" width="400" /></a></div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
展開したらそのフォルダに<u>ターミナルで移動</u>し、以下の順番でコンパイルします。</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
<pre class="code_box"><span style="background-color: #cccccc;">cd examples
mkdir build
cd build
cmake ..
cmake --build . --config Release</span></pre>
</div>
<div style="text-align: left;">
<br />
そして、またdlibトップフォルダに戻り、setup.py を実行します。<br />
<br />
<span style="background-color: #cccccc;">sudo python setup.py install</span><br />
<br />
<br />
<b>【手順4】</b>そして、Pyhon用の OpenCV もインストールしましょう。</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
<pre class="lang-py prettyprint prettyprinted"><span style="background-color: #cccccc;"><code><span class="pln">sudo apt</span><span class="pun">-</span><span class="pln">get install python</span><span class="pun">-</span><span class="pln">opencv</span></code></span></pre>
<pre class="lang-py prettyprint prettyprinted"><code><span class="pln"> </span></code></pre>
<pre class="lang-py prettyprint prettyprinted"><code><span class="pln"> </span></code></pre>
<pre class="lang-py prettyprint prettyprinted"><code><span class="pln">では次に<b>【手順1】</b>で展開したフォルダの中に入って「faceswap.py」を</span></code></pre>
<pre class="lang-py prettyprint prettyprinted"><code><span class="pln">テキストエディタで開くと、</span></code></pre>
<pre class="lang-py prettyprint prettyprinted"><span style="background-color: #999999;"><u><code><span class="pln">
</span></code></u></span></pre>
<pre class="lang-py prettyprint prettyprinted"><span style="background-color: #cccccc;"><code><span class="pln">PREDICTOR_PATH = "/home/matt/dlib-18.16/shape_predictor_68_face_landmarks.dat"</span></code></span></pre>
<pre class="lang-py prettyprint prettyprinted"><code><span class="pln"> </span></code></pre>
<pre class="lang-py prettyprint prettyprinted"><code><span class="pln">という行があるはずなので、このパスを<b>【手順2】</b>でダウンロードしたファイルを指定します。</span></code></pre>
<pre class="lang-py prettyprint prettyprinted"><code><span class="pln">
</span></code></pre>
<pre class="lang-py prettyprint prettyprinted"><code><span class="pln">※私の環境では以下のようになりました。</span></code></pre>
<pre class="lang-py prettyprint prettyprinted"><code><span class="pln">
</span></code></pre>
<pre class="lang-py prettyprint prettyprinted"><span style="background-color: #cccccc;"><code><span class="pln">PREDICTOR_PATH = "/home/sukohi/Downloads/shape_predictor_68_face_landmarks.dat"</span></code></span></pre>
<pre class="lang-py prettyprint prettyprinted"><span style="background-color: #cccccc;"><code><span class="pln"><span style="background-color: white;"></span>
</span></code></span></pre>
<pre class="lang-py prettyprint prettyprinted"><span style="background-color: #cccccc;"><code><span class="pln"><span style="background-color: white;"></span>
</span></code></span></pre>
<div style="text-align: left;">
<span style="font-size: large;"><b>【顔の入れ替えを実行】</b></span></div>
<pre class="lang-py prettyprint prettyprinted"><span style="background-color: #cccccc;"><code><span class="pln"><span style="background-color: white;"></span></span></code></span></pre>
<pre class="lang-py prettyprint prettyprinted"><span style="background-color: #cccccc;"><code><span class="pln"><span style="background-color: white;">では準備が完了したので実際に試してみましょう。</span></span></code></span></pre>
<pre class="lang-py prettyprint prettyprinted"><span style="background-color: #cccccc;"><code><span class="pln"><span style="background-color: white;">画像は以下の2枚をPixabay からダウンロードしてきました。</span></span></code></span></pre>
<pre class="lang-py prettyprint prettyprinted"><span style="background-color: #cccccc;"><code><span class="pln">
</span></code></span></pre>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7NcEdp7TShTU4_n4ju6vFYkEUngdjKp70drpTY8lngg8zXAyy9Le9QUGACWzxxObu782Q_-4EDdfC1UUv8KcwEgkaW0McUIe8hw3FIiA6DIh8QN4E9_3-dD_HaD2e2pS8PJnXlIC_yOcT/s1600/face.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="213" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7NcEdp7TShTU4_n4ju6vFYkEUngdjKp70drpTY8lngg8zXAyy9Le9QUGACWzxxObu782Q_-4EDdfC1UUv8KcwEgkaW0McUIe8hw3FIiA6DIh8QN4E9_3-dD_HaD2e2pS8PJnXlIC_yOcT/s320/face.jpg" width="320" /></a></div>
<div style="text-align: center;">
face.jp</div>
<div style="text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXoA_S4_d2MO3XUHpkWwAi2uY9RiKbWhPj0KT9StzNnByPy_yPEGibbBAqIi1ZwlYnSKNO6_O37XGfYbiuUGkvlnJvpubpsi7gx2jCHwuZ4xfyoINC5CSvJ-h8_o39GyQ1ohRiNJrIV6N1/s1600/head.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="190" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXoA_S4_d2MO3XUHpkWwAi2uY9RiKbWhPj0KT9StzNnByPy_yPEGibbBAqIi1ZwlYnSKNO6_O37XGfYbiuUGkvlnJvpubpsi7gx2jCHwuZ4xfyoINC5CSvJ-h8_o39GyQ1ohRiNJrIV6N1/s320/head.jpg" width="320" /></a></div>
<div style="text-align: center;">
<pre class="lang-py prettyprint prettyprinted"><span style="background-color: white;"><code><span class="pln">head.jpg</span></code></span></pre>
<pre class="lang-py prettyprint prettyprinted"><span style="background-color: white;"><code><span class="pln">
</span></code></span></pre>
<div style="text-align: left;">
<pre class="lang-py prettyprint prettyprinted"><span style="background-color: #cccccc;"><code><span class="pln"><span style="background-color: white;">うまくいくと、head.jpg の顔が face.jpg の顔と入れ替えになります。</span></span></code></span></pre>
<pre class="lang-py prettyprint prettyprinted"><span style="background-color: #cccccc;"><code>
</code></span></pre>
<pre class="lang-py prettyprint prettyprinted"><span style="background-color: white;"><code>では、この2つの画像を【手順1】で作成した faceswap のフォルダの中に保存し、</code></span></pre>
<pre class="lang-py prettyprint prettyprinted"><span style="background-color: white;"><code>以下のコマンドを実行しましょう。</code></span></pre>
<pre class="lang-py prettyprint prettyprinted"><span style="background-color: white;"><code>
</code></span></pre>
<pre class="lang-py prettyprint prettyprinted"><span style="background-color: white;"><code><span style="background-color: #cccccc;">sudo ./faceswap.py head.jpg face.jpg</span></code></span></pre>
<pre class="lang-py prettyprint prettyprinted"><span style="background-color: white;"><code>
</code></span></pre>
<pre class="lang-py prettyprint prettyprinted"><span style="background-color: white;"><code>うまくいくと output.jpg という画像が作成されているはずです。</code></span></pre>
<pre class="lang-py prettyprint prettyprinted"><span style="background-color: white;"><code>上の画像を使って実際に作成されたは以下になります。</code></span></pre>
<pre class="lang-py prettyprint prettyprinted"><span style="background-color: white;"><code>
</code></span></pre>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0I6cMLa8LdD2_LMaVs-JqZwWhSE9ONp_scW2ysr7NECLRVUsc_gZ6AvzvBVMjvzD7-_zgjk002ER_XpfCYAwlu565CE0sNpj7QnpprtDnfCLeCtnsrIwGln7haaN27RR_2S8ym-BZ3DCe/s1600/output.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="236" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0I6cMLa8LdD2_LMaVs-JqZwWhSE9ONp_scW2ysr7NECLRVUsc_gZ6AvzvBVMjvzD7-_zgjk002ER_XpfCYAwlu565CE0sNpj7QnpprtDnfCLeCtnsrIwGln7haaN27RR_2S8ym-BZ3DCe/s400/output.jpg" width="400" /></a></div>
<pre class="lang-py prettyprint prettyprinted"><span style="background-color: white;"><code>
</code></span></pre>
<pre class="lang-py prettyprint prettyprinted"><span style="background-color: white;"><code>
</code></span></pre>
<pre class="lang-py prettyprint prettyprinted"><span style="background-color: white;"><code>どうでしょう、すごくないですか?</code></span></pre>
<pre class="lang-py prettyprint prettyprinted"><span style="background-color: white;"><code>お気づきかと思いますが、face.jpg 顔の暗い部分も元画像に適用されて</code></span></pre>
<pre class="lang-py prettyprint prettyprinted"><span style="background-color: white;"><code>一枚の写真になっています。</code></span></pre>
<pre class="lang-py prettyprint prettyprinted"><span style="background-color: white;"><code>こんなプログラムが公開されているなんてすごい時代になりましたね。</code></span></pre>
<pre class="lang-py prettyprint prettyprinted"><span style="background-color: white;"><code>
</code></span></pre>
<pre class="lang-py prettyprint prettyprinted"><span style="background-color: white;"><code>※ちなみに、入れ替えたい顔の目や口元などに髪の毛がかかってしまっていると</code></span></pre>
<pre class="lang-py prettyprint prettyprinted"><span style="background-color: white;"><code>あまりうまくいかないパターンもありました。</code></span></pre>
<pre class="lang-py prettyprint prettyprinted"><span style="background-color: white;"><code>また、背景にいろいろとものが写っていたりすると顔を検出できないパターンや、</code></span></pre>
<pre class="lang-py prettyprint prettyprinted"><span style="background-color: white;"><code>まれなケースでは全く別の部分に顔が移植されてしまうこともありましたので</code></span></pre>
<pre class="lang-py prettyprint prettyprinted"><span style="background-color: white;"><code>まだ完璧ではないようですが、こういうのを作る人ってすごいですよね。</code></span></pre>
<pre class="lang-py prettyprint prettyprinted"><span style="background-color: white;"><code>
</code></span></pre>
<pre class="lang-py prettyprint prettyprinted"><span style="background-color: white;"><code>今回は以上です。</code></span></pre>
<pre class="lang-py prettyprint prettyprinted"><span style="background-color: white;"><code>
</code></span></pre>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqcCXDJTGDl_Ipe7jhhT-hVknvgaD4VpIAys3-JnotAt_23wz2QSQsPcI7kFbTyQx3vXG-NQBdWGvwx82xmNGQ4qDxcLGh43VHgaeNS8xRNX02KFyl7B-cNDEB3sxjl25Au2fGJh-we4JI/s1600/fasdfsd.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqcCXDJTGDl_Ipe7jhhT-hVknvgaD4VpIAys3-JnotAt_23wz2QSQsPcI7kFbTyQx3vXG-NQBdWGvwx82xmNGQ4qDxcLGh43VHgaeNS8xRNX02KFyl7B-cNDEB3sxjl25Au2fGJh-we4JI/s320/fasdfsd.png" width="258" /></a></div>
<pre class="lang-py prettyprint prettyprinted"><span style="background-color: white;"><code>
</code></span></pre>
</div>
</div>
</div>
Anonymoushttp://www.blogger.com/profile/15645657529148406101noreply@blogger.com0tag:blogger.com,1999:blog-6545450414259005128.post-11817382222700014322016-12-20T01:50:00.000+09:002016-12-20T01:50:37.164+09:00ファビコンを自動でつくってくれるサイト「Favicon Generator」を使ってみた。サイト開発をしていて結構めんどくさい作業なのがファビコンの作成です。<br />
特にこだわらない場合は favicon.ico というファイルを ico 形式の画像を作ってリンクすればいいだけですが、iPhoneなど様々な機種に対応させたい場合は個別に画像を用意してその全てにリンクなど HTML タグを追加しなければいけません。<br />
<br />
そこで紹介するのが「<span style="font-size: large;"><a href="http://realfavicongenerator.net/" target="_blank">Favicon Generator</a></span>」です。<br />
<br />
このサイトは画像を送信するだけで、様々なサイズのファビコンを作成してくれるというとても便利なサイトです。<br />
また、必要なHTMLタグも表示してくれるので、それらをコピーするだけで設定も完了します。<br />
<br />
では、作り方をひとつひとつ見ていきましょう。<br />
<br />
<br />
<span style="font-size: large;"><b>1.画像のアップロード </b></span><br />
<br />
画像の赤枠にあるボタンをクリックしてファビコンにしたい画像を選択します。<br />
<br />
※注: 最低でも 70 x 70 px 以上の画像を選んでください。推奨は260 x 260 px 以上です。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfDgVAvphoGdWRjSA9s3Dei-ESAWIQIokU6f7GCEmxgtyLffEL8CyNqlI_Wm_2GkibUns3WIygfESQYPfGkOhKEGPP5LB4_aPx2YS0CtOHcRsePOEY611W-Ho56-a8VS7NXoPochHrRsiP/s1600/Favicon+Generator+for+all+platforms++iOS++Android++PC+Mac....png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="167" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfDgVAvphoGdWRjSA9s3Dei-ESAWIQIokU6f7GCEmxgtyLffEL8CyNqlI_Wm_2GkibUns3WIygfESQYPfGkOhKEGPP5LB4_aPx2YS0CtOHcRsePOEY611W-Ho56-a8VS7NXoPochHrRsiP/s400/Favicon+Generator+for+all+platforms++iOS++Android++PC+Mac....png" width="400" /></a></div>
<br />
<br />
<b><span style="font-size: large;">2.ファビコンの設定をする</span></b><br />
<br />
ここから iPhone など各機種向けの設定をします。<br />
<br />
注意が必要なのは iOS です。<br />
iOS のアイコンは透過画像に対応していません。<br />
そのため、もしファビコンに png などの透過画像が利用されている場合、背景が真っ黒になってしまします。<br />
<br />
これを防ぐためには以下の赤枠のラジオボタンにチェックを入れ、その下の色の設定を変更する必要があります。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgt7Of7dEf0inlaHjlW-owdAchrXokisLWmaW-_Y1Gp_DUCjnM_G8qJa2BcniOLgRhmCJTB3ruWTsPgM2AqZ7k9PAXFPdx1ACk_oaOd374fJFRiaGKmuD_nSMXUuULWLsNWBjc9rU_bT5DH/s1600/Favicon+Generator+for+all+platforms++iOS++Android++PC+Mac...%25281%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="125" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgt7Of7dEf0inlaHjlW-owdAchrXokisLWmaW-_Y1Gp_DUCjnM_G8qJa2BcniOLgRhmCJTB3ruWTsPgM2AqZ7k9PAXFPdx1ACk_oaOd374fJFRiaGKmuD_nSMXUuULWLsNWBjc9rU_bT5DH/s400/Favicon+Generator+for+all+platforms++iOS++Android++PC+Mac...%25281%2529.png" width="400" /></a></div>
<br />
その他 chrome や windows の設定ができますが、同じように設定を変更すると自動でサンプル画像が変更しますのでお好みの設定に変更してみましょう。<br />
<br />
なお、もしファビコンをルートフォルダに設置したくない場合は、最後の項目で調整ができます。(ルートでいい場合はに特に設定する場合は必要ありません。) <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlo8JOKlVQYOkmSmp68tiJ2Z07ZEXmkQv5b9Y2cyqDpySNLQeUDfPmHk6QTLyG8eFDQi69cc37eTT5BtfILeB7IuaocQZhJfoeEpdfLz2lZlqlWyqvvtf_z03cvGKRNXzpkwKFqBAXuAfg/s1600/Favicon+Generator+for+all+platforms++iOS++Android++PC+Mac...%25282%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="72" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlo8JOKlVQYOkmSmp68tiJ2Z07ZEXmkQv5b9Y2cyqDpySNLQeUDfPmHk6QTLyG8eFDQi69cc37eTT5BtfILeB7IuaocQZhJfoeEpdfLz2lZlqlWyqvvtf_z03cvGKRNXzpkwKFqBAXuAfg/s400/Favicon+Generator+for+all+platforms++iOS++Android++PC+Mac...%25282%2529.png" width="400" /></a></div>
<br />
<br />
<b><span style="font-size: large;">3.ファビコンの作成</span></b><br />
<br />
さぁ、それではファビコンを作成しましょう。<br />
一番下にある以下のボタンをクリックすることで実行できます。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhN5dnRjXzy6HeyAhyphenhyphendZLrXkXxPs4qHPEOJS4HBtjRj04m6AangZpsddoEI1sE3s4iuEFQ8CPwZ2vACdkqGNJScSfR_ogagP2ANwM3V0vpmzmVYmSOIxg6JQvO3wUKtxErqNTRncFbjqA82/s1600/Favicon+Generator+for+all+platforms++iOS++Android++PC+Mac...%25283%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="51" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhN5dnRjXzy6HeyAhyphenhyphendZLrXkXxPs4qHPEOJS4HBtjRj04m6AangZpsddoEI1sE3s4iuEFQ8CPwZ2vACdkqGNJScSfR_ogagP2ANwM3V0vpmzmVYmSOIxg6JQvO3wUKtxErqNTRncFbjqA82/s320/Favicon+Generator+for+all+platforms++iOS++Android++PC+Mac...%25283%2529.png" width="320" /></a></div>
<br />
<span style="font-size: large;"><b>4.ファビコンのダウンロードと設置</b></span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4uSYtL7Cd7itCQK_VHnaiIkuFE7eFwfWPoMk0-uuTVI5BId5rXD7SHquc5O8OF-hTlfi59oK6VOIxLLUE7slCpjXtZno0Uyd3jWsSznk3kmuEd0XblxmZHamVrZn2KysTDf-Yh20Sl4Re/s1600/Your+generated+favicon.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="110" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4uSYtL7Cd7itCQK_VHnaiIkuFE7eFwfWPoMk0-uuTVI5BId5rXD7SHquc5O8OF-hTlfi59oK6VOIxLLUE7slCpjXtZno0Uyd3jWsSznk3kmuEd0XblxmZHamVrZn2KysTDf-Yh20Sl4Re/s400/Your+generated+favicon.png" width="400" /></a></div>
<br />
まず「Download your package.」の横にある「Favicon package」ボタンをクリックするとダウンロードが始まりますので適当な場所に保存してください。<br />
そして、保存した zip ファイルの中にあるファイル全てをサイトのルートフォルダへ展開します。<br />
(つまり、http://example.com/favicon.ico にアクセスできるようになればOKです)<br />
<br />
次に2個めの赤枠内の HTML コードを <head>〜</head>内に書き込みましょう。<br />
これで設定は完了です。 <br />
<br />
<b><span style="font-size: large;">5.テスト</span></b><br />
<br />
もしきちんと設置されたかをテストしたい場合は<a href="http://realfavicongenerator.net/favicon_checker#.WFgNvGdUthE" target="_blank">チェックコンテンツ</a>も提供されていますので使ってみることをおすすめします。<br />
<br />
<br />
なお、元になるファビコン画像を作りたいときは font-awesome で画像が作成できる <a href="http://fa2png.io/" target="_blank">fa2png</a>が便利です。 <br />
<br />
今回は以上です。<br />
おつかれさまでした。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqcCXDJTGDl_Ipe7jhhT-hVknvgaD4VpIAys3-JnotAt_23wz2QSQsPcI7kFbTyQx3vXG-NQBdWGvwx82xmNGQ4qDxcLGh43VHgaeNS8xRNX02KFyl7B-cNDEB3sxjl25Au2fGJh-we4JI/s1600/fasdfsd.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqcCXDJTGDl_Ipe7jhhT-hVknvgaD4VpIAys3-JnotAt_23wz2QSQsPcI7kFbTyQx3vXG-NQBdWGvwx82xmNGQ4qDxcLGh43VHgaeNS8xRNX02KFyl7B-cNDEB3sxjl25Au2fGJh-we4JI/s320/fasdfsd.png" width="258" /></a></div>
Anonymoushttp://www.blogger.com/profile/15645657529148406101noreply@blogger.com0tag:blogger.com,1999:blog-6545450414259005128.post-20700425725115429142016-12-08T05:09:00.000+09:002016-12-08T05:09:48.072+09:00Laravel で全 view からログイン中のユーザー情報を取得するLaravel を利用して開発をしていると、まだまだ全ての機能を使いきれていないことに気付かされることがあります。<br />
ということで今回は <b>ViewComposer</b> を使って、どのビューからでもログイン中のユーザーにアクセスできるようにしてみたいと思います。<br />
<br />
<i>【実行環境】Laravel 5.3</i><br />
<br />
<br />
手順は以下の3つです。<br />
<ol>
<li>ViewComposer を作る</li>
<li>ServiceProvider を作る</li>
<li>ServiceProvider を登録する</li>
</ol>
<br />
ではひとつひとつ見ていきましょう。<br />
<br />
<span style="font-size: large;"><b>1. ViewComposer </b></span><span style="font-size: large;"><b>を作る</b></span><br />
<br />
まず ViewComposer の作成です。<br />
デフォルトでは専用のフォルダは用意されていませんので<span style="background-color: #cccccc;"> app/Http/ViewComposers </span>というフォルダを新たに作成しましょう。<br />
そして、その中に AuthViewComposer.php というファイルを作成&以下のコードを保存します。<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> <?php namespace App\Http\ViewComposers;
use Illuminate\View\View;
class AuthViewComposer
{
protected $user;
public function __construct()
{
$this->user = \Auth::user();
}
public function compose(View $view)
{
$view->with([
'user' => $this->user
]);
}
}
</code></pre>
<br />
<br />
<span style="font-size: large;"><b>2.ServiceProvider を作る</b></span><br />
<br />
次に専用の ServiceProvider を作ります。<br />
<span style="background-color: #cccccc;">app/Providers/ViewComposerServiceProvider.php </span>を作成&以下のコードを保存してください。<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> <?php namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class ViewComposerServiceProvider extends ServiceProvider
{
public function boot()
{
\View::composers([
\App\Http\ViewComposers\AuthViewComposer::class => 'layouts.*'
]);
}
}
</code></pre>
<span style="color: #990000;">※ ちなみに layouts.* の部分ではどの view に適用するかを設定することができます。</span><br />
<br />
<br />
<span style="font-size: large;"><b>3.ServiceProvider を登録する</b></span><br />
<br />
最後は先ほど作った ViewComposerServiceProvider を<span style="background-color: #cccccc;"> config/app.php </span>へ登録します。<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> 'providers' => [
App\Providers\ViewComposerServiceProvider::class,
],
</code></pre>
<br />
さあ、以上で設定は完了です。好きな view の中で<span style="background-color: #cccccc;"> {{ $user->email }} </span>という風にユーザー情報にアクセスしてみましょう。<br />
なお、念のために、以下のコマンドを実行しておくといいかもしれません。<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> composer dumpautoload -o
</code></pre>
<br />
今回は以上です。<br />
お疲れ様でした。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzpp-VsPGUy2ayi1GmCWVV-eBLUZAMhU39uaVsHw6IFE-Jsz3ZUsdUnWV0d3xa-ubuDoTWuZRQiJA1aLLOPk1d_6GSW3Ioge9kcMuy1n0dpNi_-Ddq4s3F5jpec_dLLL5tH08Xb8UEUE9G/s1600/bye.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzpp-VsPGUy2ayi1GmCWVV-eBLUZAMhU39uaVsHw6IFE-Jsz3ZUsdUnWV0d3xa-ubuDoTWuZRQiJA1aLLOPk1d_6GSW3Ioge9kcMuy1n0dpNi_-Ddq4s3F5jpec_dLLL5tH08Xb8UEUE9G/s1600/bye.png" /></a></div>
<br />
<br />Anonymoushttp://www.blogger.com/profile/15645657529148406101noreply@blogger.com0tag:blogger.com,1999:blog-6545450414259005128.post-88106735368621789722016-11-10T18:51:00.000+09:002016-11-11T02:28:40.514+09:00Wikipediaを使って関連キーワード抽出プログラムを作ってみる<span style="font-size: x-large;"><b>関連キーワードが必要になった </b></span><br />
<br />
現在取り組んでいるプロジェクトの中で、キーワードを入力すると関連するキーワードを<br />
<br />
<b>「このキーワードもおすすめですよ」</b><br />
<br />
という具合で表示する機能が必要になりました。<br />
<br />
はじめはGoolgeのSuggestを利用すればいいかなと安易に考えていたのですが、この方法では関連するキーワードではなく、追加キーワードの提案という形になってしまいます。<br />
<br />
実際の例をご覧ください ⇛ <a href="https://www.google.com/complete/search?q=%E6%98%8E%E7%9F%B3%E5%AE%B6%E3%81%95%E3%82%93%E3%81%BE&hl=en&output=toolbar" target="_blank">「明石家さんま」をGoogle Suggestで検索</a><br />
<br />
そうではなく、結果としては「明石家さんま」で検索すると「ビートたけし」や「タモリ」などといった関連するキーワードを取得したかったのでGoogle Suggest の利用は見送ることにしました。<br />
(また、Googleに限らずAPIなどの提供は廃止されるリスクが常につきまとうという理由もありました。)<br />
<br />
<b><span style="font-size: x-large;">おもしろいアプローチを見つける</span></b><br />
<br />
そこで、他の方法はないかとネットを探っているとひとつおもしろいアプローチをしている人がいました。それが以下のページです。<br />
<br />
<a href="http://imagination-i.net/2014/01/06/yahoowebapitwitterapi2%E3%81%A4%E3%81%AEapi%E3%82%92%E7%B5%84%E3%81%BF%E5%90%88%E3%82%8F%E3%81%9B%E3%81%A6%E9%96%A2%E9%80%A3%E3%82%AD%E3%83%BC%E3%83%AF%E3%83%BC%E3%83%89%E6%8A%BD%E5%87%BA%E3%83%84/" target="_blank">[Yahoo!WebAPI+TwitterAPI]2つのAPIを組み合わせて関連キーワード抽出ツールを作ってみる</a><br />
<br />
※ブログ記事、カッコ良かったのでオマージュさせていただきました。m_ _m<br />
<br />
<br />
このページが提案している方法は以下になります。<br />
<br />
1.まず Twitter API を使って検索したいキーワードのツイートを取得<br />
2.Yahoo API のキーフレーズ抽出を使ってそのツイートから共通するキーワードを取得する<br />
3.頻出する言葉が関連キーワード<br />
<br />
つまり、検索するキーワードと一緒に使われている言葉を抽出するというアプローチです。<br />
<br />
<b><span style="font-size: x-large;">早速やってみた、、、しかし!</span></b><br />
<br />
なるほど。<br />
賢い人がいるものだなと感心し、実際に私もこのアプローチを試してみました。<br />
<br />
・・・が!<br />
結果はうまくいきませんでした。<br />
<br />
なぜなら、現在Twitter に投稿されるものは無差別投稿しているものも多く、全く関連しないキーワードばかりが抽出されてしまったからです。<br />
<br />
しかし、一緒に使われている言葉を抽出するというアプローチ自体はとても良い方法なのでなんとかTwitter以外の方法で考えてみることにしました。<br />
<br />
YoutubeやHatena...<br />
どれも納得できるような結果にはなりませんでした。<br />
<br />
加えて、やはりAPIはそのうちにサービスが終了してしまうリスクも心にひっかかりこれら方法も断念しました。<br />
<br />
<span style="font-size: x-large;"><b>そうだ wikipedia を使おう</b></span><br />
<br />
そして、最終的に考えだしたのが Wikipedia を利用する方法でした。<br />
流れとしては以下になります。<br />
<br />
1.検索キーワードのことが書かれたwikipedia のページを読み込む<br />
2.共通するキーワードを抽出(サイト内リンクのテキストを正規表現を使って取得)<br />
3.集計して数が多いものを関連キーワードとする<br />
<br />
この方法だと、APIが終了することはないですし読み込むページも1ページのみでいいのでレスポンスも早くすることができます。<br />
<br />
さらに、関連語の抽出具合もより精度が上がったように思います。<br />
以下は「明石家さんま」で検索した例です。<br />
<ul>
<li>
FNS27時間テレビ</li>
<li>ビートたけし</li>
<li>FNSの日</li>
<li>タモリ</li>
<li>島田紳助</li>
<li>SMAP</li>
<li>さんま・中居の今夜も眠れない</li>
<li>フジテレビジョン </li>
<li>笑福亭鶴瓶</li>
<li>所ジョージ </li>
</ul>
※ちなみに以下のようなキーワード(リンク)は必要ないのでフィルターをかけて抽出しないようにしました。<br />
<br />
1.Template: や Help: など wikipedia の特殊なリンク<br />
2.年月日のみのリンク<br />
<br />
ということで、このプログラムをクラス化しGitHubで公開していますので、実際の<a href="https://github.com/SUKOHI/RelatedWord" target="_blank">ソース</a>はそちらをご覧ください。<br />
<br />
※ちなみに上記プログラムではHTTPアクセスには<a href="https://github.com/guzzle/guzzle" target="_blank">Guzzleのバージョン6</a>を利用しています。composerを利用してインストールする方法が楽かと思いますが、もしGuzzleを使いたくない人は file_get_contents() に書き換えて利用してみてください。<br />
<br />
<a href="http://demo-laravel52.capilano-fw.com/related_words?target_locale=ja" target="_blank">デモを見る</a> <br />
<br />
<br />
以上、Wikipediaを使って関連キーワードを抽出する方法でした。<br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqcCXDJTGDl_Ipe7jhhT-hVknvgaD4VpIAys3-JnotAt_23wz2QSQsPcI7kFbTyQx3vXG-NQBdWGvwx82xmNGQ4qDxcLGh43VHgaeNS8xRNX02KFyl7B-cNDEB3sxjl25Au2fGJh-we4JI/s1600/fasdfsd.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqcCXDJTGDl_Ipe7jhhT-hVknvgaD4VpIAys3-JnotAt_23wz2QSQsPcI7kFbTyQx3vXG-NQBdWGvwx82xmNGQ4qDxcLGh43VHgaeNS8xRNX02KFyl7B-cNDEB3sxjl25Au2fGJh-we4JI/s320/fasdfsd.png" width="258" /></a></div>
<br />Anonymoushttp://www.blogger.com/profile/15645657529148406101noreply@blogger.com0tag:blogger.com,1999:blog-6545450414259005128.post-61965160115280175492016-11-01T18:40:00.000+09:002016-11-01T18:40:41.542+09:00【Stripe】PHPで課金するための基本設定課金サービスを簡単に組み込めるサービスとして、審査も必要がなくとても手軽な「<a href="https://stripe.com/jp" target="_blank">stripe</a>」に注目しています。<br />
この記事を投稿する少し前まではトップページにはベータ版だとの記述がありましたが現在はそれもなくなり、本格的に日本でもリリースがされたようです。<br />
<br />
そこで、今回は stripe で月額課金を利用するために必要な基本的な設定とアクセスキーの取得法を備忘録として投稿したいと思います。<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://upload.wikimedia.org/wikipedia/commons/thumb/2/2a/Stripe_logo,_revised_2014.png/1024px-Stripe_logo,_revised_2014.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="148" src="https://upload.wikimedia.org/wikipedia/commons/thumb/2/2a/Stripe_logo,_revised_2014.png/1024px-Stripe_logo,_revised_2014.png" width="320" /></a></div>
<br />
<b>1.まずはアカウントの作成</b><br />
<br />
以下のURLからアカウントを作成しましょう<br />
<br />
<a href="https://dashboard.stripe.com/register">https://dashboard.stripe.com/register</a><br />
<br />
<br />
<b>2.月額課金するプランを作成</b><br />
<br />
メニューリンクの中から「Plans」をクリックし、その後ページ右上にある「New」をクリックします。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiy_DQ2aCa6wB6SZS7umBcO53Uvg-d48M7MllktuzEA0c7EDYzy6a2Iceo-OZGBOVZuK1MFNEbLAoKe2XgFwJLU6nDawXxd0SICzgOxyg_czOomO3jFEUYLj8AIELf_eZiQiYAUcMDbdqMb/s1600/+Test++Plans.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiy_DQ2aCa6wB6SZS7umBcO53Uvg-d48M7MllktuzEA0c7EDYzy6a2Iceo-OZGBOVZuK1MFNEbLAoKe2XgFwJLU6nDawXxd0SICzgOxyg_czOomO3jFEUYLj8AIELf_eZiQiYAUcMDbdqMb/s640/+Test++Plans.png" width="640" /></a></div>
<br />
以下のようなプラン作成フォームが表示されます。<br />
最低限必要な項目は以下になります。 <br />
<br />
<ol>
<li>ID (←プログラム上で利用する識別IDです。)</li>
<li>Name (←課金名。見てわかりやすい名前をつけましょう)</li>
<li>Currency (←通貨。JPYが日本円です。おそらくデフォルトです)</li>
<li>Amount (←課金額。いくら課金するか?です)</li>
<li>Interval (課金する間隔) </li>
</ol>
入力したら、「create plan」 をクリックして保存します。 <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5cbxxx1zquV7z24jobd6ff8WUmesAhhdEq9x6WZIrKnmYENE06XKDeknxMSlld-4DHcotHkTRpxu5M_OIavPtqinu06RlKezId1LJbwyJ9qNKhqYiQgMYYWSG5PpWPuc8NdImwJBDD47m/s1600/+Test++Plans%25281%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5cbxxx1zquV7z24jobd6ff8WUmesAhhdEq9x6WZIrKnmYENE06XKDeknxMSlld-4DHcotHkTRpxu5M_OIavPtqinu06RlKezId1LJbwyJ9qNKhqYiQgMYYWSG5PpWPuc8NdImwJBDD47m/s400/+Test++Plans%25281%2529.png" width="325" /></a></div>
<br />
<b>3.アクセスキーを取得する</b><br />
<br />
ページ右上にある「Your Account」の中にある「Account Settings」をクリック。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTel0xxcca41Q6bS1HXr8_sbHIeD7GNLOhgUxl8IrvtGkr-eDO8F-eZzFSY-bn-Jr4nkrVVI4qI6RShNSr4uTx1Pwec9NEAZPVj6dj8o6IHvjGXE5jryYWoYUIQfVjIroH-a44ueSVmw8g/s1600/+Test++Plans%25282%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTel0xxcca41Q6bS1HXr8_sbHIeD7GNLOhgUxl8IrvtGkr-eDO8F-eZzFSY-bn-Jr4nkrVVI4qI6RShNSr4uTx1Pwec9NEAZPVj6dj8o6IHvjGXE5jryYWoYUIQfVjIroH-a44ueSVmw8g/s320/+Test++Plans%25282%2529.png" width="276" /></a></div>
<br />
現れたダイアログの中にある「API Keys」をクリックすると以下のようにアクセスキーが表示されます。<br />
<br />
上がテスト用のキー。<br />
下が本番用のキーになります。 <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhz3KpnscnpEp2GwJi1eY-NgSPBlbg5PTLFZVPFMoNcBRnJs-PdYXzTGGZsiJ1WHWyayhNAYtjt8dlJUUlAQHH04aYLEWVlXQqX647RisP-SaICV6D1uQ27pGaIrngu0yC7duTbVd3LNMNR/s1600/API+Key+Settings.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="368" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhz3KpnscnpEp2GwJi1eY-NgSPBlbg5PTLFZVPFMoNcBRnJs-PdYXzTGGZsiJ1WHWyayhNAYtjt8dlJUUlAQHH04aYLEWVlXQqX647RisP-SaICV6D1uQ27pGaIrngu0yC7duTbVd3LNMNR/s640/API+Key+Settings.png" width="640" /></a></div>
<br />
<br />
以上がAPIに必要な設定&キーの取得になります。<br />
<br />
実際にPHPに組み込むためにはライブラリが用意されていますのでそちらをつかうといいでしょう。<br />
<br />
<a href="https://stripe.com/docs/libraries#php-library">https://stripe.com/docs/libraries#php-library</a><br />
<a href="https://github.com/stripe/stripe-php">https://github.com/stripe/stripe-php</a><br />
<br />
Laravelを使っている場合はCashierというパッケージが本家Laravelによって提供されていますのでこちらを使う方がいいでしょう。<br />
<br />
<a href="https://laravel.com/docs/5.3/billing#stripe-configuration">https://laravel.com/docs/5.3/billing#stripe-configuration</a><br />
<br />
<br />
以上になります。<br />
<br />
※それにしてもドンドン便利なサービスが増えてきていろいろな事が簡単にできるようになってきています。それだけ可能性が広がっているということなので今後も楽しみですね。^^<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCIGph_K9gULbIZRPyFPKI5rU-tIwwmggKRtCNittVnTyPoKA6Kq9XDP9B2-joOBaMVYishSfi-dNBrGWqH0a1YNvsNzTQBfr7hTsU6WjgRlxAb93sHw4j8E-vtLbxY3kYZDzPYqSqZkym/s1600/9.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="190" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCIGph_K9gULbIZRPyFPKI5rU-tIwwmggKRtCNittVnTyPoKA6Kq9XDP9B2-joOBaMVYishSfi-dNBrGWqH0a1YNvsNzTQBfr7hTsU6WjgRlxAb93sHw4j8E-vtLbxY3kYZDzPYqSqZkym/s320/9.png" width="320" /></a></div>
<br />Anonymoushttp://www.blogger.com/profile/15645657529148406101noreply@blogger.com0tag:blogger.com,1999:blog-6545450414259005128.post-41339964019822959022016-09-10T04:43:00.000+09:002016-09-10T04:43:21.094+09:00PHPで国コードとその他情報を取得するクラスを公開しました最近ウェブサイトの開発のご相談を頂く際にグローバルな視点で物事を考えているクライアント様方が増えてきたように思います。<br />
<br />
その中で度々懸案事項となっていたことは、国コードを管理できるパッケージがあまり見つからないということでした。(あるのはありましたが、残念ながら日本語/英語の国名、2桁コード、3桁コード、数字コードが揃っているものではありませんでした) <br />
<br />
そこで!<br />
今後のことを考え独自に <a href="https://www.iso.org/obp/ui/#search/code/" target="_blank">ISO 3166-1</a> をベースとしたパッケージを作成し、公開しました。<br />
以下よりダウンロード or Composer によるインストールが可能です。 <br />
<br />
<a href="https://github.com/SUKOHI/CountryCode" target="_blank">GitHub | SUKOHI/CountryCode</a><br />
<br />
今回はフレームワークのパッケージではなく、純粋なPHPパッケージとしての公開ですので、いろんな環境でご利用いただけると思います。<br />
みなさんのお役にたてたら嬉しいです(^^)<br />
<br />
<br />
ちなみに、取得できるデータの例としては以下のような感じです。<br />
<br />
【日本の例】 <br />
<br />
国コード(2桁) ・・・ JP<br />
国コード(3桁) ・・・ JPN<br />
数字コード ・・・ 392<br />
国名 ・・・ Japan(英語)、日本(日本語)<br />
<br />
実際の使い方は<a href="https://github.com/SUKOHI/CountryCode" target="_blank">GitHub</a>の方でご覧ください。<br />
<br />
※なお、もし英語、日本語以外で国名を翻訳できる方は「<code>assets/csv/country_codes.csv</code>」にデータを追加するだけで新しい言語に対応ができます。よかったら GitHub にて Pull Request していただけるとなお嬉しいです! m_ _m<br />
<br />ではでは〜。<br />
(最近ブログ記事をさぼってしまっているので時間を見つけて更新しなければ!)<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUjIXpewKXoXnHSlNTb2V47vNa0RJfIFBAxvZ38I8zrRsUga0dKMLJrdU9dOBwwYHXpcI3gHo6ymb9p8Xajl7pSrBgEFyf1FvvUN08KIvHyYExoHzwBfOMAamnFnELuDsWIidY22ijgTeK/s1600/2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUjIXpewKXoXnHSlNTb2V47vNa0RJfIFBAxvZ38I8zrRsUga0dKMLJrdU9dOBwwYHXpcI3gHo6ymb9p8Xajl7pSrBgEFyf1FvvUN08KIvHyYExoHzwBfOMAamnFnELuDsWIidY22ijgTeK/s1600/2.png" /></a></div>
Anonymoushttp://www.blogger.com/profile/15645657529148406101noreply@blogger.com1tag:blogger.com,1999:blog-6545450414259005128.post-50378273548759558952016-06-22T22:24:00.000+09:002016-06-22T22:24:55.952+09:00FlysystemをLaravelで使う開発サイトの規模が大きくなってきたり、よりセキュアなサーバー環境を整えるためにサーバーを「ウェブサーバー」と「データサーバー」で物理的に分割する場合があると思います。<br />
<br />
そして、PHPでファイルをリモートで読み込み/書き込みをするためには「Flysystem」という有名なパッケージを利用すればとても簡単にできるのですが、今回はこの「Flysystem」をLaravel(5.2)で使う方法をお届けしたいと思います。<br />
<br />
※ちなみに今回はSFTPを使ってリモートサーバーとの連携をしますが、Flysystemは他にも<code>「</code><code><code>aws</code>」や「Azure」、その他には「DropBox」との連携までサポートしています。</code><br />
<br />
<br />
<code>【環境】</code><br />
<br />
<code>Laravel 5.2</code><br />
<code>SFTPで自分のVPSへSFTPを使って接続</code><br />
<br />
<code><b>【インストール】 </b></code><br />
<br />
まずは composer でパッケージのインストールです。<br />
ここではLaravelと統合されているものをインストールします。<br />
(ちなみに<a href="https://github.com/GrahamCampbell/Laravel-Flysystem" target="_blank">GitHub</a>はこちら)<br />
<blockquote class="tr_bq">
<pre>composer require graham-campbell/flysystem</pre>
</blockquote>
次に私の場合はSFTPでの接続ですので、Flysystemのサブパッケージをインストールします。<br />
<blockquote class="tr_bq">
<code>league/flysystem-sftp:^1.0</code> </blockquote>
はい。これでインストールは完了です。<br />
<br />
<br />
<b>【準備】</b><br />
<br />
いつものように ServiceProvider と aliases を config/app.php に設置しましょう。<br />
<br />
(ServiceProvider)<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> GrahamCampbell\Flysystem\FlysystemServiceProvider::class
</code></pre>
<br />
<br />
(Aliases)<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> 'Flysystem' => GrahamCampbell\Flysystem\Facades\Flysystem::class
</code></pre>
<br />
<br />
そして、以下のコマンドで専用の設定ファイルを publish します。<br />
<blockquote class="tr_bq">
<pre>php artisan vendor:publish</pre>
</blockquote>
実行すると、configフォルダの中に「flysystem.php」というファイルが作成されていると思いますのでこの中で接続情報を保存します。<br />
<br />
※もしコマンドを実行しても flysystem.php が作成されない場合は、以下のコマンドを実行してからもう一度トライしてみてください。<br />
<ul>
<li>composer dumpautoload -o</li>
<li>php artisan config:cache</li>
</ul>
<br />
では、実際の中身です。<br />
<br />
今回はSFTPでの接続なので「SFTP」のエリアを探して、必要な情報を入力すればOKです。<br />
変更する場所としては、<br />
<br />
<ul>
<li>host(IPアドレスなど)</li>
<li>port(変えている場合)</li>
<li>username</li>
<li>password</li>
<li>privateKey(プライベート・キーファイルのパス)</li>
<li>root(リモートサーバーの保存したいフォルダパス) </li>
</ul>
<br />
あたりになるかと思います。<br />
<br />
はい、これで設定は完了です。<br />
<br />
<br />
<b>【使い方】</b><br />
<u><br /></u>
<u>(基本的な使い方)</u><br />
<br />
使い方はとても直感的でシンプルです。<br />
次の例は、「test.txt」というファイルを作り、さらにそこに「bar」という文字列を書き込む手準になります。<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> \Flysystem::connection('sftp')->put('test.txt', 'bar');
</code></pre>
<br />
たったこれだけです。<br />
では逆にその保存した内容を読み込んでみましょう。<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> echo \Flysystem::connection('sftp')->read('test.txt');
</code></pre>
<br />
これで「bar」が表示されます。<br />
<br />
<br />
<u>(フォルダを指定して保存)</u><br />
<br />
もし、フォルダを指定して保存したい場合はこのようになります。<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> \Flysystem::connection('sftp')->put('test_dir/test.txt', 'bar');
</code></pre>
<br />
この場合は、test_dir/test.txt にファイルが保存されます。<br />
<br />
<br />
<u>(画像を保存)</u><br />
<br />
これもテキストファイルなどとやり方はほぼ同じで、<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> $content = file_get_contents(public_path('images/my_photo.jpg'));
\Flysystem::connection('sftp')->put('me.jpg', $content);
</code></pre>
<br />
とやればOK。<br />
とてもシンプルです。<br />
<br />
ちなみに、Laravelを使って保存した画像をサーバーから呼び出して表示するには以下のようにすればいいでしょう。<br />
<br />
(コントローラ)<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> public function flysystem_image() {
$image_contents = \Flysystem::connection('sftp')->read('me.jpg');
return response($image_contents, 200)->header('Content-Type', 'image/jpeg');
}
</code></pre>
<br />
以上、Laravel と Flysystem を使ったサーバーの連携方法でした。<br />
ではでは!<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhA6azNYCbeTb3HIU-4DkrDiKtQkpiM_Q_JCGW4l-UNSpUmDZZLGsLCbpPaQWCl9pOZ0DNPZ_xETWAYpeQm4YcNBtvxscM9WahPvOG9GzFp9aRUotrK4dLxiJiFFj2j7ln-VuMkyqdGAN1m/s1600/2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhA6azNYCbeTb3HIU-4DkrDiKtQkpiM_Q_JCGW4l-UNSpUmDZZLGsLCbpPaQWCl9pOZ0DNPZ_xETWAYpeQm4YcNBtvxscM9WahPvOG9GzFp9aRUotrK4dLxiJiFFj2j7ln-VuMkyqdGAN1m/s1600/2.png" /></a></div>
<br />Anonymoushttp://www.blogger.com/profile/15645657529148406101noreply@blogger.com0tag:blogger.com,1999:blog-6545450414259005128.post-43673017998350382982016-06-09T05:46:00.000+09:002017-06-28T17:19:24.644+09:00受信したメールをLaravelで受け取る受信メールをPHPプログラムへ送り、メールを解析して送信元のメールアドレスや本文を取得してDBに保存ということをLaravel(5.2)をからめてやるにはどうすればいいかをメールサーバーをたてるところからやってみたので備忘録としてお届けします。<br />
(はっきり言って作業内容は多かったです、、^^;)<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRLGfmcwVV6Bpy8DdkLWFga0OoQpilx_idnBzEMbribzRrIr_0JYwyJZI9ytnTkTx5SRXzTZ747mzEHyfGdOoigM8NeyZRiB9oRuXbaG45rwtF-WyIm0hBn8P0KLFnZOGcZlrrmqlO1vfn/s1600/mailwoman-1187916_640.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="213" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRLGfmcwVV6Bpy8DdkLWFga0OoQpilx_idnBzEMbribzRrIr_0JYwyJZI9ytnTkTx5SRXzTZ747mzEHyfGdOoigM8NeyZRiB9oRuXbaG45rwtF-WyIm0hBn8P0KLFnZOGcZlrrmqlO1vfn/s320/mailwoman-1187916_640.jpg" width="320" /></a></div>
<br />
<br />
<b>【作業環境】</b><br />
<br />
CentOS 6.7<br />
<br />
<br />
<b>【作業の手順】</b><br />
<ol>
<li>Postfix をインストール/設定</li>
<li>ドメインのDNS設定</li>
<li>Pecl(Pear)本体をインストール</li>
<li>Pecl の mailparse をインストール、extensionの読み込み</li>
<li>Laravelパッケージ「php-mime-mail-parser」をインストール</li>
<li>LaravelにCommandを追加</li>
</ol>
<br />
<b>【実際の作業】</b><br />
<br />
では、ここからは実際の作業になりますが、全部書くと確実に長くなってしまいますので途中は参考にしたサイトを紹介しながらすすめていきます。<br />
<br />
<b>1. Postfix をインストール/設定</b><br />
<br />
私の場合はCentOSなので<br />
<pre style="background-color: #2b2b2b; color: #a9b7c6; font-family: 'Source Code Pro'; font-size: 10.5pt;"><span style="background-color: #232525; color: #9876aa; font-style: italic;">sudo yum install postfix</span></pre>
でインストールしましたが、環境によって変更してください。<br />
また、設定の方法は以下のページがとてもわかりやすいと思いますのでぜひ参考にしてみてください。<br />
<br />
<ul>
<li><a href="http://oxynotes.com/?p=4646" target="_blank">Postfixによる、セキュリティに配慮したメールサーバの構築方法</a></li>
<li><a href="http://plusblog.jp/8842/" target="_blank">さくらVPSのバーチャルドメインでメール送受信</a></li>
</ul>
<br />
また、この記事の中にも紹介されていますが、設定が完了したら以下のサイトでセキュアチェックができます。<br />
<br />
<ul>
<li><a href="http://www.rbl.jp/svcheck.php" target="_blank">第三者中継チェック RBL.JP</a></li>
</ul>
<br />
そして「<code>/etc/aliases</code>」をエディタで開き、以下のような振り分け設定を追加しましょう。<br />
<br />
<span style="background-color: #d0e0e3;">mail: "| /usr/bin/php /path/to/your/public/folder/example.com/artisan mail:parse"</span><br />
<br />
意味としては<br />
<br />
<ul>
<li>mail・・・はユーザー名。つまり、mail@example.comでメール受信した場合の設定ですよという意味です。</li>
<li>/usr/bin/php(以下略)・・・PHPを使ってLaravelのartisanを実行</li>
<li>mail:parse・・・実行するコマンド(「6.LaravelにCommandを追加」で作る独自コマンドです)</li>
</ul>
<br />
完了したら、<code> <span style="background-color: #d0e0e3;">sudo postalias /etc/aliases</span> でエイリアスをアップデートします。</code><br />
<code>そして、最後に </code><code><code><span style="background-color: #d0e0e3;">sudo service postfix reload</span> でpostfixをリロードで完了です。</code> </code><br />
<br />
<br />
<b>2.ドメインのDNS設定</b><br />
<br />
これも人によって記述が違うと思いますが私の設定は以下のようにしています。<br />
<pre style="background-color: #2b2b2b; color: #a9b7c6; font-family: 'Source Code Pro'; font-size: 10.5pt;"><span style="background-color: #232525; color: #9876aa; font-style: italic;">mx mail</span><span style="background-color: #232525;">.</span><span style="background-color: #232525; color: #9876aa; font-style: italic;">example</span><span style="background-color: #232525;">.</span><span style="background-color: #232525; color: #9876aa; font-style: italic;">com</span><span style="background-color: #232525;">. </span><span style="background-color: #232525; color: #6897bb;">10</span>
<span style="background-color: #232525; color: #9876aa; font-style: italic;">a </span><span style="background-color: #232525;">* </span><span style="background-color: #232525; color: #6897bb;">01.234.567.890</span>
<span style="background-color: #232525; color: #9876aa; font-style: italic;">txt </span><span style="background-color: #232525;">@ </span><span style="background-color: #232525; color: #9876aa; font-style: italic;">v</span><span style="background-color: #232525;">=</span><span style="background-color: #232525; color: #9876aa; font-style: italic;">spf1 </span><span style="background-color: #232525;">a:</span><span style="background-color: #232525; color: #9876aa; font-style: italic;">example</span><span style="background-color: #232525;">.</span><span style="background-color: #232525; color: #9876aa; font-style: italic;">com </span><span style="background-color: #232525;">~</span><span style="background-color: #232525; color: #9876aa; font-style: italic;">all</span></pre>
2行目はIPアドレスです。<br />
※ちなみにこれはサーバー設定ではなく、取得したドメインの管理サイトで設定をします。<br />
<br />
<br />
<b>3.Pecl(Pear)本体をインストール</b><br />
<pre style="background-color: #2b2b2b; color: #a9b7c6; font-family: 'Source Code Pro'; font-size: 10.5pt;"><span style="background-color: #232525; color: #9876aa; font-style: italic;">sudo yum install php</span><span style="background-color: #232525;">-</span><span style="background-color: #232525; color: #9876aa; font-style: italic;">pear</span><span style="background-color: #232525; color: #9876aa; font-style: italic;"></span></pre>
ここは戸惑いました。<br />
Peclをインストールするにはpearをインストールするんですね。<br />
(その昔、mecabをインストールしたことあるのに...)<br />
<br />
なお、リポジトリを設定しないとパッケージが見つからないかもしれません。<br />
<br />
<br />
<b>4. Pecl の mailparse をインストール、extensionの読み込み</b><br />
<pre style="background-color: #2b2b2b; color: #a9b7c6; font-family: 'Source Code Pro'; font-size: 10.5pt;"><span style="background-color: #232525; color: #9876aa; font-style: italic;">pecl install mailparse</span></pre>
でメール解析に必要な mailparse をインストールします。<br />
ただ、もしかすると<br />
<blockquote class="tr_bq">
The php-devel package is required for use of this command.</blockquote>
というエラーがでてインストールできないかもしれません。<br />
そのときはエラーの表示にある <span style="background-color: #cccccc;">php-devel</span> をインストールしてからやってみてください。<br />
<br />
では、インストールした mailparse を PHPが利用できるように設定をしましょう。<br />
ファイルを作成する場所は php.ini の「Additional .ini files parsed」でリストに出てくるフォルダです。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgS6_oyez7zcIWGYt6c6Ihc9KBghV8yHwVFm4DiNmr-QjtrOqYfq6h3zzA1UmnvzE_zl8tntkF294aDHAuORf82UwTCCo7SNcZYe5QH6pysDe4or1rHW6E903Dtczlit2dCy8rFq07c8FE_/s1600/phpinfo%2528%2529+2016-06-09+04-47-25.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgS6_oyez7zcIWGYt6c6Ihc9KBghV8yHwVFm4DiNmr-QjtrOqYfq6h3zzA1UmnvzE_zl8tntkF294aDHAuORf82UwTCCo7SNcZYe5QH6pysDe4or1rHW6E903Dtczlit2dCy8rFq07c8FE_/s1600/phpinfo%2528%2529+2016-06-09+04-47-25.png" /></a></div>
<br />
<br />
たとえば、もし「/etc/php5/apache2/conf.d/05-opcache.ini」が表示されているとするなら「/etc/php5/apache2/conf.d」がそのフォルダになります。<br />
<br />
ではここに mailparse.ini というファイルを作成し、以下の内容を保存します。 <br />
<pre style="background-color: #2b2b2b; color: #a9b7c6; font-family: 'Source Code Pro'; font-size: 10.5pt;"><span style="background-color: #232525; color: #9876aa; font-style: italic;">php extension</span><span style="background-color: #232525;">=</span><span style="background-color: #232525; color: #9876aa; font-style: italic;">mailparse</span><span style="background-color: #232525;">.</span><span style="background-color: #232525; color: #9876aa; font-style: italic;">so</span></pre>
はい。<br />
これでmailparseの設定は完了です。<br />
ウェブサーバーを再起動してもう一度 phpinfo を確認すると以下のようにmailparse が表示されているはずです。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4CSBbEfptBn7zgyln0pRbXvG9zVFltaeTtzveQuFRfp0s3fsNAsNApK4Xkz05fyeZdJcV4geBeDBAa8gfgr72hE7qHaZcK28HEG6VQlNOJQ8m1KcvEHbkW2chK8uXM8xVx5onbRj6TYhg/s1600/phpinfo%2528%2529+2016-06-09+04-53-38.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="76" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4CSBbEfptBn7zgyln0pRbXvG9zVFltaeTtzveQuFRfp0s3fsNAsNApK4Xkz05fyeZdJcV4geBeDBAa8gfgr72hE7qHaZcK28HEG6VQlNOJQ8m1KcvEHbkW2chK8uXM8xVx5onbRj6TYhg/s640/phpinfo%2528%2529+2016-06-09+04-53-38.png" width="640" /></a></div>
<br />
<br />
<b>5.Laravelパッケージ「php-mime-mail-parser」をインストール</b><br />
<br />
これはとても簡単です。<br />
composer で一気にインストールできます。 <br />
<pre style="background-color: #2b2b2b; color: #a9b7c6; font-family: 'Source Code Pro'; font-size: 10.5pt;"><span style="background-color: #232525; color: #9876aa; font-style: italic;">composer </span><span style="background-color: #232525; color: #cc7832; font-weight: bold;">require </span><span style="background-color: #232525; color: #9876aa; font-style: italic;">php</span><span style="background-color: #232525;">-</span><span style="background-color: #232525; color: #9876aa; font-style: italic;">mime</span><span style="background-color: #232525;">-</span><span style="background-color: #232525; color: #9876aa; font-style: italic;">mail</span><span style="background-color: #232525;">-</span><span style="background-color: #232525; color: #9876aa; font-style: italic;">parser</span><span style="background-color: #232525;">/</span><span style="background-color: #232525; color: #9876aa; font-style: italic;">php</span><span style="background-color: #232525;">-</span><span style="background-color: #232525; color: #9876aa; font-style: italic;">mime</span><span style="background-color: #232525;">-</span><span style="background-color: #232525; color: #9876aa; font-style: italic;">mail</span><span style="background-color: #232525;">-</span><span style="background-color: #232525; color: #9876aa; font-style: italic;">parser</span></pre>
ちなみに、パッケージがあるなら mailparse は要らないんじゃ?と思った方。<br />
私もそうでした。<br />
でも、実際は mailparse を前提にしたパッケージなのでやはり Pecl他は必要なんです。^^;<br />
<br />
※GitHubのページは<a href="https://github.com/php-mime-mail-parser/php-mime-mail-parser" target="_blank">こちら</a>です。<br />
<br />
<br />
<b>6.LaravelにCommandを追加</b><br />
<br />
やっとここまで来ました。<br />
コマンドの作成/設定方法は<a href="https://laravel.com/docs/5.2/artisan" target="_blank">本家Laravelページ</a>で確認してください。<br />
<br />
コマンドの中身は以下のようになります。<br />
<pre style="background-color: #2b2b2b; color: #a9b7c6; font-family: 'Source Code Pro'; font-size: 10.5pt;"><span style="background-color: #232525; color: #9876aa;">$parser </span><span style="background-color: #232525;">= </span><span style="background-color: #232525; color: #cc7832; font-weight: bold;">new </span><span style="background-color: #232525;">Parser()</span><span style="background-color: #232525; color: #cc7832;">;</span><span style="background-color: #232525; color: #cc7832;">
</span><span style="background-color: #232525; color: #9876aa;">$parser</span><span style="background-color: #232525;">-></span><span style="background-color: #232525; color: #ffc66d;">setStream</span><span style="background-color: #232525;">(fopen(</span><span style="background-color: #232525; color: #6a8759;">'php://stdin'</span><span style="background-color: #232525; color: #cc7832;">, </span><span style="background-color: #232525; color: #6a8759;">'r'</span><span style="background-color: #232525;">))</span><span style="background-color: #232525; color: #cc7832;">;</span></pre>
あとは、以下のような便利なメソッドが備わっているのでこれを使ってメールを思うように加工してください。<br />
<pre style="background-color: #2b2b2b; color: #a9b7c6; font-family: 'Source Code Pro'; font-size: 10.5pt;"><span style="background-color: #232525; color: #9876aa;">$to </span><span style="background-color: #232525;">= </span><span style="background-color: #232525; color: #9876aa;">$parser</span><span style="background-color: #232525;">-></span><span style="background-color: #232525; color: #ffc66d;">getHeader</span><span style="background-color: #232525;">(</span><span style="background-color: #232525; color: #6a8759;">'to'</span><span style="background-color: #232525;">)</span><span style="background-color: #232525; color: #cc7832;">; </span><span style="background-color: #232525; color: grey;">// </span><span style="background-color: #232525; font-family: "takao pゴシック";">送信先</span>
<span style="background-color: #232525; color: #9876aa;">$addressesTo </span><span style="background-color: #232525;">= </span><span style="background-color: #232525; color: #9876aa;">$parser</span><span style="background-color: #232525;">-></span><span style="background-color: #232525; color: #ffc66d;">getAddresses</span><span style="background-color: #232525;">(</span><span style="background-color: #232525; color: #6a8759;">'to'</span><span style="background-color: #232525;">)</span><span style="background-color: #232525; color: #cc7832;">; </span><span style="background-color: #232525; color: grey;">// </span><span style="background-color: #232525; font-family: "takao pゴシック";">送信先(配列)</span>
<span style="background-color: #232525; color: #9876aa;">$from </span><span style="background-color: #232525;">= </span><span style="background-color: #232525; color: #9876aa;">$parser</span><span style="background-color: #232525;">-></span><span style="background-color: #232525; color: #ffc66d;">getHeader</span><span style="background-color: #232525;">(</span><span style="background-color: #232525; color: #6a8759;">'from'</span><span style="background-color: #232525;">)</span><span style="background-color: #232525; color: #cc7832;">; </span><span style="background-color: #232525; color: grey;">// </span><span style="background-color: #232525; font-family: "takao pゴシック";">送信元</span>
<span style="background-color: #232525; color: #9876aa;">$addressesFrom </span><span style="background-color: #232525;">= </span><span style="background-color: #232525; color: #9876aa;">$parser</span><span style="background-color: #232525;">-></span><span style="background-color: #232525; color: #ffc66d;">getAddresses</span><span style="background-color: #232525;">(</span><span style="background-color: #232525; color: #6a8759;">'from'</span><span style="background-color: #232525;">)</span><span style="background-color: #232525; color: #cc7832;">; </span><span style="background-color: #232525; color: grey;">// </span><span style="background-color: #232525; font-family: "takao pゴシック";">送信元(配列)</span>
<span style="background-color: #232525; color: #9876aa;">$subject </span><span style="background-color: #232525;">= </span><span style="background-color: #232525; color: #9876aa;">$parser</span><span style="background-color: #232525;">-></span><span style="background-color: #232525; color: #ffc66d;">getHeader</span><span style="background-color: #232525;">(</span><span style="background-color: #232525; color: #6a8759;">'subject'</span><span style="background-color: #232525;">)</span><span style="background-color: #232525; color: #cc7832;">; </span><span style="background-color: #232525; color: grey;">// </span><span style="background-color: #232525; font-family: "takao pゴシック";">件名</span>
<span style="background-color: #232525; font-family: "takao pゴシック";">
</span><span style="background-color: #232525; color: #9876aa;">$text </span><span style="background-color: #232525;">= </span><span style="background-color: #232525; color: #9876aa;">$parser</span><span style="background-color: #232525;">-></span><span style="background-color: #232525; color: #ffc66d;">getMessageBody</span><span style="background-color: #232525;">(</span><span style="background-color: #232525; color: #6a8759;">'text'</span><span style="background-color: #232525;">)</span><span style="background-color: #232525; color: #cc7832;">; </span><span style="background-color: #232525; color: grey;">// </span><span style="background-color: #232525; font-family: "takao pゴシック";">本文(テキスト)</span>
<span style="background-color: #232525; color: #9876aa;">$html </span><span style="background-color: #232525;">= </span><span style="background-color: #232525; color: #9876aa;">$parser</span><span style="background-color: #232525;">-></span><span style="background-color: #232525; color: #ffc66d;">getMessageBody</span><span style="background-color: #232525;">(</span><span style="background-color: #232525; color: #6a8759;">'html'</span><span style="background-color: #232525;">)</span><span style="background-color: #232525; color: #cc7832;">; </span><span style="background-color: #232525; color: grey;">// </span><span style="background-color: #232525; font-family: "takao pゴシック";">本文(</span><span style="background-color: #232525; color: grey;">HTML</span><span style="background-color: #232525; font-family: "takao pゴシック";">)</span>
<span style="background-color: #232525; color: #9876aa;">$htmlEmbedded </span><span style="background-color: #232525;">= </span><span style="background-color: #232525; color: #9876aa;">$parser</span><span style="background-color: #232525;">-></span><span style="background-color: #232525; color: #ffc66d;">getMessageBody</span><span style="background-color: #232525;">(</span><span style="background-color: #232525; color: #6a8759;">'htmlEmbedded'</span><span style="background-color: #232525;">)</span><span style="background-color: #232525; color: #cc7832;">; </span><span style="background-color: #232525; color: grey;">// </span><span style="background-color: #232525; font-family: "takao pゴシック";">データを含む本文(</span><span style="background-color: #232525; color: grey;">HTML</span><span style="background-color: #232525; font-family: "takao pゴシック";">)</span></pre>
<b>添付ファイル</b><br />
<br />
添付ファイルの扱い方は以下になります。<br />
<br />
(保存)<br />
<pre style="background-color: #2b2b2b; color: #a9b7c6; font-family: 'Source Code Pro'; font-size: 10.5pt;"><span style="background-color: #232525; color: #9876aa;">$parser</span><span style="background-color: #232525;">-></span><span style="background-color: #232525; color: #ffc66d;">saveAttachments</span><span style="background-color: #232525;">(</span><span style="background-color: #232525; color: #6a8759;">'/path/to/save/attachments/'</span><span style="background-color: #232525;">)</span><span style="background-color: #232525; color: #cc7832;">;</span></pre>
<br />
(ループ)<br />
<pre style="background-color: #2b2b2b; color: #a9b7c6; font-family: 'Source Code Pro'; font-size: 10.5pt;"><span style="background-color: #232525; color: #9876aa;">$attachments </span><span style="background-color: #232525;">= </span><span style="background-color: #344134; color: #9876aa;">$parser</span><span style="background-color: #232525;">-></span><span style="background-color: #232525; color: #ffc66d;">getAttachments</span><span style="background-color: #232525;">()</span><span style="background-color: #232525; color: #cc7832;">;</span>
<span style="background-color: #232525; color: #cc7832; font-weight: bold;">if </span><span style="background-color: #232525;">(count(</span><span style="background-color: #232525; color: #9876aa;">$attachments</span><span style="background-color: #232525;">) > </span><span style="background-color: #232525; color: #6897bb;">0</span><span style="background-color: #232525;">) {</span>
<span style="background-color: #232525;"> </span><span style="background-color: #232525; color: #cc7832; font-weight: bold;">foreach </span><span style="background-color: #232525;">(</span><span style="background-color: #232525; color: #9876aa;">$attachments </span><span style="background-color: #232525; color: #cc7832; font-weight: bold;">as </span><span style="background-color: #232525; color: #9876aa;">$attachment</span><span style="background-color: #232525;">) {</span>
<span style="background-color: #232525;"> $filename = </span><span style="background-color: #232525; color: #9876aa;">$attachment</span><span style="background-color: #232525;">-></span><span style="background-color: #232525; color: #ffc66d;">getFilename</span><span style="background-color: #232525;">()</span><span style="background-color: #232525; color: #cc7832;">;</span><span style="background-color: #232525; color: grey;">
</span><span style="background-color: #232525; color: grey;"> </span><span style="background-color: #232525; color: #cc7832; font-weight: bold;">$path = </span><span style="background-color: #232525;"></span><span style="background-color: #232525;"></span><span style="background-color: #232525; color: #6a8759;">'/path/to/save/attachments/'</span><span style="background-color: #232525;"></span><span style="background-color: #232525; color: #9876aa;">. $attachment</span><span style="background-color: #232525;">-></span><span style="background-color: #232525; color: #ffc66d;">getFilename</span><span style="background-color: #232525;">()</span><span style="background-color: #232525; color: #6a8759;"></span><span style="background-color: #232525; color: #cc7832;">;</span><span style="background-color: #232525; color: grey;">
</span><span style="background-color: #232525; color: grey;"> </span><span style="background-color: #232525; color: #cc7832; font-weight: bold;">$type = </span><span style="background-color: #232525;"></span><span style="background-color: #232525; color: #9876aa;">$attachment</span><span style="background-color: #232525;">-></span><span style="background-color: #232525; color: #ffc66d;">getContentType</span><span style="background-color: #232525;">()</span><span style="background-color: #232525; color: #cc7832;">;</span><span style="background-color: #232525; color: grey;">
</span><span style="background-color: #232525; color: grey;"> </span><span style="background-color: #232525;">}</span>
<span style="background-color: #232525;">}</span></pre>
<br />
ということで、環境の違いもあるので全てを一気にやろうと思うとなかなか難しいかもしれませんがこんな感じで受信メールをLaravelで受け取ることができます。<br />
<br />
お疲れ様でした。 <br />
<br />
【その他参考にしたページ】<br />
<br />
<a href="https://sboersma.nl/blog/setting-up-postfix-and-pipe-incoming-emails-to-laravel" target="_blank">https://sboersma.nl/blog/setting-up-postfix-and-pipe-incoming-emails-to-laravel</a><br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXki4p7f2JgJBMpF0wlEjAG7bs7dhypvISc4MN2DtiL4ZaCAv0fzIwEoRJrgyalgdeXYNErCAh1BuRtY_RR_PTNbPrNWC88K03ZSQJ55E9MpYZuCBDGmJXaN_sAcmUAtD_v3XfE3ahfM77/s1600/30.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXki4p7f2JgJBMpF0wlEjAG7bs7dhypvISc4MN2DtiL4ZaCAv0fzIwEoRJrgyalgdeXYNErCAh1BuRtY_RR_PTNbPrNWC88K03ZSQJ55E9MpYZuCBDGmJXaN_sAcmUAtD_v3XfE3ahfM77/s1600/30.png" /></a></div>
<br />
<br />Anonymoushttp://www.blogger.com/profile/15645657529148406101noreply@blogger.com0tag:blogger.com,1999:blog-6545450414259005128.post-4035591046995836892016-05-25T04:48:00.000+09:002016-05-25T05:00:26.923+09:00【無料】サイトが落ちていないか監視<div dir="ltr">
サイトの運営を行っている人間からすると一番怖いのは「サイトが落ちる」こと、つまり訪問者がアクセスしてもページにエラーが出て表示がきちんとできていない状態です。</div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
こうなってしまうと、もんろん訪問者は(もしかすると舌打ちしながら)すぐに違うページへ移動してしまいほぼ二度とはやってくることはないと思います。</div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
そのためサイトが落ちていないかどうかは定期的にチェックをするべきですが、さすがに毎日毎日となるとなかなか面倒なもの。</div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
そこで、そういう時にはサイト監視サービスを使ってみましょう。<br />
インターネット上には制限こそあるものの無料でも利用できる監視サービスが幾つか存在しているので、その中から一つをご紹介したいと思います。</div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
名前は「<a href="https://uptimerobot.com/" target="_blank">Uptime Robot</a>」です。</div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
まずは以下が3つの特徴になります。</div>
<ul>
<li>最短5分ごとにサイトをチェックできる</li>
<li>https でのアクセスも可能(他のサービスでは有料のところもあります)</li>
<li>無料でも使える(最大50ページまで監視が可能) </li>
</ul>
<div dir="ltr">
では登録と設定方法を見ていきましょう。</div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
<b>【ユーザー登録】</b></div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
まず、<a href="https://uptimerobot.com/signUp" target="_blank">ユーザー登録ページ</a> へアクセスしユーザー登録します。</div>
<div dir="ltr">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiw27CwiO6RGjzLjswaV-qz4ooX9qqPvGe3Yq5E_tIxTOQRRRtLH6smzWgnJ-6_7TqiazlYLD_iqQ_kRUZGqBzbPsc2QZG6vVCZ9Xdnyc5IW6DoNoaQaNOkqk98iotOAoTM0sR9biWXE_UL/s1600/Screenshot+from+2016-05-25+04%253A16%253A57.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="313" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiw27CwiO6RGjzLjswaV-qz4ooX9qqPvGe3Yq5E_tIxTOQRRRtLH6smzWgnJ-6_7TqiazlYLD_iqQ_kRUZGqBzbPsc2QZG6vVCZ9Xdnyc5IW6DoNoaQaNOkqk98iotOAoTM0sR9biWXE_UL/s400/Screenshot+from+2016-05-25+04%253A16%253A57.png" width="400" /></a></div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
上から、</div>
<ol>
<li>氏名</li>
<li>メールアドレス</li>
<li>パスワード</li>
</ol>
になります。<br />
<div dir="ltr">
<br />
入力して「Sign-up」をクリックすると入力したメールアドレスに本登録用のURLが書かれた以下のようなメールが届くのでこれ(clicking hereの部分)をクリックしてください。</div>
<div dir="ltr">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgHJLWqgzbN6yAmw5ND_abv8ZDgTlQTICabypArY-V6qFKgYWgueIvEpsPFrn-cceUt8t04B-_6pbP3MT2rB_r6FTGnx1LwZYCotp9NIkFDbJbzq_gI07uuBBS0vuGTeegw6cWmxjYVTTWG/s1600/Screenshot+from+2016-05-24+18%253A50%253A21.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="135" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgHJLWqgzbN6yAmw5ND_abv8ZDgTlQTICabypArY-V6qFKgYWgueIvEpsPFrn-cceUt8t04B-_6pbP3MT2rB_r6FTGnx1LwZYCotp9NIkFDbJbzq_gI07uuBBS0vuGTeegw6cWmxjYVTTWG/s400/Screenshot+from+2016-05-24+18%253A50%253A21.png" width="400" /></a></div>
<br />
これでユーザー登録は完了です。<br />
<br />
<br />
<b>【設定】</b><br />
<br />
では、早速<a href="https://uptimerobot.com/login" target="_blank">ログインページ</a>からログインしたら、まずは設定をしましょう。<br />
ページ上部にある「My Settings」をクリック。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHQdt9rp0uta_b0IIeNxSVs3Ef_ePLvckv_blzi7L6-GCaHteoDfyl-hJrNBo_h7FuW_EmlZ6mxS448RJIMGSCk8OkiT0cyi5MbGx05Qx6w1e53H5JOQhYPQyIX2nXio6gBpH1ZAqaeaXd/s1600/Uptime+Robot+-+Dashboard+2016-05-25+04-23-42.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="40" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHQdt9rp0uta_b0IIeNxSVs3Ef_ePLvckv_blzi7L6-GCaHteoDfyl-hJrNBo_h7FuW_EmlZ6mxS448RJIMGSCk8OkiT0cyi5MbGx05Qx6w1e53H5JOQhYPQyIX2nXio6gBpH1ZAqaeaXd/s320/Uptime+Robot+-+Dashboard+2016-05-25+04-23-42.png" width="320" /></a></div>
<br />
<b>1.タイムゾーン</b><br />
<br />
ページ中程にあるタイムゾーンを東京へ変更しUpdateをクリック。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsk48l69A_h5DS7g5mGWZkFfd2Lk4TUPDTtJScUzIb_fBa87Ev9SYBoyQS-8Msqrfy3gEAynyvfsgHcrUSiu4YmpXIOCeT0h4ver9tq7PV83dOkO9MJ1VK4g7tJjz1WgyMAVus68OIoqQC/s1600/Screenshot+from+2016-05-24+18%253A56%253A43.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="223" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsk48l69A_h5DS7g5mGWZkFfd2Lk4TUPDTtJScUzIb_fBa87Ev9SYBoyQS-8Msqrfy3gEAynyvfsgHcrUSiu4YmpXIOCeT0h4ver9tq7PV83dOkO9MJ1VK4g7tJjz1WgyMAVus68OIoqQC/s400/Screenshot+from+2016-05-24+18%253A56%253A43.png" width="400" /></a></div>
<br />
※もしサイトからのお知らせメールが必要ない場合は「<span class="f12">Inform me about new features and updates (no more than twice a month).</span>」のチェックを外しておきましょう。<br />
<br />
また、通知を受け取りたいメールアドレスが他にもある場合は以下を参考にして追加しておきましょう。<br />
<br />
<b>2.通知先メールアドレスの追加</b><br />
<br />
「Add Alert Contact」 をクリック。 <br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdEH1UcQgQhJNVB6YY90qspWr2Mzpw5iaxuV5AvUPykoLMKQI50n8QSGpJ9zBVanI6qS4dmjiQ-OPSl7_7MBU3sW_hLLIfD1GPJ5vDZFLIlWc914nMgEo0fHDtDr6tH4Mn7f5HklX6M95n/s1600/Screenshot+from+2016-05-24+18%253A53%253A23.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="166" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdEH1UcQgQhJNVB6YY90qspWr2Mzpw5iaxuV5AvUPykoLMKQI50n8QSGpJ9zBVanI6qS4dmjiQ-OPSl7_7MBU3sW_hLLIfD1GPJ5vDZFLIlWc914nMgEo0fHDtDr6tH4Mn7f5HklX6M95n/s400/Screenshot+from+2016-05-24+18%253A53%253A23.png" width="400" /></a></div>
<br />
以下のようなダイアログが表示されるので<br />
<ol>
<li><span style="background-color: #cccccc;">Alert Contact Type</span> を E-mail に設定</li>
<li><span style="background-color: #cccccc;">Friendly Name</span> は区別しやすい好きな名前を入力</li>
<li><span style="background-color: #cccccc;">E-mail</span> に通知先メールアドレスを追加 </li>
<li><span style="background-color: #cccccc;">Create Alert Contact</span>を クリック</li>
</ol>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3hf1izLMbCa2GtXZWPqTsIZjR1UWI_Po6vN8lLuerfmYgVglG1qAhZt9gggy02MOIKF1K-0YK6MosEUoCtMN6m2iqRY1zZcFDN8BEDPtWynjRI8wLpRWTQqRiNYgvzyIVgCeZkWxU2i3w/s1600/Screenshot+from+2016-05-24+18%253A54%253A02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="292" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3hf1izLMbCa2GtXZWPqTsIZjR1UWI_Po6vN8lLuerfmYgVglG1qAhZt9gggy02MOIKF1K-0YK6MosEUoCtMN6m2iqRY1zZcFDN8BEDPtWynjRI8wLpRWTQqRiNYgvzyIVgCeZkWxU2i3w/s320/Screenshot+from+2016-05-24+18%253A54%253A02.png" width="320" /></a></div>
<br />
<br />
<b>【監視サイトの追加】 </b><br />
<br />
ホーム画面に戻って「+ Monitor」をクリック。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEil5J5GB0CBJ64s17Ml9aHjsSOr6p9tqoQN1EjI4tCzF175yoHvJXDAmzrywPJH8d0kOQtxQfD-x2-CtD5BIijSapwng1uSlFqXWiL0AACHz_LpKUXGxLHxEAausrwrdrPtYFWOmkwYXlLe/s1600/%25EF%25BD%259C.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="82" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEil5J5GB0CBJ64s17Ml9aHjsSOr6p9tqoQN1EjI4tCzF175yoHvJXDAmzrywPJH8d0kOQtxQfD-x2-CtD5BIijSapwng1uSlFqXWiL0AACHz_LpKUXGxLHxEAausrwrdrPtYFWOmkwYXlLe/s200/%25EF%25BD%259C.png" width="200" /></a></div>
<br />
以下のようなダイアログが表示されるので監視したいサイトの各種データを入力します。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEititG5SC22IOstBnWfwKdI6A0wa_4CQDKTWgXxpvNtbldFmjr2mJ0W_eVVzjkzm7w-qQM4gG-MdStmh_aSd1T5H1n6D_ZLbLBz9O-EJqR6jMW7E3VTsXyqcrsGFdBs0_NfLZATRrQRNWYM/s1600/Screenshot+from+2016-05-24+18%253A58%253A26.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEititG5SC22IOstBnWfwKdI6A0wa_4CQDKTWgXxpvNtbldFmjr2mJ0W_eVVzjkzm7w-qQM4gG-MdStmh_aSd1T5H1n6D_ZLbLBz9O-EJqR6jMW7E3VTsXyqcrsGFdBs0_NfLZATRrQRNWYM/s640/Screenshot+from+2016-05-24+18%253A58%253A26.png" width="451" /></a></div>
<br />
<ol>
<li><span style="background-color: #cccccc;">Monitor Type</span> ・・・ HTTP(s)を選択</li>
<li><span style="background-color: #cccccc;">Friendly Name</span> ・・・ 区別しやすい名前</li>
<li><span style="background-color: #cccccc;">URL (or IP)</span><span class="required"> ・・・ 監視したいページのURL</span></li>
<li><span class="required"><span style="background-color: #cccccc;">Monitoring Interval</span> ・・・ 何分毎にページをチェックしたいか?</span></li>
<li><span class="required">(任意)Authentication Settings ・・・ </span>おそらくページ監視時に送信するデータがある場合に利用できるものだと思いますが、通常は必要ないでしょう。</li>
</ol>
(通知先メールアドレス)<br />
<br />
あとは通知したいメールアドレスにチェックを入れて「Create Monitor」をクリックすれば完了です。<br />
もし他にも登録したいURLがある場合は同じ作業を繰り返し行ってください。<br />
<br />
もしサイトが落ちていたら通知がきますし、ホーム画面で統計データを見ることができます。<br />
<br />
以上、サイト監視ができる Uptime Robot の紹介でした。<br />
皆さんもぜひ一度試してみてください。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOS4-Bd0oxUG7InHwf5GiexEsytq-B4WL92vJHtdc2VDuIJuW0NMeEl5GqLfa8s2vZ81wvdo0JKtAkaZCHXV7AQieg5rEN9XlmQPhs_x6CWSqYawP-_21rAx63lPccAn88oUkkFjSm6LNF/s1600/sleeping.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOS4-Bd0oxUG7InHwf5GiexEsytq-B4WL92vJHtdc2VDuIJuW0NMeEl5GqLfa8s2vZ81wvdo0JKtAkaZCHXV7AQieg5rEN9XlmQPhs_x6CWSqYawP-_21rAx63lPccAn88oUkkFjSm6LNF/s1600/sleeping.png" /></a></div>
Anonymoushttp://www.blogger.com/profile/15645657529148406101noreply@blogger.com1tag:blogger.com,1999:blog-6545450414259005128.post-78578579997391646162016-05-25T04:13:00.000+09:002016-05-25T22:47:42.847+09:00私がフェイスブック・アプリを削除した理由と対処<div dir="ltr">
私は2012年からフェイスブックを利用しています。始めたころ私はカナダのバンクーバーに語学留学中で、初めて登校したとき先生から「友達とやりとりするようになるから(英文を書く習慣がつくから)絶対登録しなさい」と言われ半ば嫌々登録したのを覚えている。</div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
まだその頃は周りではミクシィをやっている人が多く、フェイスブックをやってるよ、という人はまだ少なかった。</div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
それがあれよあれよという間にフェイスブックの知名度が日本でも高くなり、そのうちミクシィよりもフェイスブックのアプリを開く時間の方が多くなってしまった。(私の場合、帰国後もカナダで会った友達のニュースを仕入れるにはフェイスブックに頼るしかなかったというのも大きな理由の一つだ)</div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
ちなみに私は今でも1〜2日ぐらいの頻度でフェイスブックをチェックする。</div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
ただ、それでもフェイスブックのアプリはこの度アンインストールしてしまった。</div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
理由は2つ。</div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
まず、あまりハイスペックとはいえない私のスマートフォンではフェイスブックのアプリをアップデートする際はとても時間がかかり、また不具合なのかもしれないがアップデートこの後は再起動をしなければいけない場合もあった。</div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
しかも幸か不幸かフェイスブックの開発スタッフはとても熱心で、ことあるごとにアプリをアップデートしてくれるからやっかいだった。</div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
さすがにもう毎回作業するのが面倒になり、自動でアップデートしない設定にもしてみたが結局はこの理由が大きく、アプリを削除してしまった。</div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
そして、もう一つの理由はバッテリーの消費だ。</div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
以下の記事だとフェイスブック・アプリによって電池消耗が20%も増えると書かれてある。</div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
<a href="https://www.blogger.com/blogger.g?blogID=6545450414259005128#editor/target=post;postID=7857857999739164616;onPublishedMenu=allposts;onClosedMenu=allposts;postNum=0;src=link" target="_blank">Facebookアプリを削除するとスマホのバッテリーが最大20%も長持ちすることが判明</a> </div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
携帯式バッテリーは過去に持っていたが紛失して以降全く使っていない私にとってはこれも都合が悪いものとなってしまった。</div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
【アプリ削除後の対処】</div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
では、今でもフェイスブックを開く私がとった対処とはなんだったのか?</div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
もうお気づきかもしれないが、そう、PCと同じくスマートフォンのブラウザでログインすることにしたのだ。</div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
こう書くと「いちいちブラウザを開いてフェイスブックを検索し、さらにログイン情報まで入力するのは面倒すぎる」という意見があるのかもしれない。そのとおりだと思う。</div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
なので、この問題を以下のようなテクニックで対処した。</div>
<div dir="ltr">
<br /></div>
<ol>
<li>まず初めてブラウザでフェイスブックにログインする場合にパスワードを保存するかと聞かれると思うのでこれを保存する。(以降、ログインする必要はなくなる)</li>
<li> ログインしたらブラウザのメニューの中からホームスクリーンにショートカットを作成する。</li>
</ol>
<div dir="ltr">
これで今までのアプリと同じようにアイコンをタップするだけでフェイスブックにログインした状態でブラウザがURLを開いてくれるというわけだ。</div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
では、使用感はどうか。<br />
残念ながらやはりネイティブアプリの方が動きはスムーズだ。フェイスブックがその昔HTML5を利用したアプリ開発をやめた理由がよくわかる。</div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
ただし、とは言ってもブラウザの方も進化していることは確かで、そこまでイライラさせられることがないというのも事実だ。私のようなライトなフェイスブックユーザーであればなんの問題もないかと思う。</div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
さらにこれはまだ未確認だが、私が使っているChromeは現在プッシュ通知にも対応しているそうなのでもしかしたら「今日はお友達のお誕生日ですよ」などと通知をしてくれるのかもしれない。</div>
<div dir="ltr">
ということで、フェイスブックはまだもう少し続けそうだが、アプリの方はもう使わないようになりそうだ。</div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
と、いっても最近は世界中の友達もフェイスブック自体をやらなくなってきているし、私自身が最後にフェイスブックに投稿したのももう半年ほど前になる。</div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
だからといって、Lineのタイムラインに移行するつもりもないのでそのうち本格的にSNSは卒業するかもしれない。</div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
今後SNSがなくなることはないだろうが、一時期ブームになったのはやはりそういう時代だったから、というのが私のSNSに対するものの捉え方だ。</div>
Anonymoushttp://www.blogger.com/profile/15645657529148406101noreply@blogger.com0tag:blogger.com,1999:blog-6545450414259005128.post-47350998067565321182016-05-24T17:07:00.000+09:002016-05-24T19:16:29.324+09:00n倍でループ【PHP】PHPに限らずプログラムで開発をするよく使うものの一つに for() ループがあると思います。<br />
今回はいつもとは少し変わったループの仕方を紹介したいと思います。<br />
<br />
通常でしたら、以下のように <span style="background-color: #cccccc;">$i++</span> インクリメントを使って1ずつ変数を追加していくパターンを使うかと思います。<br />
<pre style="background-color: #2b2b2b; color: #a9b7c6; font-family: 'Source Code Pro'; font-size: 10.5pt;"><span style="background-color: #232525; color: #cc7832; font-weight: bold;">for</span><span style="background-color: #232525;">(</span><span style="background-color: #232525; color: #9876aa;">$i </span><span style="background-color: #232525;">= </span><span style="background-color: #232525; color: #6897bb;">0 </span><span style="background-color: #232525; color: #cc7832;">; </span><span style="background-color: #232525; color: #9876aa;">$i </span><span style="background-color: #232525;">< </span><span style="background-color: #232525; color: #9876aa;">$count </span><span style="background-color: #232525; color: #cc7832;">; </span><span style="background-color: #232525; color: #9876aa;">$i</span><span style="background-color: #232525;">++) {</span><span style="background-color: #232525;">
</span><span style="background-color: #232525;"> </span><span style="background-color: #232525; color: grey;">// </span><span style="background-color: #232525; font-family: "takao pゴシック";">ここで何かの処理</span><span style="background-color: #232525; font-family: "takao pゴシック";">
</span><span style="background-color: #232525;">}</span></pre>
<br />
もしくは逆に <span style="background-color: #cccccc;">$i--</span> を使って変数を減らしていく方法もたまに使うのではないでしょうか。
<br />
<pre style="background-color: #2b2b2b; color: #a9b7c6; font-family: 'Source Code Pro'; font-size: 10.5pt;"><span style="background-color: #232525; color: #cc7832; font-weight: bold;">for</span><span style="background-color: #232525;">(</span><span style="background-color: #232525; color: #9876aa;">$i </span><span style="background-color: #232525;">= </span><span style="background-color: #232525; color: #6897bb;">5 </span><span style="background-color: #232525; color: #cc7832;">; </span><span style="background-color: #232525; color: #9876aa;">$i </span><span style="background-color: #232525;">> </span><span style="background-color: #232525; color: #6897bb;">0 </span><span style="background-color: #232525; color: #cc7832;">; </span><span style="background-color: #232525; color: #9876aa;">$i</span><span style="background-color: #232525;">--) {</span><span style="background-color: #232525;">
</span><span style="background-color: #232525;"> </span><span style="background-color: #232525; color: grey;">// </span><span style="background-color: #232525; font-family: "takao pゴシック";">ここで何かの処理</span><span style="background-color: #232525; font-family: "takao pゴシック";">
</span><span style="background-color: #232525;">}</span></pre>
<br />
では、今回は for() ループを nの倍数ずつループさせる方法はどうなるでしょうか。<br />
いろいろな方法があると思いますが、ひとつの答えとしては以下のようなものもあります。<br />
<pre style="background-color: #2b2b2b; color: #a9b7c6; font-family: 'Source Code Pro'; font-size: 10.5pt;"><span style="background-color: #232525; color: #9876aa;">$n </span><span style="background-color: #232525;">= </span><span style="background-color: #232525; color: #6897bb;">3</span><span style="background-color: #232525; color: #cc7832;">;</span>
<span style="background-color: #232525; color: #9876aa;">$count </span><span style="background-color: #232525;">= </span><span style="background-color: #232525; color: #6897bb;">15</span><span style="background-color: #232525; color: #cc7832;">;</span><span style="background-color: #232525; color: #cc7832;">
</span><span style="background-color: #232525; color: #cc7832; font-weight: bold;">for </span><span style="background-color: #232525;">(</span><span style="background-color: #232525; color: #9876aa;">$i </span><span style="background-color: #232525;">= </span><span style="background-color: #232525; color: #6897bb;">0</span><span style="background-color: #232525; color: #cc7832;">; </span><span style="background-color: #232525; color: #9876aa;">$i </span><span style="background-color: #232525;">< </span><span style="background-color: #232525; color: #9876aa;">$count</span><span style="background-color: #232525; color: #cc7832;">; </span><span style="background-color: #232525; color: #9876aa;">$i</span><span style="background-color: #232525;">+=</span><span style="background-color: #232525; color: #9876aa;">$n</span><span style="background-color: #232525;">) {</span><span style="background-color: #232525;">
</span><span style="background-color: #232525;"> </span><span style="background-color: #232525; color: #cc7832; font-weight: bold;">echo </span><span style="background-color: #232525; color: #9876aa;">$i </span><span style="background-color: #232525;">.</span><span style="background-color: #232525; color: #6a8759;">"</span><span style="background-color: #232525; color: #cc7832;">\n</span><span style="background-color: #232525; color: #6a8759;">"</span><span style="background-color: #232525; color: #cc7832;">;</span><span style="background-color: #232525; color: #cc7832;">
</span><span style="background-color: #232525;">}</span></pre>
<br />
実行結果としては、以下になります。<br />
<blockquote class="tr_bq">
<pre id="line1">0
<span id="line2"></span>3
<span id="line3"></span>6
<span id="line4"></span>9
<span id="line5"></span>12</pre>
</blockquote>
ではひとつずつ中身を見て行きましょう。<br />
<b><br /></b>
<b><br /></b>
<b>$n = 3</b><br />
これは何倍ずつループするかです。<br />
つまりループを3、6、9...という形にしたい場合は「3」になります。<br />
<br />
<b>$count = 15;</b><br />
最大値はいくらかになります。<br />
つまり、もし15を含めたい場合は $count = 16; に変更するか<br />
for() 内の <span style="background-color: #cccccc;">$i < $count</span> を <span style="background-color: #cccccc;">$i <= $count</span> へ変更する必要があります。<br />
<br />
ここまでは通常の for() ループを同じですね。<br />
では次。<br />
<br />
<b>for ($i = 0; $i < $count; $i+=$n) {}</b><br />
<ol>
<li>$i = 0 ・・・初期値が0</li>
<li>$i < $count ・・・ 最大値</li>
<li>$i+=$n <u>ループのたびに倍数を追加</u></li>
</ol>
ここが今回の特徴的な部分です。<span style="background-color: #cccccc;"> </span><br />
<span style="background-color: #cccccc;">$i++</span> の代わりに <span style="background-color: #cccccc;">$i+=3</span> を使ってループ内の変数を倍数にしています。<br />
<br />
はい。<br />
短いですが、以上解説でした。<br />
<br />
<br />
<b>【終わりに】</b> <br />
通常はあまりこのようなループを使うことは無いでしょうし、だとすると「正直可読性悪いんじゃ、、、?」と言われると確かにそのとおりですが、これもひとつのアイデアなのかなと思い紹介してみました。(もしかすると結構使われてるのかな?)<br />
<br />
今回は以上です。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEcH_2SMgNuCyDqzO9UV8CL6IX3woSCZ6krTk91_rcYTpCU7FsR62cIG2H2jZWqooK4UrBeEZLmCSo5dghaNWpa2GE3EMzIPACCQ0zaY-vSS8_e2S6appv4lyx0ViTQg609Q4pCMcktHhl/s1600/1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEcH_2SMgNuCyDqzO9UV8CL6IX3woSCZ6krTk91_rcYTpCU7FsR62cIG2H2jZWqooK4UrBeEZLmCSo5dghaNWpa2GE3EMzIPACCQ0zaY-vSS8_e2S6appv4lyx0ViTQg609Q4pCMcktHhl/s320/1.png" width="157" /></a></div>
<br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/15645657529148406101noreply@blogger.com0tag:blogger.com,1999:blog-6545450414259005128.post-14070688104826550152016-05-19T05:21:00.000+09:002016-05-19T20:44:44.188+09:00開発者のブラウザ「Blisk」を使ってみた感想ウェブ開発をしていて時々必要となってくる要件にPC、モバイルともに対応可能な「レスポンシブ・デザイン」というものが増えてきました。現在はPCが家になく、スマホだけ持っているという人も多くいるため、「モバイル・ファースト」に主眼をおいておられるクライアント様も多くいらっしゃいます。<br />
<br />
そこで、今回紹介するのは「Blisk」というブラウザです。<br />
このBliskは「開発者のためのブラウザ」 と銘打っているだけあって、ひとつの画面の中でスマートフォンやタブレットの画面を確認することができるとのことでした。<br />
忙しい時期ですが、業務の効率化を考えて時間を割いて少し体験してみました。<br />
<br />
<span id="goog_2128044472"></span><span id="goog_2128044473"></span><br />
<span id="goog_2128044470"></span><span id="goog_2128044471"></span>【ブラウザの外観】<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizZgAN-r2QiZEya05zOXQUZikzLPGU4GMMN5WKgPGmJACLavUfdo3NR8M07TE1XFEEvlPOwEGRcrt9r7kpsE9p6b8uWYzkLYBnLTDPoPhD4m7cEM_zMQa0ZECnfvSDuO2xWvTsSAjGEziV/s1600/Screenshot+from+2016-05-19+04%253A23%253A09.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="223" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizZgAN-r2QiZEya05zOXQUZikzLPGU4GMMN5WKgPGmJACLavUfdo3NR8M07TE1XFEEvlPOwEGRcrt9r7kpsE9p6b8uWYzkLYBnLTDPoPhD4m7cEM_zMQa0ZECnfvSDuO2xWvTsSAjGEziV/s400/Screenshot+from+2016-05-19+04%253A23%253A09.png" width="400" /></a></div>
<br />
必要なものだけが用意されている印象です。余計なものは必要ではない開発者としてはありがたいと思いました。<br />
ちなみに左側からスマートフォンやタブレットを選択するとすぐに画面が切り替わります。<br />
また、左側のエミュレーター部分ではマウスは黒丸に変更されタップやスワイプの動作となります<br />
<br />
<br />
【操作感】<br />
<br />
エミュレーターでよくある表示が遅くなることやひっかかりを感じることはほぼありませんでした。<br />
(私の場合はVirtualBoxで実行したので通常のWindowsでしたらまた違っているかもしれません)<br />
<br />
ただ、サイトによっては違うのかもしれませんが、スライダーなどの横スワイプが効かなったことが残念でした。<br />
また、モバイル対応していないページでは通常のブラウザとして利用できるのは好感がもてました。<br />
別のブラウザを開いて検索する必要はありませんので。 <br />
<br />
もちろん開発者ツールも使えます。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3mwo74aSb6RIXUim50ZiYb9dUeHtYSdpijmF9OUZJS5hWOo3yhhEvz365DfRA-pnwses03Tq7tbBzfiwFLI34qZmcspnKHxdnljj7JipoxJ15MKcHR9C6XXV_YPNfp80QzpIgTlZp42Dj/s1600/Screenshot+from+2016-05-19+04%253A35%253A25.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="301" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3mwo74aSb6RIXUim50ZiYb9dUeHtYSdpijmF9OUZJS5hWOo3yhhEvz365DfRA-pnwses03Tq7tbBzfiwFLI34qZmcspnKHxdnljj7JipoxJ15MKcHR9C6XXV_YPNfp80QzpIgTlZp42Dj/s400/Screenshot+from+2016-05-19+04%253A35%253A25.png" width="400" /></a></div>
<br />
<br />
【設定できるスマートフォン/タブレット機種】<br />
<ul>
<li>IPhone 4</li>
<li>IPhone 5</li>
<li>IPhone 6</li>
<li>IPhone 6 Plus</li>
<li>Nokia N9</li>
<li>Galaxy S3</li>
<li>Galaxy S4</li>
<li>Nexus 4</li>
<li>Nexus 6</li>
<li>Nexus 7</li>
<li>Nexus 10</li>
<li>IPad mini</li>
<li>IPad Air Retina</li>
</ul>
これだけそろっていれば必要なものは揃っているのではないでしょうか。<br />
<br />
<br />
【今後の開発予定】<br />
<br />
<span id="goog_2128044478"></span><span id="goog_2128044479"></span> これが少し楽しみですが、どうやら以下のように画面のビデオ録画機能を予定しているようです。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhw3aLvRJaOVl7sufKQdLuY0ipOBnpbXHXosiDAhHRBjbvtsfxuwPcaoV221EwCQoUffKXaRpic0iYCqu4OSu4Pm3j7devCII4Isf9B1VdckinkMDxoP28at37u05tsdNi4Q7_32MSa0ES/s1600/Screenshot+from+2016-05-19+04%253A24%253A52.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhw3aLvRJaOVl7sufKQdLuY0ipOBnpbXHXosiDAhHRBjbvtsfxuwPcaoV221EwCQoUffKXaRpic0iYCqu4OSu4Pm3j7devCII4Isf9B1VdckinkMDxoP28at37u05tsdNi4Q7_32MSa0ES/s400/Screenshot+from+2016-05-19+04%253A24%253A52.png" width="215" /></a></div>
<br />
<br />
【実行環境】<br />
<br />
現在までのところ windows のみしかありませんがMac、Linux版も予定しているようです。<br />
<br />
<br />
【Bliskを使ってみて】<br />
<br />
全体的に使いやすくていいソフトだなと思いました。 <br />
モバイル主体の開発があれば利用してみてもいいかなという感じですが、今のところ windows版のみとのことでしたので、私のLinuxの開発環境だといちいち VirtualBox を開かなくてはいけません。私にとってはここがネックになってきそうです。<br />
<br />
とりあえずのところはキープですかね。<br />
ではでは〜(^^)<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOS4-Bd0oxUG7InHwf5GiexEsytq-B4WL92vJHtdc2VDuIJuW0NMeEl5GqLfa8s2vZ81wvdo0JKtAkaZCHXV7AQieg5rEN9XlmQPhs_x6CWSqYawP-_21rAx63lPccAn88oUkkFjSm6LNF/s1600/sleeping.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOS4-Bd0oxUG7InHwf5GiexEsytq-B4WL92vJHtdc2VDuIJuW0NMeEl5GqLfa8s2vZ81wvdo0JKtAkaZCHXV7AQieg5rEN9XlmQPhs_x6CWSqYawP-_21rAx63lPccAn88oUkkFjSm6LNF/s1600/sleeping.png" /></a></div>
<br />
Anonymoushttp://www.blogger.com/profile/15645657529148406101noreply@blogger.com0tag:blogger.com,1999:blog-6545450414259005128.post-4994432450153463652016-05-14T19:40:00.000+09:002016-05-14T19:40:17.762+09:00wp-cli をさくらのVPSにインストール以前よりここのブログとはまた別テーマの新ブログを開始しようと考えていたため、wordpressを以前から利用しているさくらのVPSへインストールしてみました。<br />
早速ログインしてみるとプラグインを更新しろとのメッセージを発見したので実行しようとすると、FTP(or STFP)の情報が必要だとのことでした。<br />
<br />
ただ、私のサーバーはセキュリティ上の理由からFTPは使っておらず、SFTPも公開鍵ファイルでログインする形になっています。。<br />
<br />
途方にくれていたところターミナルから実行できる wordpress のクライアントバージョン「wp-cli」というものが存在するということだったので早速インストールしてみました。<br />
本記事はそのインストール手順と主要なコマンドのまとめになります。<br />
<br />
<br />
<br />
<b>【サーバー環境】</b><br />
さくらのVPS(CentOS 6.7)<br />
<br />
<br />
<b>【インストール手順】</b><br />
インストールといっても実際はファイルをダウンロードして権限を設定し、適当な場所に設置するだけです。<br />
実際には以下になります。 <br />
<br />
<br />
<b>1. wp-cli をダウンロード</b><br />
<pre style="background-color: #2b2b2b; color: #a9b7c6; font-family: 'Source Code Pro'; font-size: 10.5pt;"><span style="background-color: #232525;">curl -O https:</span><span style="background-color: #232525; color: grey;">//raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar</span></pre>
※curlコマンドが利用できない場合は先にインストールが必要です。<br />
<br />
<br />
<b>2.権限の設定</b><br />
<pre style="background-color: #2b2b2b; color: #a9b7c6; font-family: 'Source Code Pro'; font-size: 10.5pt;"><span style="background-color: #232525;">chmod +x wp-cli.phar</span></pre>
※環境によっては <span style="background-color: #cccccc;">sudo</span> が必要かもしれません。<br />
<br />
<br />
<b>3.パスが通っているフォルダへ移動</b><br />
<pre style="background-color: #2b2b2b; color: #a9b7c6; font-family: 'Source Code Pro'; font-size: 10.5pt;"><span style="background-color: #232525;">sudo mv wp-cli.phar /usr/local/bin/wp</span></pre>
※環境によって、<span style="background-color: #cccccc;">/usr/local/bin/ <span style="background-color: white;">の部分を変更してください。</span></span><br />
<br />
<br />
はい!<br />
これで <span style="background-color: #cccccc;">wp ***</span> というコマンドが利用可能になっているはずです。<br />
まずは以下のコマンドを実行してインフォメーションを見てみましょう。<br />
バージョン情報などが表示されるはずです。<br />
<pre style="background-color: #2b2b2b; color: #a9b7c6; font-family: 'Source Code Pro'; font-size: 10.5pt;"><span style="background-color: #232525;">wp --info</span></pre>
<br />
<br />
【主要なコマンド】<br />
<br />
<b>1.wordpress本体のアップデート</b><br />
<pre style="background-color: #2b2b2b; color: #a9b7c6; font-family: 'Source Code Pro'; font-size: 10.5pt;"><span style="background-color: #232525;">wp core update</span></pre>
<br />
<b>2.(全ての)プラグインのアップデート</b><br />
<pre style="background-color: #2b2b2b; color: #a9b7c6; font-family: 'Source Code Pro'; font-size: 10.5pt;"><span style="background-color: #232525;">wp plugin update --all</span></pre>
<br />
<b>3.テーマのインストール</b><br />
<pre style="background-color: #2b2b2b; color: #a9b7c6; font-family: 'Source Code Pro'; font-size: 10.5pt;"><span style="background-color: #232525; color: #9876aa; font-style: italic;">wp theme install </span><span style="background-color: #232525; color: #6a8759;">"wp castle"</span></pre>
<br />
その他のコマンドは <a href="https://wp-cli.org/commands/" target="_blank">こちら</a> をご覧ください。<br />
そのうち、時間ができたらもっと多くのコマンドをまとめてみたいと思います。<br />
<br />
ではでは。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-bNe21trbGNGUbVYPaLIFngbcYdUgCQKpaU6zzkqORbmMf6XlYuX-FIfJkIKKXgTmqVbnhK-JrU4c2jK8V5It7ocMaBkhFNwxQA0_KaVvkf2ttm-woX_jcIajRojQY2Pmz_OO40PHk5P4/s1600/bye.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-bNe21trbGNGUbVYPaLIFngbcYdUgCQKpaU6zzkqORbmMf6XlYuX-FIfJkIKKXgTmqVbnhK-JrU4c2jK8V5It7ocMaBkhFNwxQA0_KaVvkf2ttm-woX_jcIajRojQY2Pmz_OO40PHk5P4/s1600/bye.png" /></a></div>
Anonymoushttp://www.blogger.com/profile/15645657529148406101noreply@blogger.com0tag:blogger.com,1999:blog-6545450414259005128.post-60143920851740191492016-05-11T19:18:00.001+09:002016-05-11T19:33:22.574+09:00PHPで休日を管理するなら yasumi【サンプルあり】ウェブサイトの開発を進めているとたまに必要となってくるものに「祝日、休日の取り扱い」があります。<br />
祝日・休日は結構厄介で、最近で言うと「山の日」など新たに制定されたり、突然名前が変わってしまう場合もあるため、これまでは Google Calendar APIから取得をするというのが定石だったかと思います。<br />
<br />
ただ、GoogleのAPIは変更が大きく、また廃止されてしまうものも少なくないため最近は極力は使用しないようにしています。<br />
<br />
そこで、何か別のアプローチ方法はないかと考えていたところ、とても便利なパッケージを発見したので試してみました。<br />
<br />
その名は「<a href="https://github.com/azuyalabs/yasumi" target="_blank">Yasumi</a>」です。(←開発者は日本の方っぽいです)<br />
世界各国の言語での翻訳にも対応しているようなので、もちろん日本語の祝日・休日の名前も取得できますよ。 <br />
<br />
<br />
<b>【インストール】 </b><br />
composer を使ってインストールできます。<br />
<pre style="background-color: #2b2b2b; color: #a9b7c6; font-family: 'Source Code Pro'; font-size: 10.5pt;"><span style="background-color: #232525;">composer </span><span style="background-color: #232525; color: #cc7832; font-weight: bold;">require </span><span style="background-color: #232525;">azuyalabs/yasumi</span></pre>
<br />
<b>【使い方】 </b><br />
使い方はとても簡単で、Yasumi::create() の引数に<br />
<ol>
<li>どこの国の祝日・休日を取得するか</li>
<li>取得したい祝日・休日は西暦何年か</li>
<li>(オプション)翻訳する言語はどこか</li>
</ol>
を設定するだけで1年間の全祝日・休日を取得することができます。<br />
<br />
<pre style="background-color: #2b2b2b; color: #a9b7c6; font-family: 'Source Code Pro'; font-size: 10.5pt;"><span style="background-color: #232525; color: #cc7832; font-weight: bold;">use </span><span style="background-color: #232525;">Yasumi\Yasumi</span><span style="background-color: #232525; color: #cc7832;">;</span>
<span style="background-color: #232525; color: #cc7832;">
</span><span style="background-color: #232525; color: #9876aa;">$holidays </span><span style="background-color: #232525;">= Yasumi::create(</span><span style="background-color: #232525; color: #6a8759;">'Japan'</span><span style="background-color: #232525; color: #cc7832;">, </span><span style="background-color: #232525; color: #6897bb;">2016</span><span style="background-color: #232525; color: #cc7832;">, </span><span style="background-color: #232525; color: #6a8759;">'ja_JP'</span><span style="background-color: #232525;">)</span><span style="background-color: #232525; color: #cc7832;">;</span>
<span style="background-color: #232525; color: #cc7832;">
</span><span style="background-color: #232525; color: #cc7832; font-weight: bold;">foreach </span><span style="background-color: #232525;">(</span><span style="background-color: #232525; color: #9876aa;">$holidays </span><span style="background-color: #232525; color: #cc7832; font-weight: bold;">as </span><span style="background-color: #232525; color: #9876aa;">$holiday</span><span style="background-color: #232525;">) {</span>
<span style="background-color: #232525;">
</span><span style="background-color: #232525;"> </span><span style="background-color: #232525; color: #cc7832; font-weight: bold;">echo </span><span style="background-color: #232525; color: #9876aa;">$holiday</span><span style="background-color: #232525;">->format(</span><span style="background-color: #232525; color: #6a8759;">'Y-m-d'</span><span style="background-color: #232525;">) .</span><span style="background-color: #232525; color: #6a8759;">': '</span><span style="background-color: #232525;">. </span><span style="background-color: #232525; color: #9876aa;">$holiday</span><span style="background-color: #232525;">->getName() .</span><span style="background-color: #232525; color: #6a8759;">'<br>'</span><span style="background-color: #232525; color: #cc7832;">;</span>
<span style="background-color: #232525; color: #cc7832;">
</span><span style="background-color: #232525;">}</span></pre>
<br />
<b><span style="font-size: large;"><a href="http://demo-laravel52.capilano-fw.com/example/yasumi" target="_blank">【サンプル】</a></span></b><br />
<br />
<br />
ちなみにこのパッケージも将来的にサポートされなくなってしまう可能性はありますがMITライセンスでの公開ですし、この記事を書いている時点で240ものスターがついているのでおそらくGoogle のAPIを利用するよりは安定性は高いと考えています。<br />
<br />
いざとなったらPull Request やフォークして使えますしね。<br />
<br />
ではでは、今回は以上です。<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOS4-Bd0oxUG7InHwf5GiexEsytq-B4WL92vJHtdc2VDuIJuW0NMeEl5GqLfa8s2vZ81wvdo0JKtAkaZCHXV7AQieg5rEN9XlmQPhs_x6CWSqYawP-_21rAx63lPccAn88oUkkFjSm6LNF/s1600/sleeping.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOS4-Bd0oxUG7InHwf5GiexEsytq-B4WL92vJHtdc2VDuIJuW0NMeEl5GqLfa8s2vZ81wvdo0JKtAkaZCHXV7AQieg5rEN9XlmQPhs_x6CWSqYawP-_21rAx63lPccAn88oUkkFjSm6LNF/s1600/sleeping.png" /></a></div>
<div style="text-align: center;">
(休みほしい...笑)</div>
<br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/15645657529148406101noreply@blogger.com0tag:blogger.com,1999:blog-6545450414259005128.post-50525916300708739802016-05-11T18:20:00.000+09:002016-05-11T18:20:54.661+09:00Composer でインストールができない!(短文)composer であるパッケージをインストールしようとしたら次のようなエラーが出てしまいました。<br />
<blockquote class="tr_bq">
Your configuration does not allow connections to http://packagist.jp/packages.json. See https://getcomposer.org/doc/06-config.md#secure-http for details.</blockquote>
うむむ、、、どうやら私の設定では接続できないよと言っているようです。<br />
そんな設定してないのに、、、?<br />
<br />
仕方がないので言われたとおりURLをチェックしてみることに<br />
<br />
<a href="https://getcomposer.org/doc/06-config.md#secure-http%20for%20details">https://getcomposer.org/doc/06-config.md#secure-http for details</a><br />
<br />
説明としては、<br />
<br />
secure-http の項目はデフォルトで「true」。そして、この項目が true だったら http<b>s </b>の通信しか許可しないよ、ということらしいです。<br />
<br />
ということは、 composer がデフォルトでセキュア対応したということなんですね。<br />
そこで、composer.json に以下のように secure-http を false にしてインストールを実行すると今まで通りうまくいきました。<br />
<br />
<pre style="background-color: #2b2b2b; color: #a9b7c6; font-family: 'Source Code Pro'; font-size: 10.5pt;"><span style="color: #9876aa;">"config"</span><span style="color: #cc7832;">: </span>{
<span style="color: #9876aa;">"secure-http"</span><span style="color: #cc7832;">: </span><span style="color: #cc7832; font-weight: bold;">false</span>
}<span style="color: #cc7832;">,</span></pre>
<br />
ちなみにsecure-httpの項目の最後には <a href="http://sukohi.blogspot.jp/2016/02/htts-lets-encrypt.html">以前の記事</a> で紹介した Let's Encryp でセキュア対応した方がいいよと書いてあります。<br />
世のウェブページのセキュア対応がどんどんすすんでいることが今回の件からもわかりますね。<br />
<br />
というか、Packagistがまだ https に対応してないのですかね?<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhj_SQjMquqotLGmmwq-ucjmivRxRmEj_KMGk961JO4MTHrRicU3J1R7tfNJ6J6wumzK73XUhUVWMyhyphenhyphenFBmVMmzVMDIGp8V67S439u3cf8ZxhhoOH1qRj5LMasVV8fpFWNBBlMQ6Ee-fSf0/s1600/fasdfsd.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhj_SQjMquqotLGmmwq-ucjmivRxRmEj_KMGk961JO4MTHrRicU3J1R7tfNJ6J6wumzK73XUhUVWMyhyphenhyphenFBmVMmzVMDIGp8V67S439u3cf8ZxhhoOH1qRj5LMasVV8fpFWNBBlMQ6Ee-fSf0/s320/fasdfsd.png" width="258" /></a></div>
<br />
<span id="goog_1003715468"></span><span id="goog_1003715469"></span><br />Anonymoushttp://www.blogger.com/profile/15645657529148406101noreply@blogger.com0