[ カテゴリー » Programぽいの » PHP ]

PHPのshuffle()が連想配列では使えない件について

↓こんな連想配列があったとして、
$AmericanLeagueEastDivisionTeams = array(
    'BAL' => array('city' => 'Baltimore', 'name' => 'Orioles'),
    'BOS' => array('city' => 'Boston', 'name' => 'Red Sox'),
    'NYY' => array('city' => 'New York', 'name' => 'Yankees'),
    'TB' => array('city' => 'Tampa Bay', 'name' => 'Rays'),
    'TOR' => array('city' => 'Toronto', 'name' => 'Blue Jays'),
);

shuffle()してみると…
shuffle($AmericanLeagueEastDivisionTeams);
var_export($AmericanLeagueEastDivisionTeams);
↓結果(見やすいように整形済み)
array (
  0 => array ('city' => 'Boston', 'name' => 'Red Sox'),
  1 => array ('city' => 'Toronto', 'name' => 'Blue Jays'),
  2 => array ('city' => 'New York', 'name' => 'Yankees'),
  3 => array ('city' => 'Tampa Bay', 'name' => 'Rays'),
  4 => array ('city' => 'Baltimore', 'name' => 'Orioles')
)
はい。キーが破棄されて、数字キーに割り当て直されちゃいます。

じゃあ、array_rand()でランダム順のキーを取得しよう、と思った。
$len = count($AmericanLeagueEastDivisionTeams);
$abbrs = array_rand($AmericanLeagueEastDivisionTeams, $len);
var_export($abbrs);
↓結果
array (
  0 => 'BAL',
  1 => 'BOS',
  2 => 'NYY',
  3 => 'TB',
  4 => 'TOR',
)
よし、この「キーがランダム順に入った配列」を使おう。
…あれ?並べ変わってなくね?
たまたまかな(^o^;

再実行→やっぱりおんなじ→再々実行→やっぱりおんなじ→(無限ループ)
全件取得する場合は並べ換えて紅の豚?
マニュアルに書いといてよ。そんなこと。。

まあ、array_keys()を使ってそれをshuffle()すれば同じ事はできるか。
$abbrs = array_keys($AmericanLeagueEastDivisionTeams);
shuffle($abbrs);
var_export($abbrs);
↓結果
array (
  0 => 'NYY',
  1 => 'BOS',
  2 => 'TB',
  3 => 'BAL',
  4 => 'TOR',
)
当然ながらうまくいく。再実行すればまた並び変わる。

せっかくだから、関数化しておくか。
PHPオリジナルの命名則にあわせて、ashuffle()と名付ける(※)。
オリジナルのshuffle()が並べ替えが成功したかどうかを返しているので、とりあえずtrueを返すことにする。
function ashuffle(&$array) {
    $keys = array_keys($array);
    shuffle($keys);

    $res = array();
    for ($i = 0, $_l = count($keys); $i < $_l; $i++) {
        $res[$keys[$i]] = $array[$keys[$i]];
    }

    $array = $res;
    return true;
}

これで、
ashuffle($AmericanLeagueEastDivisionTeams);

$rank = 0;
foreach ($AmericanLeagueEastDivisionTeams as $abbr => $team) {
    printf("%d: %s %s (%s)¥n", ++$rank, $team['city'], $team['name'], $abbr);
}
↓結果

1: New York Yankees (NYY)
2: Baltimore Orioles (BAL)
3: Tampa Bay Rays (TB)
4: Boston Red Sox (BOS)
5: Toronto Blue Jays (TOR)
成功。


※:蛇足。
この記事を書く時に、そういえば、もうすでに誰かが作ってるよな。"ashuffle()"って名前で。
っと思ってググってみたら、どうやら無いみたい。。
ってことは、このページがひっかかるようになるんだ。ウシシ( ̄ー ̄)

PHP

— posted by たか at 12:12 am   pingTrackBack [0]

PHPSESSIDの無限ループ

Cookieが無効な環境のために、PHPのセッションID(デフォルトで"PHPSESSID")をURLに(クエリストリングとして)くっつけてリダイレクトする。
ということはモバイル向けサービスで良くあることだと思う。
んで、ローカルでテスト中、件の無限ループが発生した。
apacheのアクセスログを見ると、
hoge.php?foo=var
hoge.php?foo=var&amp;PHPSESSID=(SSID1)
hoge.php?foo=var&amp;amp;PHPSESSID=(SSID1)&amp;PHPSESSID=(SSID2)
...
hoge.php?foo=var&amp;amp;amp;amp;amp;amp;PHPSESSID=(SSID1)&amp;amp;amp;amp;amp;PHPSESSID=(SSID2)&amp;amp;amp;amp;PHPSESSID=(SSID3)&amp;amp;amp;PHPSESSID=(SSID4)&amp;amp;PHPSESSID=(SSID5)&amp;PHPSESSID=(SSID6)
...

すなわち、
hoge.php?foo=var
にアクセスがあって、セッションIDがついてないのでつけましょう。そしてリダイレクト。
hoge.php?foo=var&amp;PHPSESSID=(SSID1)
おやおや、セッションIDがついてないのでつけましょう。そしてリダイレクト。
hoge.php?foo=var&amp;amp;PHPSESSID=(SSID1)&amp;PHPSESSID=(SSID2)
っという具合に、無限に繰り返し、URL長エラーになるまで繰り返してた。っということ。

原因は、"&"であるべきセパレータが"&amp;"になっていること。
"PHPSESSID"のつもりが、"amp;PHPSESSID"になっちゃったわけだ。

さて、誰の仕業だろう?
プログラムで発行しているときにやっちまった?
Net_URLを使ってるから、この子のせい?
PHPが自動で付けたもの?
Apacheが変換した?

とまあ、色々調べてしまったよ。
結論を言うのは簡単だなぁ。。
その結論とは、
PHPの設定がヘンだった。それと、PHPの設定をNet_URLが忠実に読み込んでいたから。

Net_URL::getQueryString()で、クエリストリングのセパレータを、ini_get('arg_separator.output')で取ってきてます。

んで、オイラのWindowsなxampp環境では、php.iniファイルで下記の通り指定していた。
arg_separator.output = "&amp;"


むむむ。なんでこんなことしたんだっけ?
はい。これをコメントアウトして、サービスを再起動すると、…ちゃんと動いた。


以下、苦労した原因を箇条書きしておく。繰り返さないように(´・ω・`)
・デバッグ用にリダイレクトURLをHTML出力してみたわけだが、<textarea>タグ内ならば生のソースが表示されるハズ、と初歩的な勘違い
  → "&"と表示されて、うーん、ここまでは上手く行ってるのに…と誤解。実際は"&amp;"だったのに
・php.iniを書き換えたら即時適用されそうな気がしていた
  → apacheを最起動しないと読まないよ。Windowsの場合サービスの再起動が必要。
・php.iniを変更するなら、なぜそうしたかメモっておこうよ。。
・グーグル先生を過信し過ぎ(←あえて冗長表現してみた)。

PHP

— posted by たか at 03:27 pm   pingTrackBack [0]

perlでphpでいうところのfile_get_contentsを

なぜかperlを使わなければならなくなり…。
phpだったらfile_get_contentsなんだけどなぁ…。という訳で。

Webページの取得Link
use LWP::Simple;
my $cont = get('http://example.com/');
これで行けたっ!
useってなに?な状態だけど、魂塊(※)はそれでヨシ!もういいよ。
三項にならなくてゴメンナサイ。

※:今回を無理に誤変換した

ついでに書いておくと、Basic認証が必要な場合。
use LWP::Simple;
my $cont = get('http://example.com/gw.php?n=2');
if (!$cont) {
  $cont = get('http://id:pw@example.com/test/gw.php?n=2');
}
そう、サブディレクトリでテストしていて、そっちにはBasic認証かかってやがる。って場合に上記が使える。
さらに言うと、こちらはPHPで、あちらはPerlな*.cgiで、それぞれ開発してて、
いざ、ガッチャンコ!
…できねーよ。。
ナレーション『説明しよう。PHPさんとCGIさんは仲が悪くて共存できないのである。
ってな場合に、こんな風にすると良いんじゃないかと。
  • PHP側では、必要な情報を抽出してパーツとして出力するのみ
  • Perl側では、PHPにWebアクセスしてパーツを取得、表示したいところに埋め込む。
もちろん役割分担を逆にしても可。よきかなよきかな(by 水鏡先生@横山三国志)。


さて、もっと愚痴るか(^^;
PerlなあちらさんLink
昨今超スタンダードなPerl言語の勉強をする機会を提供して下さり、誠にありがとうございました。
感涙をこらえることができません。
厚かましいとは存じますが、ひとつご質問がございます。
御社が会社理念Link となされていらっしゃる、
CONSUITATION
SOLOUTION
とは何語ですか?
当方外国語の心得が無く、浅学の身にて、このような言語は目にしたことがございませんので、ご教授頂ければありがたく存じます。


注:カギ括弧"『"は閉じないのがオシャレなのです(自己満足

— posted by たか at 08:25 pm   pingTrackBack [0]

拡張子htmlのままPHPとして動かす場合

拡張子がhtmlなPHPファイルをそのままPHPとして動かす場合、HTML先頭の宣言がPHPとして解釈され、結果エラーとなる。
PHP開始タグを「
よって、この『ショートオープンタグ』設定を無効化すればよい。
ただ、この設定を行うためのディレクティブ"short_open_tag"なのだが、『変更の可否』がPHP_INI_ALL、ただし、
PHP <= 4.0.0 では PHP_INI_ALL、PHP < 5.3.0 では PHP_INI_PERDIR。
だそうで、PHP5.3.0以降なんてまだあまりつかわれていないだろうから、
PHP_INI_PERDIRであって、つまり『php.iniかApacheのhttpd.confか.htaccessで設定する必要がある』
ので注意が必要。。
(ini_set()できません、ってこと)


追記。あとから読んで、はてな?と思ったので。
上記で、PHP5.3.0以降の場合が書いてないじゃん、って思ったけど、最初に
    『変更の可否』がPHP_INI_ALL
って書いてあって、んで、
    PHP < 5.3.0 では PHP_INI_PERDIR
だから、PHP5.3.0以降はPHP_INI_ALLってことみたい。


というわけで.htaccessの例。
AddType application/x-httpd-php .html
php_flag short_open_tag off

ちゃんと動くかは環境次第なので、あしからず。

PHP

— posted by たか at 08:41 pm   pingTrackBack [0]

mb_strcutに渡す数値はバイト数

とりあえず。

ソース:
$str = "hankaku+全角文字列";
echo strlen($str) . "¥n";
echo mb_strlen($str, "EUC-JP") . "¥n";
echo substr($str,7,4) . "¥n";
echo mb_substr($str,7,4,"EUC-JP") . "¥n";
echo mb_strcut($str,7,4,"EUC-JP") . "¥n";
echo mb_strcut($str,14,4,"EUC-JP") . "¥n";

結果:
18
13
+全�(文字化け)
+全角文
+全
字列

PHP

— posted by たか at 05:23 pm   pingTrackBack [0]

T: Y: ALL: Online:
ThemeSwitch
Created in 0.1221 sec.
prev
2017.11
next
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30    
 
blogBar
Firefox3 Meter