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

2017年6月8日木曜日

Laravelを Github + Circle CIで CIするまでの参考サイトまとめ


Laravel

前にメモしたリンク集。
floatingdays: 初めてのLaravel参考サイト
floatingdays: Laravelと Vue.jsのチュートリアル参考サイト

MySQL5.6以前だと出るエラーの対処方法。
他にもやり方はあるみたいだけど、ここのが公式?
Laravel 5.4: Specified key was too long error - Laravel News

テストを書くチュートリアル。
Laravel5.3以前の記事のようで、Laravel5.4からはページ遷移やページ内のテストは別途インストールが必要なLaravel Duskの管轄に変わったので、その部分は読み替えが必要。
Laravelでテストコードを書くためのチュートリアル - Qiita


Github

Githubを二要素認証にして、かつ、Githubへのpushをsshではなくhttpsでする方法。
ユーザー名とトークンの入力省略も。
https+アクセストークンを使ってGitHubのアカウントを使い分ける - Qiita

同じく入力省略について、こちらは.netrcに書く方法。
[Git][GitHub]GitHubにPushする際に認証失敗する | DevAchieve


Circle CI

DBまわりの設定。
seedはtest内でやるなら設定ファイルには要らないかも。
CircleCiでLaravelのMySQLを使ったテストを実行する - Qiita

APP_KEYをcircle.ymlに定義しないとエラーになるので書いておく。
エラーメッセージが分かりづらい → "RuntimeException: The only supported ciphers are AES-128-CBC and AES-256-CBC with the correct key lengths."
Laravel アプリケーションを、 Circle CI 経由で AWS ElasticBeanstalk に自動デプロイ - Qiita

Circle CIで使えるPHPのバージョンの参考ページのリンクなど。
PHPプロジェクトにおけるCircle CIの設定 - Qiita

Circle CIからプロジェクトを削除せずにGithubからプロジェクトを削除すると、Circle CI側で削除できなくなる(ずっと読み込み中になる)。
対策は、Githubに同名のプロジェクトを作ればCircle CIから削除できるようになる。
相羽 大輔 (Daisuke AIBA)さんのツイート: "さっきの件、解決。CircleCIに登録したプロジェクトを削除するには「Project Settings > Stop Building on CircleCI」GitHub側で先に消すとCircleCIのプロジェクト設定が触れなくなるので注意。 #kzrb"

2017年5月28日日曜日

初めてのLaravel参考サイト

メモ。

試しにログイン周りを自動生成してみる。
Laravelの標準Authentication(Auth)の動きを調べてみる - Qiita

Specified key was too longというエラーが出たら。
Laravel 5.4: Specified key was too long error - Laravel News

RESTなAPIを作ってみる。微妙に古い?
開発の進め方きめごと - Qiita

次はこれかな。
Laravel 5.4でWeb APIを作る : アシアルブログ

2016年7月16日土曜日

Ansibleや Itamaeで LAMP環境を作る

参考サイトのメモ。
Itamaeの方がいいかな。


Ansible

Ansibleのインストールと、ごく簡単なplaybook
VagrantとAnsibleでCentOSの環境を用意してみる - yk5656 diary

LAMP環境を作成
AnsibleでとりあえずのLAMP環境してみる - yk5656 diary

PHPをインストール
Ansible でインストール (php 5.6) - Qiita



Itamae

Itamaeのインストール、ごく簡単なレシピ、リモートサーバへの適用
Itamae on AWS - Itamae の EC2 へのインストールとレシピ適用 - - Qiita

レシピの書き方など
Chef脱落者が、Itamaeで快適インフラ生活する話 - Qiita
itamae 入門 - Qiita
Itamaeチートシート - Qiita
vagrantとitamaeによるLAMP環境構築 - Qiita
EC2 のインスタンスを Itamae でプロビジョニングした | mizoguche.info

設定値をJSONまたはYAMLに切り出す
第3回 ノード属性で汎用的なレシピを書く:Itamaeが構成管理を仕込みます! ~新進気鋭の国産・構成管理ツール~|gihyo.jp … 技術評論社

公式ドキュメント(英語。詳細は載ってない)
Home · itamae-kitchen/itamae Wiki · GitHub

公式ドキュメントが想像よりそっけないので、詳細は他のブログ等やQiitaで調べながら...。まあシェルコマンドが使えるから汚い書き方でいいならどうにでもなるけど。

2015年2月25日水曜日

Content Security Policy

ApacheでContent Security Policyを設定したメモ。


httpd.confで設定する例。

Header set Content-Security-Policy "default-src 'self'; script-src 'self', 'unsafe-inline', www.example.com"


とりあえずレポートだけ見たい場合の例。
Header set Content-Security-Policy-Report-Only \
"default-src 'none';\
 script-src 'self';\
 object-src 'none';\
 img-src 'self';\
 media-src 'none';\
 frame-src 'none';\
 font-src 'none';\
 connect-src 'none';\
 style-src 'self';\
 report-uri /csp-report.php?v=1"

レポートでどのポリシーに違反したのか見やすくするため、xxxx-srcを全部書いた。
何がエラーになるか分かるように基本厳し目に、使わなそうなのはとりあえずnoneにしている。
report-uriのパラメータ(v=1)は後述。

右辺の書き方については下記参照。
CSP policy directives - Security | MDN

はまりそうなとこだけ書くと、

  • 'none'・'self'・'unsafe-inline'・'unsafe-eval'はシングルクォーテーションも含めて書く必要がある。
  • データスキーム(data:)はコロンも含めて書く。
    (mod_pagespeedを使っていると、気づかない間にデータスキームが使われていたりする。)
    ちなみに、スキームはデータに限らず、"https:"など特定のスキーム限定を指定できるみたい。
  • URLはスキームを省略可(例:www.example.com)。省略した場合、元のページと同じスキームと同じもののみ許可する。
    ポートも同様。
  • URLで別のスキームを許可したい場合、別途記載が必要。
    例:元のページがhttpで、読み込むCSSがhttpsの場合、httpsのURLも書く必要がある。
    ワイルドカードが使えるという説明もあったが、下記のどちらも駄目だった(ブラウザによる?)
  • *://www.example.com
  • *//www.example.com
  • URLのサブドメインはワイルドカード(*)が使える。
    サブドメインをワイルドカードにすると、サブサブ(...略)ドメインまでワイルドに適用される。
    ただしサブドメイン無しには適用されないらしい。


レポートをログに書き出すPHPの例。
<?php
if (!$_GET || $_GET['v'] < 1) {
        exit;
}
$report = json_decode(file_get_contents('php://input'), true);
$log = date('[Y-m-d H:i:s] ') . $_SERVER['HTTP_USER_AGENT'] . ' ';
$log .= var_export($report['csp-report'], true) . "\n";
error_log($log, 3, '/var/log/csp-report.log');

Content-Security-Policy-Report-Onlyの例でreport-uriにパラメータを付けたのは、このPHPの2行目で古いポリシーを無視するため。
ブラウザによってはキャッシュしてしまうようで、古いポリシーに基づき送信してくることがあり、ノイズになるので。
ポリシーを変えたら、パラメータの数字とPHPの2行目の数字を両方インクリメントする。

ログファイルはApacheが書き込めるように権限設定しておく。

(2015/3/2 追記)
logrotateも追加しておく。(phpのlogrotate設定をコピーして作成。)
/var/log/csp-report.log { missingok notifempty}

(追記終わり)

また、ModSecurityを使っている場合はレポートがModSecurityではじかれないように注意。

ログを見ていると、違反URLとして報告される"about"はabout:blankだと思うけど、"asset"って何だろう?



ちなみに、Gmailのポリシーはこんな感じだった。
script-src https://*.talkgadget.google.com 'self' 'unsafe-inline' 'unsafe-eval' https://talkgadget.google.com https://www.googleapis.com https://www-gm-opensocial.googleusercontent.com https://docs.google.com https://www.google.com https://s.ytimg.com https://www.youtube.com https://ssl.google-analytics.com https://apis.google.com https://clients1.google.com https://ssl.gstatic.com https://www.gstatic.com blob:;frame-src https://*.talkgadget.google.com https://www.gstatic.com 'self' https://accounts.google.com https://apis.google.com https://clients6.google.com https://content.googleapis.com https://mail-attachment.googleusercontent.com https://www.google.com https://docs.google.com https://drive.google.com https://*.googleusercontent.com https://feedback.googleusercontent.com https://talkgadget.google.com https://isolated.mail.google.com https://www-gm-opensocial.googleusercontent.com https://plus.google.com https://wallet.google.com https://www.youtube.com https://clients5.google.com https://ci3.googleusercontent.com;object-src https://mail-attachment.googleusercontent.com;report-uri /mail/cspreport

見やすく整形。
script-src
https://*.talkgadget.google.com
'self'
'unsafe-inline'
'unsafe-eval'
https://talkgadget.google.com
https://www.googleapis.com
https://www-gm-opensocial.googleusercontent.com
https://docs.google.com
https://www.google.com
https://s.ytimg.com
https://www.youtube.com
https://ssl.google-analytics.com
https://apis.google.com
https://clients1.google.com
https://ssl.gstatic.com
https://www.gstatic.com
blob:
frame-src
https://*.talkgadget.google.com
https://www.gstatic.com
'self'
https://accounts.google.com
https://apis.google.com
https://clients6.google.com
https://content.googleapis.com
https://mail-attachment.googleusercontent.com
https://www.google.com
https://docs.google.com
https://drive.google.com
https://*.googleusercontent.com
https://feedback.googleusercontent.com
https://talkgadget.google.com
https://isolated.mail.google.com
https://www-gm-opensocial.googleusercontent.com
https://plus.google.com
https://wallet.google.com
https://www.youtube.com
https://clients5.google.com
https://ci3.googleusercontent.com
object-src
https://mail-attachment.googleusercontent.com
report-uri
/mail/cspreport

scriptは'unsafe-inline'も'unsafe-eval'も許可してしまっているが、imgも含めて*を使っていないのは立派。
style等は(defaultも)指定していないが、不要という判断か、指定すると差し障りがあるのか、どちらだろう?

また、1バイトを削るのにもこだわるGoogleがわざわざこれだけの文字列を送信するのは、セキュリティの方が重要だからということだろう。
サブドメインをワイルドカードでまとめれば随分減りそうだが、Googleともなると使っているサブドメインも膨大なので、セキュリティが担保しづらくなるのだろう。
policy-uriを指定してポリシーをXMLでやりとりしてキャッシュを効かせれば総通信料は減りそうだが、柔軟性とのトレードオフか。
report-uriも送信料を増やすが、これ無しは運用的にきっと難しいだろう。

2014年4月20日日曜日

RedHatの yumリポジトリに remiを追加する方法

wgetがなければインストール

yum install wget

yumリポジトリにepel追加(remiの追加の前に必要)
CentOSにEPELリポジトリを追加する - Qiitaを参考に、最新(マイナー)バージョンのURLを調べる
(RedHat5の場合)
rpm -ivh http://ftp-srv2.kddilabs.jp/Linux/distributions/fedora/epel/5/i386/epel-release-5-4.noarch.rpm

yumリポジトリにremi追加
(RedHat5の場合)
rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-5.rpm

epelをデフォルトでは使用しないようにする
vi /etc/yum.repos.d/epel.repo
enabled=0にする
(remiはデフォルトでenabled=0になっている)


remiを使う時にはenabledrepoオプションを付ける
(例)
yum install --enablerepo=epel,remi php


参考:Remi 基本リポジトリで提供されていないパッケージのyumインストール - [yum/Linux [Red Hatなど]] ぺんたん info (きちんとGPGを確認するやり方)

2013年11月15日金曜日

PHP5.5を Amazonの yumリポジトリからインストール

EC2のAmazon Linux AMIでデフォルトのyumリポジトリであるamznリポジトリから、PHP5.5をインストールできるようになった。

$ yum info php55

Loaded plugins: priorities, update-motd, upgrade-helper
amzn-main/latest/primary_db                                                                                                                      | 2.5 MB     00:00    
amzn-updates/latest/primary_db                                                                                                                   | 301 kB     00:00    
mod-pagespeed/primary                                                                                                                            | 4.5 kB     00:00    
mod-pagespeed                                                                                                                                                     28/28
Available Packages
Name        : php55
Arch        : x86_64
Version     : 5.5.5
Release     : 1.55.amzn1
Size        : 2.9 M
Repo        : amzn-updates/latest
Summary     : PHP scripting language for creating dynamic web sites
URL         : http://www.php.net/
License     : PHP and Zend and BSD
Description : PHP is an HTML-embedded scripting language. PHP attempts to make it
            : easy for developers to write dynamically generated web pages. PHP also
            : offers built-in database integration for several commercial and
            : non-commercial database management systems, so writing a
            : database-enabled webpage with PHP is fairly simple. The most common
            : use of PHP coding is probably as a replacement for CGI scripts.
            :
            : The php package contains the module (often referred to as mod_php)
            : which adds support for the PHP language to Apache HTTP Server.



手元のサーバで使ってる拡張(Extension)のPHP5.4から5.5への変更のメモ。

php54-mbstring → php55-mbstring
php54-pdo → php55-pdo
php54-mysql → php55-mysqlnd
php54-pecl-apc → php55-opcache
php54-pecl-xdebug → まだない

5.4に比べてまだ少ないようだ。

2013年7月28日日曜日

PHPのフレームワークの人気を Googleトレンドで比較

世界で人気のPHPフレームワークでGoogle検索されている上位5つはこれ。

 
CodeIgniterの人気がグングン上がって、2010年頃にトップになってそのまま独走してる。ライセンス問題云々の問題は影響がなかったように見える。

また、それを追うようにYiiの人気が上昇し、PHPフレームワーク旧御三家のCake、Symfony、Zendを抜いてしまった。

それにしても2009年にみんな揃ってガクッと落ちてるのはなんだろう?


で、上位5つをの下はこれ。(比較用にZendも入れている。)

Laravelがグググッと上がってきて、Zendを抜くのは時間の問題か。CodeIgniter、Yii、Laravelが新御三家になるのかな。

有望株だったKohanaは伸び悩んでこのまま消えていくのか。意外にもEthnaは細く長く頑張ってる...?日本で人気のFulePHPは、Ethnaに辛うじて勝つ程度という低空飛行


最後に、日本限定で比べると上位5つはこれ。

みんな大好きCakePHP。安定のぶっちぎり。

後は小さくて見辛いが、Fuelがここ2年で他を抜き去って2位になって、このまま伸びそうか?Rails好きな日本人のはずが、Symfonyは落ちてきてCodeIgniterも伸び悩み。


で、ここまで書いてきてなんだけど、Googleトレンドで調べる場合の問題は、普通の単語だとPHPのフレームワークと関係なく検索数が増えてしまうこと。
例えば「Rails」で調べたら、Ruby on Railsと関係ない検索もたくさん含まれてしまうよね?Yiiなんかもどこかの国の言葉で存在してPHPと関係なく調べられてるかもしれないとも思ったけど、グラフの伸びから見るとPHPフレームワークとして検索されてそう。Yiiの強さは、普通名詞の組み合わせではない、かつ、シンプルであることだろう。

逆に、FuelPHPやZend Frameworkは「Fuel」や「Zend」と略した場合の検索がカウントされていないので、過小評価になってしまう。
「Zend Controller」「Fuel Exception」など他の言葉との組み合わせでたくさん検索されてそうだが、Googleトレンドではそこまで調べられないので。

それでも日本では圧勝のCakePHPは、それだけ凄いんだろうけど...。

2012年4月26日木曜日

PHPExcelで使えない数式

PHPExcel(バージョンはちょっと古い1.7.4)でExcel5形式でExcelを書きだす時に、セルに書いても空白になってしまう(罫線すら付かない...)計算式(formula)のメモ。

下記の数式をPHPExcelで使おうとすると、セルに何も出力されないので注意。


SUFIFS()
Excel2007からの数式なので仕方ないんだろう。


SUMPRODUCT()
下記のようにSUMIFSの代わりに使おうとすると空白になる。

=SUMPRODUCT((A1:A5='hoge')*(B1:B5='hage'),C1:C5)


SUMIF()
下記のように条件のところを他のセル値の参照にすると空白になる。
=SUMIF(A1:A5,B1,C1:C5)


空白になるのは、PHPExcelの内部的には数式のパースエラー時にExceptionを投げてて、それをcatchしてそのまま処理を続行してるからみたい。


(おまけ)
&が使えない
「=A1&"@"&B1」と書いたら「=A1」と出力される。
対策としては、下記のようにCONCATENATE()を使えばOK。
=CONCATENATE(A1,"@",B1)

2011年11月14日月曜日

PDOでテーブルの列名を全て取得する方法

テーブルの列名を取得するには、MySQLならDESCRIBEで簡単にできるが、PostgreSQLだとpg_attributeカタログから取得しないといけないらしい。

でもPDOを使えばMySQLでもPostgreSQLでも取得できた。

$pdo = new PDO("$driver:dbname=$db", $user, $password);
$pdoStatement = $pdo->query("SELECT * FROM $table_name LIMIT 0");

$columns = array();

for ($i = 0; $i < $pdoStatement->columnCount(); $i++) {
    $meta = $pdoStatement->getColumnMeta($i);
    $columns[] = $meta['name'];
}

var_dump($columns);

もしテーブルに1行以上データがあることが保証されているなら普通に1行SELECTして連想配列の列名見れば済む話だが、データなしでも動くようにしたらこうなった。


ただし、PDOStatement->getColumnMeta()のマニュアルを見ると、
この関数は、 実験的 なものです。この関数の動作・ 名前・その他ドキュメントに書かれている事項は、予告なく、将来的な PHP のリリースにおいて変更される可能性があります。 この関数は自己責任で使用してください。
PDO ドライバの全てが PDOStatement::getColumnMeta(). をサポートしているわけではありません。
と書いてあり、PHPやDBのバージョンによっては上手く動かないかもしれないが、とりあえず手元の環境では動いた。


これでPHPでO/R Mapperを作りたい人も安心だ。

2011年9月30日金曜日

preg_match()の$は末尾に改行があってもマッチする


$は最後に改行があってもマッチする。(ただし、マッチした結果には改行は含まれない。)

preg_match('/^aaa$/', "aaa\n", $match);
echo '<pre>"', $match[0], '"</pre>';

"aaa"


$の代わりに"\z"(バックスラッシュ+小文字のz)にすれば、改行があるとマッチしない。
preg_match('/^aaa\z/', "aaa\n", $match);
echo '<pre>"', $match[0], '"</pre>';

""


Zが大文字だと$と同様に改行があってもマッチするので注意。
preg_match('/^aaa\Z/', "aaa\n", $match);
echo '<pre>"', $match[0], '"</pre>';

"aaa"


$は改行の後ろに何かあればマッチしない。
preg_match('/^aaa$/', "aaa\n ", $match);
echo '<pre>"', $match[0], '"</pre>';

""


例えそれが改行でも。
preg_match('/^aaa$/', "aaa\n\n", $match);
echo '<pre>"', $match[0], '"</pre>';

""


マッチした結果に改行まで含ませるとこうなる。
preg_match('/^aaa\n\z/', "aaa\n", $match);
echo '<pre>"', $match[0], '"</pre>';

"aaa
"


参考

2011年9月29日木曜日

PHPExcelで PDFが文字化けする問題の解決方法


PHPExcelではExcelの他にPDFも出力できる。

$writer = PHPExcel_IOFactory::createWriter($xls, "PDF");
$writer->save($path);
しかし、これだとPDFで日本語を出力しようとすると文字化けする。

文字化けを回避するには、フォントをセットする必要がある。
$writer = PHPExcel_IOFactory::createWriter($xls, "PDF");
$writer->SetFont('arialunicid0-japanese');
$writer->save($path);
これができるようになったのはわりと最近のようだ。(参考:PHPExcel - phpexcel - View Issue #11919: Can't set font on writing PDF

ただし環境によってはこれでも見られないらしい。(参考:PHPExcel の PDF出力で日本語文字化け2 携帯ビューア - PC・通信メモ


また、PHPExcelで作るPDFはExcelとして出力した場合と比べていろいろ違う(罫線とか数値フォーマットとか横幅とか)ので、綺麗に出すにはPDF用にいろいろ工夫しないといけないようだ。


参考

2011年5月9日月曜日

Webベースのテキストエディタ ecoderのカスタマイズメモ

WebブラウザでPHP等を編集できるオンラインテキストエディタのecoderのセットアップ時の変更箇所のメモ。


前提知識

  • $_SESSION['live'] == 0 になるのはサーバがlocalhostの場合


変更箇所
  • /code.php
    • 一通り関係しそうな設定を変更する
  • /code/base/server.php
    • $_SESSION['google']を0にすると初期表示ページのAdSenseが非表示になる
  • /code/tree/type.php
    • 表示対象の拡張子を追加する場合は、if文の該当箇所に追加する
  • その他
    • .htaccessを使わない場合は、Noticeを抑制するために index.php の先頭あたりに下記を入れる?
      error_reporting(E_ALL ^ E_NOTICE);
    • ただしphp.iniでE_STRICTを有効にしている場合はStrictエラーが出てしまうことがある。
      PHPのパース時に出るので、PHP内でerror_reportingを変更してもこれには効かない。(参考:PHP: error_reporting - Manual
(2012/04/18 追記)
  • /code/logs/analytics.php
    • Google Analyticsの読み込みをコメントアウトする
ちなみに上記はversion 0.4.9の話。今の最新は0.4.10みたい。
(追記 終わり)

2011年4月11日月曜日

PHPのエラーメッセージのマニュアルへのリンクを変更する

PHPのfunctionでエラーが発生すると、エラーメッセージが該当するfunctionへのリンクになる場合がある。

array_merge('foo');

Warning: array_merge() [function.array-merge]: Argument #1 is not an array in /var/www/html/test.php on line 2

このリンクのリンク先は、デフォルトでは有効なURLではない。

php.ini等でマニュアルの場所を指定してあげると、マニュアルの該当functionへのリンクにすることができる。
ini_set('docref_root', 'http://jp.php.net/manual/ja/');
array_merge('foo');

Warning: array_merge() [function.array-merge]: Argument #1 is not an array in /var/www/html/test.php on line 3

このエラーメッセージをブラウザで見る場合は便利な場合もあるかもしれないが、このエラーメッセージはそのままエラーログにも出力されるので、エラーログが余計に増えてしまう。
(エラーログ上のマニュアルのURLを使うなら便利かもしれないが。)
このリンクを抑制するにはhtml_errorsをOffにする。
ini_set('html_errors', false);
array_merge('foo');

Warning: array_merge(): Argument #1 is not an array in /var/www/html/test.php on line 3

すっきりしたね。


参考:PHP: 実行時設定 - Manual

2011年4月4日月曜日

PHPの crypt()で SHA2のハッシュを生成する

PHPのcrypt()を使うと、パスワードで使うのに便利な文字列を生成できる。(説明のために3色に色付けした。)

$str = crypt('test'); => $1$X0zFikbH$z9QaylK29Eu4VQajK6PKw0

生成された文字列は$記号で区切られた3つの部分から構成されている。
  • $1$ → MD5でハッシュを生成したことを表す
  • X0zFikbH → ハッシュ生成に使ったsalt。crypt()の第2引数でsaltを指定した場合は指定したsaltが使われるが、指定しないと自動生成されたsaltが使われる
  • z9QaylK29Eu4VQajK6PKw0 → 生成されたハッシュ


この文字列を使ってパスワードが正しいか確認したい場合、下記のようにcrypt()だけで確認できる。
if (crypt($input_password, $str) === $str) {
    echo 'OK';
} else {
    echo 'NG';
}

crypt()の第2引数としてcrypt()で生成した文字列を渡すと、saltの部分だけを取り出してsaltとして使ってくれる(後ろのハッシュ値は無視される)ので、わざわざsaltだけを取り出す必要はない。(便利だが一見しただけでは分かり辛い...)


crypt()の第2引数でsaltを指定しなかった場合のハッシュアルゴリズムは、手元の環境ではMD5が使われた。
第2引数でsaltを指定する場合は、saltの前に付ける文字列によって下記のようにハッシュアルゴリズムを指定することができる。
  • 何も付けない → DES(拡張DESではなく標準DES?)
  • $1$ → MD5
  • $2a$ → Blowfish
  • $5$ → SHA-256 (PHP 5.3.2以降)
  • $6$ → SHA-512 (PHP 5.3.2以降)

上記のように、PHP 5.3.2以降ではcrypt()でSHA2(SHA-256/512)が使えるようになった。
(既に脆弱性が発見されているSHA-1はスキップされたようだ。)

BlowfishやSHA-256/512を使う場合は自動生成のsaltが使えないので、文字列生成時にはsaltを渡してあげないといけない。
saltは推測可能な値でも構わない(元の文字列が同じでもハッシュが異なるようにすることに意味がある)ので、uniqid()あたりでいいんじゃないかな。
$str = crypt('test', '$6$' . uniqid());


参考:PHP: crypt - Manual


関連記事

2011年4月1日金曜日

PHPで 簡単にGET / POSTできるように file_get_contents()を拡張する

file_get_contents()は便利だが、POSTとかエラー対応とかは少し面倒なので、手軽に使えるようにラップしてみた。
PHPのバージョンは5.2.10以降または5.3.0以降が対象。

function file_http(
    $url,
    $params = null,    //パラメータがあれば配列で渡す
    $method = 'GET',    //GET or POST
    &$status = null,    //参照渡しでレスポンスのHTTP Status Codeを返す
    &$http_response_header = null,    //参照渡しでレスポンスのHTTP Headerの配列を返す
    $request_header = array()    //追加したいリクエストのHTTP Headerがあれば
) {
  
    $opt = array(
        'method' => $method,
        'header' => (array)$request_header,    //PHP 5.2.10 / 5.3.0 以降は配列でもOK
        'ignore_errors' => true,    //PHP 5.2.10 / 5.3.0 以降で有効
    );
  
    if ($params) {
        $query_string = http_build_query($params);
      
        if ($method === 'GET') {
            $url .= '?' . $query_string;
        } else {    //POSTの場合
            $opt['header'][] = 'Content-type: application/x-www-form-urlencoded';
            $opt['content'] = $query_string;
        }
    }
  
    $res = file_get_contents($url, false, stream_context_create(array('http' => $opt)));
  
    //レスポンスのHTTP Headerは$http_response_headerにセットされている
    if (is_array($http_response_header)) {
        preg_match('@^HTTP/1\\.. ([0-9]{3}) @i', $http_response_header[0], $matches);
        $status = $matches[1];
    }
  
    return $res;
}

使用例
$res = file_http(
    'http://localhost/test.php',
    array('foo' => 'テスト'),
    'POST',
    $status,
    $responseHeaders,
    array('User-Agent: ゆーざーえーじぇんと', 'Referer: りふぁら')    // 1つだけの場合は文字列でもOK
);

echo $status;    // => "200"
var_dump($responseHeaders);

実際に使う場合には結果の判断等でレスポンスのHTTPステータスコードが欲しい場合があるので、パラメータの参照渡しで取得できるようにした。
そしてステータスコード以外のHTTP Headerを参照したいケースもあるので、これも参照渡しで配列として取得できるようにした。

また、ignore_errorsを指定することにより、レスポンスのHTTPステータスコードが400以上でもWarningを出さない、かつレスポンスのBodyを取得できるようにした。(参考:[メモ] PHPのfile_get_contentsを、HTTPリクエストに使うときのTIPS ::ハブろぐ
ただしホスト名の名前解決ができない場合はその手前でWarningが出てしまうので、PHPで URLのホスト名(ドメイン)が存在するかチェックする方法のような対応が必要。


以下は余談。
普段は変数名等はcamelCaseにするのだが、$http_response_header等に引っ張られてアンダーバー繋ぎにしてみた。
関数名は、
  • http_request
  • http_get
  • httpRequest
などを考えたのだが、どれもPECLで既に使われているので諦めた。

2011年3月25日金曜日

プログラム言語とフレームワークのオンラインマニュアル29選


Webで公開されている、プログラム言語・フレームワーク・DBのマニュアル(リファレンス)サイトへのリンクをまとめてみた。
選んだ基準は、できるだけ日本語で、なるべく分かりやすいこと。それを満たすなら公式リファレンスより非公式のものを優先している。



JavaScriptのマニュアルは他にも色々あり、使う人のレベルや用途によってどれが使いやすいかが変わってくると思うが、昔大変参考にさせて頂いた杜甫々版を挙げておいた。

Python、Perl、Objective-Cについては公式/準公式のリンクを書いたが、有志によるマニュアルでもっと良いものがあるのかもしれない。(これらの言語はあまり使わないので知らない。)

2011年3月24日木曜日

PHPで URLのホスト名(ドメイン)が存在するかチェックする方法

PHPでURLのホスト名(ドメイン)が有効なものかどうかをチェックする例。
file_get_contents()でignore_errorsをtrueにしてstream_context_create()してもホスト名が名前解決できなくてWarningが出てしまう問題に悩んでいる場合などにどうぞ。

$url = 'http://www.example.com/path';

$array = parse_url($url);

if ($array && $array['host']) {
    $ip = getHostByName($array['host']);
    $long = ip2long($ip);
  
    if ($long === false || $ip !== long2ip($long)) {
        echo '名前解決できなかった';
    } else {
        echo 'OK';
    }
} else {
    echo 'URLが正しくない';
}

DNSで名前解決できたらOKにしている。
また、ホスト名がIPアドレス(IPv4)の場合はどんなIPでも(たとえ255.255.255.255でも)OKにしている。

ip2long()で得た値をlong2ip()でIPアドレスに戻してチェックしているのは、ip2long()が「0.0.256」のような値を「0.0.1.0」などと解釈してしまうため。
参考:(IPv4) インターネットプロトコルドット表記のアドレスを、適当なアドレスを有する文字列に変換する - PHP 5.3 日本語マニュアル
ip2long() を、それ単体で IP の検証に利用するべきではありません。long2ip() と組み合わせて利用します。

<?php
// IP が有効であることを確認します。また、不完全な形式の IP を
// 以下で示すような正しい形式(ドットで 4 つに区切られている)に変換します。
$ip = long2ip(ip2long("127.0.0.1")); // "127.0.0.1"
$ip = long2ip(ip2long("10.0.0")); // "10.0.0.0"
$ip = long2ip(ip2long("10.0.256")); // "10.0.1.0"
?>


これはIPv4を使ってるけど、今後IPv6が普及したら...その時までにPHPも進化しているでしょう。


参考

2011年3月23日水曜日

PHPの SimpleXMLを配列に変換する

シンプルなXMLなら、SimpleXMLElementオブジェクトをarrayにキャストするだけで連想配列に変換できる。

$xml = '<?xml version="1.0" ?>
<root>
<test>TEST1</test>
<test>TEST2</test>
<attr trouble="MISSING">WHY?</attr>
</root>';

$sx = simplexml_load_string($xml);

var_dump((array)$sx);

array(2) {
  ["test"]=>
  array(2) {
    [0]=>
    string(5) "TEST1"
    [1]=>
    string(5) "TEST2"
  }
  ["attr"]=>
  string(4) "WHY?"
}

同じ要素名の要素がある場合(上記の例ではtest要素)、まとめて添字が0から始まる配列になる。
しかし、なぜか属性とテキストノードの両方がある要素の属性(上記の例ではattr要素のtrouble="MISSING")が無視される。

また、子要素や属性のあるXMLの場合、配列の中まで再帰的にキャストしていないのでSimpleXMLElementのままになってしまう。
$xml = '<?xml version="1.0" ?>
<root>
<parent>
<child>MUSUKO</child>
</parent>
<attr foo="FOO" bar="BAR" />
</root>';

$sx = simplexml_load_string($xml);

var_dump((array)$sx);

array(2) {
  ["parent"]=>
  object(SimpleXMLElement)#3 (1) {
    ["child"]=>
    string(6) "MUSUKO"
  }
  ["attr"]=>
  object(SimpleXMLElement)#2 (1) {
    ["@attributes"]=>
    array(2) {
      ["foo"]=>
      string(3) "FOO"
      ["bar"]=>
      string(3) "BAR"
    }
  }
}




これに対して、PHPマニュアルのコメント欄に一発で配列に変換する方法が書いてあった。
$xml = '<?xml version="1.0" ?>
<root>
<parent>
<child>MUSUKO</child>
</parent>
<attr foo="FOO" bar="BAR" />
</root>';

$sx = simplexml_load_string($xml);

var_dump(json_decode(json_encode($sx), true));

array(2) {
  ["parent"]=>
  array(1) {
    ["child"]=>
    string(6) "MUSUKO"
  }
  ["attr"]=>
  array(1) {
    ["@attributes"]=>
    array(2) {
      ["foo"]=>
      string(3) "FOO"
      ["bar"]=>
      string(3) "BAR"
    }
  }
}



json_decode()の第2引数(戻り値を連想配列にするかどうか)をtrueにするのがポイント。
属性は@attributesというKEYの連想配列に格納される。


しかし、属性とテキストノードの両方がある要素の属性が無視される問題は、このjson_encode/json_decodeを使った方法でも発症する。
$xml = '<?xml version="1.0" ?>
<root>
<attr trouble="MISSING">WHY?</attr>
</root>';

$sx = simplexml_load_string($xml);

var_dump(json_decode(json_encode($sx), true));

array(1) {
  ["attr"]=>
  string(4) "WHY?"
}

Why?
まあでも属性値がないことが分かっているXMLならこれで使えそう。(後から属性値を使いたいということになったら大変だけど。)

きちんとやりたいなら、SimpleXMLで取得したオブジェクトを属性も含めて配列に変換 | とりさんのソフト屋さんのやり方がスマートで良さそう。

2011年3月18日金曜日

AWS CloudFormationで PHP Hello World Applicationを作成してみた

AWS(Amazon Web Services)のCloudFormationの「PHP Hello World Application」に関する情報があまりないので試してみた。


まずはAWS Management Consoleから「PHP Hello World Application + SSH enabled」のstackを作成。
場所はAsia/Pacific 東京リージョンを選択できた。
インスタンスタイプはMicroインスタンス、OperatorEmailには自分のメールアドレスを記入した。


しばらくすると、こんなのが作成された。

  • S3
    • 空のバケットが作成された(バックアップ用?)
  • EC2
    • Root Device Typeがebsのインスタンスが1つ作成された
    • EBSのCapacityは8GiB
    • Security Groupが1つ作成された
      • SSHとHTTP(ポート番号は8888)のポートで、ともにIPアドレス制限無し
    • Load Balancerが起動した
      • 80番ポートを待ち受けてインスタンスの8888番ポートに向ける
    • Elastic IPは作成されなかった
  • CloudWatch
    • Alarmが3つ作成された
      • RequestLatencyAlarmHigh
      • CPUAlarmHigh
      • TooManyUnhealthyHostsAlarm
    • 閾値に達したら登録したメールアドレスにメールで知らせてくれるようだ
  • CloudFormation
    • stackが1つ作成された(そりゃそうだ)
  • RDS
    • DB Instanceが1つ作成された
      • DB Engine Versionは5.1.50
      • DB Instance Classはdb.m1.small
      • DB Storageは5GiB
      • Backup Windowは15:00~15:30(日本時間?)
      • Maintenance Windowは日曜14:00~14:30(これも日本時間?)
    • DB Security Groupが1つ作成された
      • 上記のEC2 Security Groupが適用されている
    • DB Parameter Groupのcharacter_set関連は「engine-default」になっているが、UTF-8使えるのかな?
  • SNS
    • CloudWatchのメール通知用のTopicが1つ作成された


EC2のLoadBalancerのドメインにHTTPでアクセスすると、Wellcomeメッセージとともにphpinfoが表示された。
phpinfoによるとバージョンは下記の通り。
  • Apache : 2.2.16
  • PHP : 5.3.3

SSHでアクセス(SSHのログインユーザーはrootでなく"ec2-user"なので注意。"ec2-user"はsudoができる)してみると、/var/www/html の中には index.php しかなかった。
ユーザー"ec2-user"のviはPHPのソースがハイライトされて見やすい。(少し目がチカチカするが。)

PHP拡張については主なものは入っているが、mbstringが入っていない。
yumで入れたら普通にインストールできた。
sudo yum install php-mbstring

mbstringを有効にするためにApacheを再起動。
すると、アクセスできなくなった。EC2のLoadBalancerからインスタンスが外れている。
SNSからのアラートメールもいくつも送られてきてる。

調べてみると、httpd.confでポート番号が80になっていた
8888に変更して再起動。

これでアクセスできるようになった。mbstringも使えるようになった。


使い終わったら、AWS Management ConsoleでCloudFormationのstackを削除。
するとCloudFormationが作った一連のものをきれいに削除してくれた。
例外はS3で、S3だけはバケットが残っていた。


あとこれは今回の調査に直接関係ないが、AWS Management ConsoleのS3とEC2が重くなった気がする。(この前の改善の影響?)


結論
ささっとPHP実行環境を作りたいなら、これもありかもしれないと思った。
RDSを使いたいかどうかは状況によるけど、CloudWatchとかSNSの設定が楽なのは便利そう。

ブログ アーカイブ

tags