memo.xight.org

日々のメモ

カテゴリ : PHP

1ページ目 / 全10ページ

anyenv で phpenv の設定

Install

$ cd $PHPENV_ROOT
$ git submodule init
$ git submodule update
(snip)
Unable to checkout '4f5c3c8b8b58ffc1ef0f70e3b347dfbb6b63fd0f' in submodule path 'php-ext/http'

php-ext/http を origin/master から取ってくる

$ cd .anyenv/envs/phpenv/php-ext/http
$ git fetch
$ git reset --hard origin/master
$ cd ..
$ git commit -am 'fix http'

phpenv/phpenv の phpenv 0.0.4-dev は
phpenv install -l が動作しない。

CHH/phpenv を利用するには
$(anyenv root)/share/anyenv-install/phpenv を編集する

install_env "https://github.com/CHH/phpenv.git" "master"

$ rm $(anyenv root)/envs/phpenv
$ anyenv install phpenv

Reference

anyenvで入れたphpenvでMacにPHPをインストールする - DailyRecord::Base
http://littlestarling.github.io/blog/2014/05/02/install-php-via-phpenv-on-anyenv/

rbenv, pyenv, plenv, phpenv から anyenv への移行

*env を remove

$ brew list |grep env
plenv
pyenv
pyenv-virtualenv
rbenv
$ brew remove plenv
$ brew remove pyenv
$ brew remove pyenv-virutalenv
$ brew remove rbenv

anyenv インストール

$ git clone https://github.com/riywo/anyenv ~/.anyenv

zshrc

if [ -d $HOME/.anyenv ] ; then
	export PATH="$HOME/.anyenv/bin:$PATH"
	eval "$(anyenv init -)"

	for D in `ls $HOME/.anyenv/envs`
	do
		export PATH="$HOME/.anyenv/envs/$D/shims:$PATH"
	done
fi

シェル再読み込み

$ exec $SHELL -l

anyenv で *env をインストール

$ anyenv install plenv
$ anyenv install pyenv
$ anyenv install rbenv
$ anyenv install phpenv

anyenv-update

$ mkdir -p $(anyenv root)/plugins
$ git clone https://github.com/znz/anyenv-update.git $(anyenv root)/plugins/anyenv-update
$ anyenv update

anyenv-exec

$ mkdir -p $(anyenv root)/plugins
$ git clone git://github.com/aereal/anyenv-exec.git $(anyenv root)/plugins/anyenv-exe
$ anyenv --version

anyenv-git

$ mkdir -p $(anyenv root)/plugins
$ git clone https://github.com/znz/anyenv-git.git $(anyenv root)/plugins/anyenv-git
$ anyenv git gc

Refence

GitHub - anyenv
https://github.com/riywo/anyenv

GitHub - anyenv-update
https://github.com/znz/anyenv-update

GitHub - anyenv-git
https://github.com/znz/anyenv-git

GitHub - anyenv-exec
https://github.com/aereal/anyenv-exec

phpenv の導入

Install

% git clone git://github.com/phpenv/phpenv.git .phpenv
% $HOME/.phpenv/bin/phpenv-install-all-darwin

.zshrc, .zshenv あたり

# phpenv
eval "$(phpenv init -)"

if [[ -d $HOME/.phpenv ]]; then
	export	PATH="$HOME/.phpenv/bin:$HOME/.phpenv/shims:$PATH"
fi

php-fpm の利用

php-fpm が $HOME/.phpenv/versions/X.X.X/sbin/php-fpm にインストールされるが、
phpenv 内で使うpathは .phpenv/versions/X.X.X/bin 内のみ
ここに sbin を追加するのが面倒くさかったので ad hoc に対応

% cd $HOME/.phpenv/shims 
% cp php php-fpm
% cd $HOME/.phpenv/versions/X.X.X/bin
% ln -s php-fpm ../sbin/php-fpm

Reference

phpenv/phpenv
https://github.com/phpenv/phpenv

Homebrew で nginx + PHP + PHP-FPM

Summary

Homebrew を使って、ユーザ権限で nginx, PHP-FPM を動かしたい。

Install

brew tap josegonzalez/php
brew install nginx
brew install php54 --with-mysql --with-fpm --with-intl --with-readline

/usr/local/etc/nginx/nginx.conf

http {
...
	include /usr/local/etc/nginx/conf.d/*.conf;
	include /usr/local/etc/nginx/sites-enabled/*;
}

/usr/local/etc/nginx/sites-available/localhost

server {
	listen       8000;
	server_name  localhost;

	root   /Users/yoshiki/Sites/localhost;
	index index.php index.html index.htm;

	access_log /usr/local/var/log/nginx/localhost/access_log;
	error_log  /usr/local/var/log/nginx/localhost/error_log;

	location / {
		try_files $uri $uri/ $uri.php;
	}

	location ~ \.php$ {
		fastcgi_pass   127.0.0.1:9000;
		fastcgi_index  index.php;
		fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
		include        fastcgi_params;
	}
}

ディレクトリとシンボリックリンクを作成

mkdir -p /usr/local/var/run/nginx
mkdir -p /usr/local/var/log/nginx/localhost

mkdir -p /usr/local/etc/nginx/conf.d
mkdir -p /usr/local/etc/nginx/sites-available
mkdir -p /usr/local/etc/nginx/sites-enabled
ln -s /usr/local/etc/nginx/sites-available/localhost /usr/local/etc/nginx/sites-enabled/localhost

php-fpm.conf

listen = 127.0.0.1:9000
listen.allowed_clients = 127.0.0.1

nginx, PHP-FPMの起動

nginx
/usr/local/sbin/php54-fpm start

nginx, PHP-FPMの停止

nginx -s stop
/usr/local/sbin/php54-fpm stop

PHPでTwitter APIのOAuthを使う方法 - twitteroauth版

Summary

PEARの HTTP_OAuthを利用すると、ソースがゴチャゴチャしていたので、
twitteroauth.php を利用してみる。

Access Token, Access Token Secret を取得

http://www.sdn-project.net/ups/oauth_test.txt
$consumer_key と $consumer_secret を変更してブラウザから実行。

例えば、このようなURLで実行。
http://example.com/oauth_test.php

数字が表示されたらNG。
Twitter アプリケーションの設定を見直す。(http://twitter.com/apps)
Twitter の 「あなたの招待状」を「ブラウザアプリケーション」にしておくこと。
Callback URL に oauth_test.php へのURL (http://example.com/path/to/opauth_test.php) を記載。

Twitterへの投稿

<?php
require_once("path/to/twitteroauth.php");
require_once("path/to/conf.inc.php");

$to = new TwitterOAuth($consumer_key,$consumer_secret,$access_token,$access_token_secret);

$mes = "投稿するメッセージ";

// TwitterへPOSTする。パラメーターは配列に格納する。
// http://apiwiki.twitter.com/Twitter-REST-API-Method:-statuses%C2%A0update
// 他の操作はTwitter APIを参照。
$req = $to->OAuthRequest("https://twitter.com/statuses/update.xml","POST",array("status"=>$mes));

header("Content-Type: application/xml");
echo $req;
?>


conf.inc.php

$consumer_key = "consumer_key";
$consumer_secret = "consumer_secret";
$access_token = "access_token";
$access_token_secret = "access_token_secret";

Reference

GitHub - twitteroauth at master from abraham's twitteroauth
http://github.com/abraham/twitteroauth/tree/master/twitteroauth/

Twitter API Wiki / Twitter API Documentation
http://apiwiki.twitter.com/Twitter-API-Documentation

via

twitterのbotなどでOAuthを使う方法(PHPバージョン) | 星光のつれづれ日記
http://www.hosimitu.com/2009/11/2020-1358.php

PHP+OAuthでTwitter - SDN Project
http://www.sdn-project.net/labo/oauth.html

PHPによるデザインパターン入門 原稿公開

Summary

PHPによるデザインパターン入門は2009-09-14に絶版となり、原稿を公開。

Reference

書籍「PHPによるデザインパターン入門」の原稿テキストを公開します - Do You PHP はてな
http://d.hatena.ne.jp/shimooka/20100301/1267436385

PHPによるデザインパターン入門|サポート|秀和システム
http://www.shuwasystem.co.jp/books/7980/1516-4/1516-4.html

PHPによるデザインパターン入門 - Do You PHP?
http://www.doyouphp.jp/book/book_phpdp.shtml

Google ブックス - PHPによるデザインパターン入門
http://books.google.co.jp/books?id=sXNh4TeQeBIC

PHPでTwitter APIのOAuthを使う方法

Summary

PHPでTwitter APIのOAuthを使う方法。
PEARの HTTP_OAuthを利用する。

1. Twitter での操作
  1-1. Twitter にアプリケーションを登録する。
  1-2. Consumer Key と Consumer secret を取得する。

2. アプリケーションからTwitter APIを利用する。
  2-1. リクエストトークンを取得する。
  2-2. 認証用 URL を取得する。
  2-3. ユーザーから承認を受ける (bot の場合は自分でやる)。
  2-4. アクセストークンを取得する。
  2-5. API にアクセスする。

1-1. Twitter にアプリケーションを登録する。

Register a new application からアプリケーションを登録する。

Application Name from XXXの部分にあたる。日本語も可能。
Description アプリケーションの説明文。
Application Website アプリケーションのウェブサイト。Application Name のリンク先URLを指定する。
Organization アプリケーションを管理する組織名。
Website 組織のウェブサイト。
Application Type Browser を指定すると、ユーザーがアクセス権を承認したあと、 Callbak URL にリダイレクトする。Client を指定した場合は「クライアントソフトに戻ってこのコードを入力してね」と表示される。
Callback URL Application Type を Browser にした場合に入力する。ユーザーがアクセス権を承認した後、この URL にリダイレクトする。サービスの URL が確定してない場合は、仮で入れておくか Application Type を Client にしておいて、後で設定しても良い。
Default Access type アプリケーションに与えられる権限。Read & Write か Read-only か。
Use Twitter for login 自分のアプリケーションで「Sign in with Twitter (Twitter でログイン) 」を利用する場合はチェックを入れる。

1-2. Consumer Key と Consumer secret を取得する。

アプリケーションを登録すると、 Consumer KeyとConsumer secretが取得できます。
こんな感じです。
クリックして拡大

2. アプリケーションからTwitter APIを利用する。

HTTP_Request2 は デフォルトで ssl_verify_peer が true になっている。
デフォルトのまま使うと Twitter と SSL 通信するときに
Unable to connect to ssl://twitter.com:443
のエラーになってしまうため、 ssl_verify_peer を false にして accept

$consumer_key = '[1-2で取得したConsumer key]';
$consumer_secret = '[1-2で取得したConsumer secret]';

include 'HTTP/OAuth/Consumer.php';
$consumer = new HTTP_OAuth_Consumer($consumer_key, $consumer_secret);

$http_request = new HTTP_Request2();
$http_request->setConfig('ssl_verify_peer', false);
$consumer_request = new HTTP_OAuth_Consumer_Request;
$consumer_request->accept($http_request);
$consumer->accept($consumer_request);

session_start();

// リクエストトークン を取得
$callback = '[Twitter に登録した Callback URL]';
$consumer->getRequestToken('https://twitter.com/oauth/request_token', $callback);

$_SESSION['request_token'] = $consumer->getToken();
$_SESSION['request_token_secret'] = $consumer->getTokenSecret();

// 認証用 URL を取得
$auth_url = $consumer->getAuthorizeUrl('https://twitter.com/oauth/authorize');

// アクセストークンを取得する
$verifier = $_GET['oauth_verifier'];
$consumer->setToken($_SESSION['request_token']);
$consumer->setTokenSecret($_SESSION['request_token_secret']);
$consumer->getAccessToken('https://twitter.com/oauth/access_token', $verifier);

$_SESSION['access_token'] = $consumer->getToken();
$_SESSION['access_token_secret'] = $consumer->getTokenSecret();


ここまでで、アクセストークンを取得できる。
ここからは、Access Token, Access Token Secret を利用して Twitter APIにアクセスする。

アクセストークンを利用してAPIにアクセス

$consumer->setToken($_SESSION['access_token']);
$consumer->setTokenSecret($_SESSION['access_token_secret']);

$status = 'つぶやきの内容';
$response = $consumer->sendRequest("https://twitter.com/statuses/update.xml", array('status' => $status), "POST");
echo htmlspecialchars($response->getBody());


Services_Twitter の場合

require_once 'Services/Twitter.php';
require_once 'HTTP/OAuth/Consumer.php';

try {
    $twitter = new Services_Twitter();
    $oauth   = new HTTP_OAuth_Consumer(
       'consumer_key',
       'consumer_secret',
       'auth_token',
       'token_secret');
    $twitter->setOAuth($oauth);

    $msg = $twitter->statuses->update("I'm coding with PEAR right now!");
    print_r($msg);
} catch (Services_Twitter_Exception $e) {
    echo $e->getMessage();
}


Reference

PHPでTwitter APIのOAuthを使う方法まとめ - 頭ん中
http://www.msng.info/archives/2010/01/twitter_api_oauth_with_php.php

Twitter API Wiki / Twitter API Documentation
http://apiwiki.twitter.com/Twitter-API-Documentation

HTTP_OAuth
Net_URL2
HTTP_Request2
Services_Twitter

Twitter bot の作り方

Summary

Twitter botのスクリプト。

以下の動作が可能。
  - 用意した文章を順番に投稿。
  - 用意した文章をランダムに投稿。
  - reply を受けると、ランダムに文章を返す。
  - 特定の語を含む reply を受けると、特定の文章を返す。

Reference

プログラミングができなくても作れるTwitter botの作り方
http://pha22.net/text/twitterbot.html

Services_Twitter
http://labs.transrain.net/products/services_twitter/

phaのニート日記
http://d.hatena.ne.jp/pha/

PHPMailerでGmailのSMTPを利用する

Summary

PHPMailerでGmailのSMTPを利用してメールを送信する。
ポート465からSMTP over SSLを利用する。

Source

<?php
mb_language("japanese");
mb_internal_encoding("UTF-8");

require("class.phpmailer.php");
$mailer = new PHPMailer();
$mailer->IsSMTP();
$mailer->Host = 'ssl://smtp.gmail.com:465';
$mailer->SMTPAuth = TRUE;
$mailer->Username = 'user@gmail.com';  // Gmailのアカウント名
$mailer->Password = 'gmail_password';  // Gmailのパスワード
$mailer->From     = 'from@gmail.com';  // Fromのメールアドレス
$mailer->FromName = mb_encode_mimeheader(mb_convert_encoding("Fromの名前","JIS","UTF-8"));
$mailer->Subject  = mb_encode_mimeheader(mb_convert_encoding("メールのタイトル","JIS","UTF-8"));
$mailer->Body     = mb_convert_encoding("メールの内容","JIS","UTF-8");
$mailer->AddAddress('friend@example.com'); // 宛先
// $mailer->AddReplyTo($email, $from);

if(!$mailer->Send()) {
   echo "Message was not sent<br/ >";
   echo "Mailer Error: " . $mailer->ErrorInfo;
} else {
   echo "Message has been sent";
}
?>


Reference

tishon.net - Using PHPMailer with Gmail
http://www.tishon.net/index.php/2008/03/21/phpmailer-gmail/

さぼてん - 2009-02-14 - メールフォーム - PHPmailer+xajax
http://saboten009.blogspot.com/2009/02/phpmailerxajax.html

PEAR::MailでGmailのSMTPを利用する

Summary

Pear::MailでGmailのSMTPを利用してメールを送信する。
ポート587からSTARTTLSを利用する。

Source

<?php
mb_language("japanese");
mb_internal_encoding("UTF-8");

require_once 'Mail.php';

$params = array(
  'host'     => 'smtp.gmail.com',
  'port'     => 587,
  'auth'     => true,
  'username' => 'example@gmail.com',
  'password' => 'password',
  'debug'    => true,
);

$headers = array(
  'From'    => 'example@gmail.com',
  'To'      => 'example@gmail.com',
  'Subject' => mb_encode_mimeheader(mb_convert_encoding("メールのタイトル","JIS","UTF-8"))
);

$recipients = 'example@gmail.com';
$body = mb_convert_encoding("メールの内容","JIS","UTF-8");

$smtp = Mail::factory('smtp', $params);
$e = $smtp->send($recipients, $headers, $body);

if ( PEAR::isError($e) ) echo $e->getMessage() . "\n";
?>


追記 [2010-06-15]

http://ap.atmarkit.co.jp/bbs/core/flinux/15247 より

$params = array(
	'host'     => 'tls://smtp.gmail.com',
	'port'     => 465,
	'auth'     => true,
	'username' => 'account', // @より左部分のみ
	'password' => 'password',
	'debug'    => false,
	'protocol'=>'SMTP_AUTH'
);


ぷららの場合
$params = array(
	'host'     => 'secure.plala.or.jp',
	'port'     => 25,
	'auth'     => true,
	'username' => 'account@subdomain.plala.or.jp',
	'password' => 'password',
	'debug'    => true, // false
	'protocol'=>'SMTP_AUTH'
);


Reference

たら風呂 - 2007-04-04 - PEAR::MailでGmailのSMTPを使う
http://d.hatena.ne.jp/taraburo/20070404/1175694545

HTML Purifier - HTMLを許可しつつXSS対策を行えるPHPライブラリ

Usage

$purifier = new HTMLPurifier();
$clean_html = $purifier->purify( $dirty_html );


HTML Purifier Live Demo

http://hp.jpsband.org/live/docs/examples/demo.php

Reference

HTML Purifier - Filter your HTML the standards-compliant way!
http://hp.jpsband.org/

via

phpspot開発日誌 - HTMLを許可しつつXSS対策を行えるPHPライブラリ「HTML Purifier」
http://phpspot.org/blog/archives/2007/03/htmlxssphphtml.html

PHPの文字化け - 5つの誤解と5つの対策

Summary

設定すべき項目は以下.

;; Disable Output Buffering
output_buffering = Off

;; Set HTTP header charset
; default_charset = EUC-JP

;; Set default language to Japanese
mbstring.language = Japanese

;; HTTP input encoding translation is enabled.
mbstring.encoding_translation = off

;; Set HTTP input encoding conversion to auto
mbstring.http_input = pass

;; Convert HTTP output to EUC-JP
mbstring.http_output = pass

;; Set internal encoding to EUC-JP
mbstring.internal_encoding = EUC-JP

;; Do not print invalid characters
mbstring.substitute_character = none

mbstring.detect_order = SJIS,EUC-JP,JIS,UTF-8,ASCII

誤解1: default_charsetはデフォルトの文字コードのことではない.

default_charsetは,出力時にHTTPヘッダとして送信する文字コード名のこと.

default_mimetype = 'text/html'
default_charset = 'utf-8' の場合
header('Content-Type: text/html; charset:utf-8');

が自動的に実行される.

Content-Typeが固定されるため,default_charsetは使用すべきではない.

誤解2: languageパラメータは内部言語のことではない.

languageパラメータは,mb_send_mailを利用した際にのみ使用される.
また,mb_send_mailは文字コードの変換を指定できないため,使用すべきでない.
PEAR::Mailで代替可能.
よって,languageパラメータは実質的に意味をなさない.

誤解3: internal_encodingは内部エンコードのことではない.

internal_encodingはmbstring関数のデフォルトエンコードのこと.
mb_convert_kanaなどで変換元文字コードの指定がない場合に使用される.

変換元文字コードを固定にするため,
internal_encodingはソースコードの文字コードと揃えておくと良い.

誤解4: http_outputを指定しても,自動的に文字コードは変換されない.

http_outputとは,mb_output_handlerが実行された時の出力エンコード.
ob_start("mb_output_handler")

と指定して初めて使われる.
また,http_outputの動作条件は,出力がtext/htmlである必要がある.

誤解5: detect_orderでautoを指定してはいけない.

detect_orderとは,文字コードの自動検出の優先順位のこと.
未指定の場合は,"auto" という値になるが,
"auto" は "ASCII,JIS,UTF-8,EUC-JP,SJIS" に展開される.

マルチバイトを扱う際に,ASCIIが最初にある点が問題.
出力する文字コードを先頭にし,JISやASCIIは最後の方に設定する.

結論

対策1: default_charsetを設定しない.
対策2: mb_send_mailを使用しない.
対策3: internal_encodingをソースコードの文字コードと揃える.
対策4: http_outputを使用しない.
対策5: detect_orderは必ず指定する.

Reference

PHPの文字化けを本気で解決する - ぎじゅっやさん
http://hain.jp/index.php/tech-j/2007/02/13/%EF%BC%B0%EF%BC%A8%EF%BC%B0%E3%81%AE%E6%96%87%E5%AD%97%E5%8C%96%E3%81%91

PHPで画像にWatermark 加工

Summary

二つの画像を合成し,Watermark加工が行なえる.

Source

function emboss($pic1,$patt) {
	header("Content-type: image/png");
	
	$source=imagecreatefromjpeg($pic1);    // Source
	$pattern=imagecreatefromjpeg($patt);    // pattern
	list($width, $height) = getimagesize($pic1);
	list($widthpatt, $heightpatt) = getimagesize($patt);
	$new_width=$width;
	$new_height=$width/$widthpatt*$heightpatt;
	if($new_height>$height){
		$offset=intval(($new_height-$height)/2);
	}
	elseif($new_height<$height){
		$offset=intval(($new_height-$height)/2);
	}
	else{
		$offset=0;
	}
	
	$image_p = imagecreatetruecolor($new_width, $new_height);
	$pattern = imagecreatefromjpeg($patt);
	imagecopyresampled($image_p, $pattern, 0, 0, 0, 0, $new_width, $new_height, $widthpatt, $heightpatt);
	
	$im = imagecreatetruecolor($width, $height);   
	
	for($y=0; $y < $height; $y++) {
		for($x=0; $x < $width; $x++) {
			$colors=imagecolorsforindex($source, imagecolorat($source, $x,$y));
			$pattern_color=imagecolorsforindex($image_p, imagecolorat($image_p, $x,($y+$offset)));
			//changes brightness depending on luminance
			if(($y+$offset+1)>0 &&($y+$offset)<($new_height-1)){
				$brightness=abs(($pattern_color['red']*50/255)-50);
				if($pattern_color['red']<150){
					$change=true;}
				else{
					$change=false;
					$tally=0;
				}
				if($change&&$tally<2){
					$highlight=1.8;
					$tally++;
				}
				else{
					$highlight=1;
				}
				$brightness = $brightness * $highlight;
			}
			else{
				$brightness=0;
			}
			$r=(($colors['red']+$brightness)>255)? 255 : ($colors['red']+$brightness);
			$g=(($colors['green']+$brightness)>255)? 255 : ($colors['green']+$brightness);
			$b=(($colors['blue']+$brightness)>255)? 255 : ($colors['blue']+$brightness);
			
			$test=imagecolorallocate($im, $r,$g,$b);
			imagesetpixel($im,$x, $y, $test);
		}
	}
	imagepng($im);
	imagedestroy($im);
}
emboss("me.jpg","patternsq.jpg");
//emboss("magic800.jpg","patternsq.jpg");
//emboss("crop.jpg","patternsq.jpg");


<img src="emboss.php" />


Reference

http://www.ckdog.co.uk/php/imgtests/emboss.phps

Watermarking JPEG and PNG Images with PHP and GD2
http://koivi.com/php-gd-image-watermark/

via

Merge images / add logo - PHP
http://www.thescripts.com/forum/thread121386.html

PHPでオーディオ読み上げCAPTCHAを実現

Summary

function joinwavs($wavs){
    $fields = join('/',array( 'H8ChunkID', 'VChunkSize', 'H8Format',
        'H8Subchunk1ID', 'VSubchunk1Size',
        'vAudioFormat', 'vNumChannels', 'VSampleRate',
        'VByteRate', 'vBlockAlign', 'vBitsPerSample' ));
    $data = '';
    foreach($wavs as $wav){
        $fp     = fopen($wav,'rb');
        $header = fread($fp,36);
        $info   = unpack($fields,$header);
        // read optional extra stuff
        if($info['Subchunk1Size'] > 16){
            $header .= fread($fp,($info['Subchunk1Size']-16));
        }
        // read SubChunk2ID
        $header .= fread($fp,4);
        // read Subchunk2Size
        $size  = unpack('vsize',fread($fp, 4));
        $size  = $size['size'];
        // read data
        $data .= fread($fp,$size);
    }
    return $header.pack('V',strlen($data)).$data;
}


Usage

joinwavs(array("1st.wav","2nd.wav","3rd.wav"));


Reference

splitbrain.org - Joining .WAVs with PHP
http://www.splitbrain.org/blog/2006-11/15-joining_wavs_with_php

Index of /audio
http://bartok.wizbit.net/audio/

via

phpspot開発日誌 - 2006-12-01 - PHPでオーディオ読み上げCAPTCHAを実現する方法
http://phpspot.org/blog/archives/2006/12/phpcaptcha_1.html