[PHP] docomo 雑談対話 API

docomo が提供してくれている 雑談対話API をさくっと php で使う方法。

<?php
/*****
* https://dev.smt.docomo.ne.jp/?p=docs.api.page&api_docs_id=5
*****/
function webnist($text) {
$context_file = dirname(__FILE__).'/.docomoapi.context';
$api_key = 'your API key here';
$api_url = sprintf('https://api.apigw.smt.docomo.ne.jp/dialogue/v1/dialogue?APIKEY=%s&#39;, $api_key);
$req_body = array('utt' => $text);
if ( file_exists($context_file) ) {
$req_body['context'] = file_get_contents($context_file);
}
$headers = array(
'Content-Type: application/json; charset=UTF-8',
);
$options = array(
'http'=>array(
'method' => 'POST',
'header' => implode( "\r\n", $headers ),
'content' => json_encode($req_body),
)
);
$stream = stream_context_create( $options );
$res = json_decode(file_get_contents($api_url, false, $stream));
if (isset($res->context)) {
file_put_contents($context_file, $res->context);
}
return isset($res->utt) ? $res->utt : '';
}

curl で試したいときは、こんな感じ

curl -s --insecure \
 -H "Content-Type: application/json; charset=UTF-8" \
 https://api.apigw.smt.docomo.ne.jp/dialogue/v1/dialogue?APIKEY=XXXXXX \
 -d "{\"utt\":\"アイス食べたい\"}"

view raw
gistfile1.md
hosted with ❤ by GitHub

まともに使いたければ https://github.com/fetus-hina/docomo-dialogue とかのライブラリ使うといいと思うよ。

[PHP] Google Calendar API v3 で日本の祝日を取得する

下準備

  • Google APIs ConsoleでCalendar APIのステータスをONにする
  • Google API keyを取得する
<?php
function get_holidays_this_month($year, $month){
// 月初日
$first_day = mktime(0, 0, 0, intval($month), 1, intval($year));
// 月末日
$last_day = strtotime('-1 day', mktime(0, 0, 0, intval($month) + 1, 1, intval($year)));
$api_key = 'YOUR API KEY HERE';
$holidays_id = 'outid3el0qkcrsuf89fltf7a4qbacgt9@import.calendar.google.com'; // mozilla.org版
//$holidays_id = 'japanese__ja@holiday.calendar.google.com'; // Google 公式版日本語
//$holidays_id = 'japanese@holiday.calendar.google.com'; // Google 公式版英語
$holidays_url = sprintf(
'https://www.googleapis.com/calendar/v3/calendars/%s/events?&#39;.
'key=%s&timeMin=%s&timeMax=%s&maxResults=%d&orderBy=startTime&singleEvents=true',
$holidays_id,
$api_key,
date('Y-m-d', $first_day).'T00:00:00Z' , // 取得開始日
date('Y-m-d', $last_day).'T00:00:00Z' , // 取得終了日
31 // 最大取得数
);
if ( $results = file_get_contents($holidays_url) ) {
$results = json_decode($results);
$holidays = array();
foreach ($results->items as $item ) {
$date = strtotime((string) $item->start->date);
$title = (string) $item->summary;
$holidays[date('Y-m-d', $date)] = $title;
}
ksort($holidays);
}
return $holidays;
}

view raw
gistfile1.php
hosted with ❤ by GitHub

9行目の $api_key = 'YOUR API KEY HERE'; って所を取得してきた Google API Key に書き換えてください。

[PHP] 非公開領域にある pdf をダウンロードさせる

ログインとかしてないと pdf をダウンロードできないようにしようと思って、pdf を非公開領域に置いて、いかのようなコードを書いたんですよ。

<?php
$mime_type = 'application/pdf';
$file_path = '/path/to/pdf';
header('Content-Disposition: inline; filename="'.basename($file_path).'"');
header('Content-Length: '.filesize($file_path));
header('Content-Type: '.$mime_type);
readfile($file_path);

view raw
gistfile1.php
hosted with ❤ by GitHub

そしたら https な環境で IE 8 からダウンロードできないってクレームががが…

IE5 – IE8 では https 環境で Cache-control:no-cache へっだが付いてるとダウンロードできないんですって…
Internet Explorer file downloads over SSL do not work with the cache control headers

そこで以下のようになおしました。

<?php
$mime_type = 'application/pdf';
$file_path = '/path/to/pdf';
// for IE 8 ( see http://support.microsoft.com/kb/323308/ja )
$expires = 30;
header("Last-Modified: ". gmdate("D, d M Y H:i:s", filemtime($file_path)). " GMT");
header("Expires: " . date(DATE_RFC1123, time() + $expires));
header("Pragma: cache");
header("Cache-Control: max-age={$expires}");
header("Cache-Control: cache");
// for IE 8
header('Content-Disposition: inline; filename="'.basename($file_path).'"');
header('Content-Length: '.filesize($file_path));
header('Content-Type: '.$mime_type);
readfile($file_path);

view raw
gistfile1.php
hosted with ❤ by GitHub

IE8めー

静的ファイルの大文字小文字を吸収

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* /canonical.php [L]
</IfModule>

view raw
.htaccess
hosted with ❤ by GitHub

<?php
function not_found($message = '') {
header("HTTP/1.1 404 Not Found");
echo $message."\n";
die();
}
if (!isset($_SERVER['REQUEST_URI']))
not_found();
$uri = htmlspecialchars($_SERVER['REQUEST_URI']);
if ($uri === '/canonical.php')
not_found();
$dir = dirname(__FILE__).dirname($uri).'/';
if (!file_exists($dir))
not_found("{$uri} is not found.");
$file = pathinfo(basename($uri));
$name = isset($file['filename']) ? $file['filename'] : '';
$ext = isset($file['extension']) ? '.'.$file['extension'] : '';
$filenames = array(
$name . strtolower($ext),
strtolower($name) . $ext,
strtolower($name) . strtolower($ext),
strtolower($name) . strtoupper($ext),
$name . strtoupper($ext),
strtoupper($name) . $ext,
strtoupper($name) . strtoupper($ext),
strtoupper($name) . strtolower($ext),
);
foreach ($filenames as $filename) {
if (file_exists($dir.$filename)) {
header('HTTP/1.1 301 Moved Permanently');
header('Location: '.dirname($uri).'/'.$filename);
exit();
}
}
not_found("{$uri} is not found.");

view raw
canonical.php
hosted with ❤ by GitHub

[PHP] eAccelerator で .phar インクルード時に Fatal error が発生する

[Tue May 07 13:29:34 2013] [error] [client 127.0.0.1] PHP Fatal error:  Uncaught exception 'PharException' with message '__HALT_COMPILER(); must be declared in a phar' in /path/to/wp/wp-content/plugins/nephila-clavata/includes/aws.phar:17\nStack trace:\n#0 /path/to/wp/wp-content/plugins/nephila-clavata/includes/aws.phar(17): Phar::mapPhar('aws.phar')\n#1 /path/to/wp/wp-content/plugins/nephila-clavata/includes/class-s3-helper.php(2): require_once('/path/to/wp...')\n#2 /path/to/wp/wp-content/plugins/nephila-clavata/plugin.php(32): require_once('/path/to/wp...')\n#3 /path/to/wp/wp-settings.php(195): include_once('/path/to/wp...')\n#4 /path/to/wp/wp-config.php(88): require_once('/path/to/wp...')\n#5 /path/to/wp/wp-load.php(29): require_once('/path/to/wp...')\n#6 /path/to/wp/wp-admi in /path/to/wp/wp-content/plugins/nephila-clavata/includes/aws.phar on line 17, referer: http://example.com/wp-admin/options-general.php?page=nephila-clavata

上記のように eAccelerator 有効になってる環境で *.phar ファイルを include すると Fatal Error が発生する場合。
eaccelerator.filter を設定して *.phar を対象外にして対応。

eaccelerator.filter = "!*.phar"

いや、APC 使えって話なんですけどね…

[PHP] ISBN のチェック

たまには写経を

ISBN は、誤り検出のため各数字の重み付き合計が 11 の倍数になるように最後の数字が調節されている。
最後の数字のみ 10 にしたい場合は X で表す。(via. C言語によるアルゴリズム辞典 P.371)

<?php
var_dump(validISBN('4-87408-414-1'));
function validISBN($isbn) {
if (preg_match('/^(\d)-?(\d)-?(\d)-?(\d)-?(\d)-?(\d)-?(\d)-?(\d)-?(\d)-?([\dX])$/i', $isbn, $d)) {
$d[0] = 0;
foreach ( $d as $key => &$val ) {
$val = ($key == 10 && ($val == 'x' || $val == 'X')) ? 10 : intval($val);
}
for ( $i = 1; $i <= 10; $i++ ) {
$d[$i] += $d[$i1];
}
for ( $i = 1; $i <= 10; $i++ ) {
$d[$i] += $d[$i1];
}
return ($d[10] % 11 == 0);
} else {
return false;
}
}

view raw
valid-isbn.php
hosted with ❤ by GitHub

[PHP][AWS] AWS SDK for PHP 2 で S3 にファイルをアップロード

<?php
require_once("aws.phar");
use Aws\Common\Aws;
use Aws\Common\Enum\Region;
use Aws\S3\Enum\CannedAcl;
use Aws\S3\Exception\S3Exception;
use Guzzle\Http\EntityBody;
$access_key = 'Your Access Key';
$secret_key = 'Your Secret Key';
$region = Region::AP_NORTHEAST_1; // Region::AP_NORTHEAST_1 = Tokyo Region
$bucket = 's3_bucket_name';
try {
// S3
$s3 = Aws::factory(array(
'key' => $access_key,
'secret' => $secret_key,
'region' => $region,
))->get('s3');
$info = new FInfo(FILEINFO_MIME_TYPE);
// Upload File
$filename = 'test.txt';
$filebody = EntityBody::factory(fopen($filename, 'r'));
$filetype = $info->file($filename);
$response = $s3->putObject(array(
'Bucket' => $bucket,
'Key' => $filename,
'Body' => $filebody,
'ContentType' => $filetype,
'StorageClass' => 'STANDARD', // STANDARD or REDUCED_REDUNDANCY
//'ServerSideEncryption => 'AES256',
'ACL' => CannedAcl::PUBLIC_READ, // PUBLIC_READ, PRIVATE_ACCESS…
));
var_dump($response);
} catch (S3Exception $e) {
}

view raw
upload-s3.php
hosted with ❤ by GitHub

Region の設定値: PHP 2: Class Aws\Common\Enum\Region | AWS SDK for PHP 2
ACL の設定値: PHP 2: Class Aws\S3\Enum\CannedAcl | AWS SDK for PHP 2

[PHP] Twitter Search API の使い方

<?php
$search_word = 'http://example.com/&#39;;
$page_per_posts = 100;
$twitter_search_api = sprintf(
'http://search.twitter.com/search.json?q=%s&rpp=%d&#39;,
urlencode($search_word),
$page_per_posts
);
$results = array();
if ( $response = file_get_contents($twitter_search_api) ) {
$json = json_decode($response);
$list = (array)(isset($json->results) ? $json->results : array());
foreach ( $list as $item ){
$results[$item->id_str] = array(
'author' => $item->from_user_name ,
'author_id' => $item->from_user_id_str ,
'profile_url' => $item->profile_image_url ,
'tweet_url' => sprintf('https://twitter.com/%s/status/%s&#39;, $item->from_user, $item->id_str) ,
'datetime' => (int) strtotime($item->created_at) ,
'content' => $item->text ,
'geo' => $item->geo ,
'language' => $item->iso_language_code ,
);
}
}

$search_word は検索したい文字列、$page_per_posts は一度に取得するツイート数、$results に検索結果が入るよ。

via. GET search | Twitter Developers

Re: phpで日本の祝日や振替休日を出力する。

とりあえず1か月分の祝日を取得します。ついでに振替休日やら、国民の休日にも対応してみました。国民の休日なんてめったにあるもんじゃないんですけど、2015年にまたあるようなので、とりあえず実装してみました。イベントスケジュールとかを作るときに結構便利です。

via. phpで日本の祝日や振替休日を出力する。 ::: Toro_Unit

引数には、年も指定できた方が良いですね。

<?php
function get_holidays_this_month($year, $month){
// 月初日
$first_day = mktime(0, 0, 0, intval($month), 1, intval($year));
// 月末日
$last_day = strtotime('-1 day', mktime(0, 0, 0, intval($month) + 1, 1, intval($year)));
$holidays_url = sprintf(
'http://www.google.com/calendar/feeds/%s/public/full-noattendees?start-min=%s&amp;start-max=%s&amp;max-results=%d&amp;alt=json&#39; ,
'japanese__ja@holiday.calendar.google.com' ,
date('Y-m-d', $first_day) , // 取得開始日
date('Y-m-d', $last_day) , // 取得終了日
31 // 最大取得数
);
if ( $results = file_get_contents($holidays_url) ) {
$results = json_decode($results, true);
$holidays = array();
foreach ($results['feed']['entry'] as $val ) {
$date = $val['gd$when'][0]['startTime'];
$week = date('w',strtotime($date));
$title = $val['title']['$t'];
$holidays[$date] = $title;
if( $week == 0) {
$nextday = date('Y-m-d',strtotime('+1 day', strtotime($date)));
$holidays[$nextday] = '振替休日';
}
$before_yesterday = date('Y-m-d',strtotime('-2 day', strtotime($date)));
if(isset($holidays[$before_yesterday])){
$yesterday = date('Y-m-d',strtotime('-1 day', strtotime($date)));
$holidays[$yesterday] = '国民の休日';
}
}
ksort($holidays);
}
return $holidays;
}

[2014-8-26 追記] Google Calendar API v3 に対応させる記事を書きました
[PHP] Google Calendar API v3 で日本の祝日を取得する

[PHP] 10進数をn進数に変換

<?php
function dec_to_n( $dec, $n = 62, $disits = null ) {
if ( !$disits ) {
$disits = array(
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
'u', 'v', 'w', 'x', 'y', 'z',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z',
);
}
$max_n = count($disits);
if ( ! (preg_match('/^\d+$/', $n) && $n >= 2 && $n <= $max_n) ) return FALSE;
if ( ! preg_match('/^\d+$/', $dec) ) return FALSE;
if ( $dec == 0 ) return $dec;
$num_str = '';
while ( $dec !== 0 ) {
$num_str = $disits[$dec % $n] . $num_str;
$dec = (int) ($dec / $n);
}
return $num_str;
}
function n_to_dec( $num_str, $n = 62, $disits = null ) {
if ( !$disits ) {
$disits = array(
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
'u', 'v', 'w', 'x', 'y', 'z',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z',
);
}
$max_n = count($disits);
$valids = array();
for ( $i = 0; $i < $max_n; $i++ ) {
$valids[$disits[$i]] = $i;
}
if ( ! (preg_match('/^\d+$/', $n) && $n >= 2 && $n <= $max_n) ) return FALSE;
if ( ! preg_match('/^[\da-zA-Z]+$/', $num_str) ) return FALSE;
$dec = 0;
for ( $i = 0; $i < strlen($num_str); $i++ ) {
$dec += $valids[ substr($num_str, ($i + 1) * –1, 1) ] * pow( $n, $i );
}
return $dec;
}

view raw
dec_to_n.php
hosted with ❤ by GitHub