※ パクレゼルヴではWeb開発エンジニアを大募集中!詳細はこちら

Archive

Archive for the ‘Tips’ Category

HTMLの事とか  

2010/7/5 月曜日 14:33:29

先月はWebデザインを主にしていました。
プログラムを全く触っていないわけじゃないですよ・・・?
まぁともかく!HTMLとかCSSとか、後PHPですこし気付いた事でも。
自分メモ的な感じで。

array_shift()とarray_pop()

array_shift()
array_pop()
てのがあるんですが。この関数、例えばarray_shift()だったら

$data = array('青','赤','黄','白','緑','紫','金','銀');
$data1 = array_shift($data);
echo $data1;
foreach($data1 as $val){
    echo $val;
}

ってやれば

//$data1
青
//$data
赤黄白緑紫金銀

となる。配列の先頭の要素を抜き出す。
array_pop()は最後の要素を抜き出す。
元の配列が変わってしまうという点に注意さえすれば、便利な関数なんですが、
元の配列が変わってしまった事で起きた出来事が。

配列に都道府県毎の料金を入れて、最大値と最低値、都道府県毎の料金を表示させるって事をやってたんですが、
料金の最大値と最低値が表示されない!なんで!
と思って調べたら、array_shift()とarray_pop()を使っていたためでした。
料金の配列を降順でソートして、array_shift()で先頭(最大値)を、array_pop()で最後(最低値)を
抜いていたのです。

そこで、reset()、end()の登場。

reset()は内部ポインタを最初の要素まで戻し、その値を返す。
end()はその逆。

array_shift()とarray_pop()と似たような動きをする関数です。
array_shift()等とは違って、元の配列が変わらない。
処理速度はというと・・・そんなに変わらないそうです;;(若干reset()のほうが早いようですが)

しかし、max()、min()でやったら?って気がするかも・・・

因みにこのreset()関数、同じソースで、同じ配列を複数回使う場合などに使えます。というか使います。

$array = array('1', '2', '3', '4');

next($array);
echo current($array) ; // "2"

//ポインタをリセットして再度実行
reset($array);
echo current($array) ; // "1"

こんな感じかな?

以降はhtml関係のお話
メイリオについて
>メイリオとは、和文ゴシック体フォントの一つで、Vista以降のマイクロソフト製OSに標準で搭載されてる。
まぁXPとか2003とかで使ってたMS UI Gothicに代わるフォントなんですけど、今回これに苦しめられました。

font-family:"メイリオ",Meiryo,"Hiragino Kaku Gothic Pro","ヒラギノ角ゴ Pro W3","MS P Gothic","MS Pゴシック",Verdana,Arial,sans-serif;

てな感じで指定してるんですけど、OSがVistaと7だとデザインが崩れるんですよね。

なぜかというと、メイリオは全角文字がすべて固定幅のフォントであり、行間も従来フォントに比べて広いから。
なのでゴシックなどを想定して作ってるとデザインが崩れる。

font-familyでメイリオはずして、ゴシックを先頭にするとかで解決。
line-heightで行間を短くするのでもOKかな?
僕は今回line-heightで行間短くして対処しました。ゴシックだとなんか字が汚いんですよね・・・

つっしー HTMLとか, PHP, Tips

mysqlでINは内部的に処理できない  

2010/5/26 水曜日 0:33:39

お久しぶりです。

以前、ボトルネックになっているSQLを探していたら以下のような事がありました。

EXPLAIN SELECT * FROM user_master
	WHERE user_id IN (
		SELECT user_id FROM game_user_status);

とすると

+----+--------------------+------------------+-----------------+---------------+---------+---------+------+------+-------------+
| id | select_type        | table            | type            | possible_keys | key     | key_len | ref  | rows | Extra       |
+----+--------------------+------------------+-----------------+---------------+---------+---------+------+------+-------------+
|  1 | PRIMARY            | user_master      | ALL             | NULL          | NULL    | NULL    | NULL |   86 | Using where |
|  2 | DEPENDENT SUBQUERY | game_user_status | unique_subquery | PRIMARY       | PRIMARY | 4       | func |    1 | Using index |
+----+--------------------+------------------+-----------------+---------------+---------+---------+------+------+-------------+

86*1 
で普通に意図した結果が取得できます。

しかし、サブクエリ中でGROUP BYすると酷いことになりました。

EXPLAIN SELECT * FROM user_master
	WHERE user_id IN (
		SELECT user_id FROM game_user_status GROUP BY user_id);
+----+--------------------+------------------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type        | table            | type  | possible_keys | key     | key_len | ref  | rows | Extra       |
+----+--------------------+------------------+-------+---------------+---------+---------+------+------+-------------+
|  1 | PRIMARY            | user_master      | ALL   | NULL          | NULL    | NULL    | NULL |   86 | Using where |
|  2 | DEPENDENT SUBQUERY | game_user_status | index | NULL          | PRIMARY | 4       | NULL |   67 | Using index |
+----+--------------------+------------------+-------+---------------+---------+---------+------+------+-------------+

GROUP BYすると

86*67

と、検索ロジックに大きな違いが出てきます。

で、原因は”IN”句

MySQLは内部的にINを直接処理することができないので、EXISTSに変換することでSQL的には相関のないサブクエリも相関サブクエリになってしまうのである。これがまさにMySQLのサブクエリが遅い!と言われている原因だろう。
なぜMySQLのサブクエリは遅いのか。

だからってGROUP BY使っただけでそこまでしなくても・・・

と、いう事で以下のように書き換えると解決できるようです。

EXPLAIN SELECT * FROM user_master um
WHERE EXISTS
(SELECT 1 FROM game_user_status gus WHERE um.user_id = gus.user_id);
+----+--------------------+-------+--------+---------------+---------+---------+-----------------------+------+-------------+
| id | select_type        | table | type   | possible_keys | key     | key_len | ref                   | rows | Extra       |
+----+--------------------+-------+--------+---------------+---------+---------+-----------------------+------+-------------+
|  1 | PRIMARY            | um    | ALL    | NULL          | NULL    | NULL    | NULL                  |   86 | Using where |
|  2 | DEPENDENT SUBQUERY | gus   | eq_ref | PRIMARY       | PRIMARY | 4       | warui_test.um.user_id |    1 | Using index |
+----+--------------------+-------+--------+---------------+---------+---------+-----------------------+------+-------------+

個人のブログの方でご指摘いただきました内容を解答例とさせていただいています。
安直にINを利用するのは良くないという例でした。

ちなみにgroup by してもしなくても取得結果が変わらない場合もあります。
今回の例なんかはgroup by しなくても取得結果は変わりません。

むやみやたらと色々つければいいって物でも無い いい例です。

のびーにょ MySQL, Tips, データベース

画像認証(CAPTCHA)  

2010/4/16 金曜日 20:42:19

仕事で必要だったので画像認証(CAPTCHA)とか簡単に使えるスクリプトないかなーと探してました

色々あったんですが、ライセンスがどうとか色々言われそうだったので作ってみました。

と、言ってもサンプルコピペに近いですけど。

PEARにText_CAPTCHAってのがあったのでそれ使ってやってみます。

PHPはGDとttfをサポートしていないと使えないので注意してね!

まずPEARインストールでText_CAPTCHAを取得
依存関係の奴も全部

pear install  -a Text_CAPTCHA

ってやったら

Failed to download pear/Text_CAPTCHA within preferred state "stable", latest release is version 0.4.0, stability "alpha", use "channel://pear.php.net/Text_CAPTCHA-0.4.0" to install
install failed

とかって怒られたので

pear install -a channel://pear.php.net/Text_CAPTCHA-0.4.0

で取得
alphaバージョンとかbetaバージョンは普通にインストールできないので、バージョン番号まで入れろって事です

で、phpをファイルを以下のような感じで作ると

< ?php
require_once ("Text/CAPTCHA.php");
$CAPTCHA = Text_Captcha::factory('Image');
//locate .ttfとかやって適当にフォントファイルのパスを見つけて指定してあげてね!
//ちゃんとあるフォントファイル指定してあげてね!
$CAPTCHA->init(200, 70, null, array(
	'font_size' => 22,
	'font_path' => '/usr/share/fonts/japanese/TrueType/',
	'font_file' => 'sazanami-mincho.ttf'
	)
);
$img = $CAPTCHA->getCAPTCHAAsPNG();
//セッションに保存するとかしてね!
$_SESSION['captcha_pass'] = $CAPTCHA->getPhrase();
header('Content-type: image/png');
echo $img;
exit;

ってファイルを作ってやってそのファイルにアクセスしてみる

すると以下のような画像ができるはず!

20100213070928

セッションに保存したフレーズを次のページに遷移するときに、ユーザーが入力した値と比べて
きちんと認証されているか確認してね!

セッションに保存したフレーズは1回できちんと消すようにしないとだめだよ!

セッションにフレーズが保存されていない場合の処理も書かないと、認証スルーするかもしれないから注意だよ!
とかとか、適当にできるっぽいです。

のびーにょ PHP, Tips

mod_rewriteでGETパラメータ名を変更する  

2010/4/16 金曜日 20:22:56

mod_rewriteのお話

旧システムから新システムの以降など、システムの仕様が変わる時でも古いURLを引き継ぎたい場合に役に立つ小技です。

問題1

GETパラメータの名前aaaをbbbに変更したい場合はどのようにすれば良いか?

ついつい以下のように設定してしまうかと思いますが、うまく動きません。

RewriteRule filename.html\?aaa=(.*) filename.html?bbb=$1 [L]

RewriteCondを使い、QUERY_STRINGの条件を指定すると、うまく動きます。

RewriteCond %{QUERY_STRING}     aaa=(.+)
RewriteRule filename.html filename.html?bbb=%1 [L]

%1で、RewriteCondでマッチしたパターンを取得できる。

問題2

GETパラメータの名前aaaをbbbに変更したいが、aaa以外のパラメータはそのまま残したい場合はどのようにすれば良いか?

解答1

QSAをつける。

RewriteCond %{QUERY_STRING}     aaa=(.+)
RewriteRule filename.html filename.html?bbb=%1 [L,QSA]

解答2

以下の場合、aaaのみbbbに書き換える事ができる。

RewriteCond %{QUERY_STRING}     ^(.*)aaa=(.+)$
RewriteRule filename.html filename.html?%1bbb=%2 [L]

オマケ

『上記試してみましたが、うまく動きません!』という場合

上から順に評価されるので、こんな事しているとうまく動かない。

#ファイルが存在する場合はそれを表示する
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.* - [L]
# ↑ファイルが存在した時点で、上記が評価されて終わってしまう。

#パラメータ名を書き換える。
RewriteCond %{QUERY_STRING}     ^(.*)aaa=(.+)$
RewriteRule filename.html filename.html?%1bbb=%2 [L]

順番を変更する事でうまく動く。

#パラメータ名を書き換える。
RewriteCond %{QUERY_STRING}     ^(.*)aaa=(.+)$
RewriteRule filename.html filename.html?%1bbb=%2 [L]
#↑先に評価される。

#ファイルが存在する場合はそれを表示する
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.* - [L]

そんな感じで、お役に立てれば幸いです。

マカー Apache, Tips

携帯電話のキャリア毎のHTMLの解釈の差を吸収する  

2009/7/31 金曜日 18:00:20

お久しぶりです

のびーにょです。

さて、携帯電話のHTMLに関するお話でも。

<div>
	<div style = "background-color:#FFAAAA">TITLE</div>
	<div style = "background-color:#CCCCCC">
		コンテンツ<br />
		コンテンツ<br />
		コンテンツ<br />
	</div>
</div>

ってな感じで書いた場合
ドコモ端末だと
block_dc1
ってな感じで
au端末だと
block_au1
こんな感じになっちゃいます。

divタグとdivタグの間に隙間ができてしまって、何ともみっともないことになります。
CSSでどうにかして隙間を埋めてしまいたいのですが、これはほぼ不可能です。

で、これ実はHTMLの書き方だけで同じようなレイアウトになります。

それが以下

<div>
	<div style = "background-color:#CCCCCC">
		<div style = "background-color:#FFAAAA">TITLE</div>
		コンテンツ<br />
		コンテンツ<br />
		コンテンツ<br />
	</div>
</div>

htmlの概念的にはよくはないんですけどね
イメージとしては以下のような感じ
灰色の部分がコンテンツのdivでピンクの部分がタイトルのdiv
s2

普通のイメージは
s1
こんな感じで、タイトルとコンテンツ部分の隙間をなくすようなCSSを書いたりしますが
携帯の場合、サポートしていない場合が多いです。

上記のHTMLで書いた場合は
ドコモ
block_dc2

au
block_au2
ってな感じで表示されて両方同じ見え方になります


もう一個例を出しましょう
1エリアごとに交互に色を入れ変えたい場合
良くあるのがランキングとか一覧表示とか
そのあたり。

<div>
	<div style = "background-color:#FFAAAA">aaaaa</div>
	<div style = "background-color:#CCCCCC">aaaaa</div>
	<div style = "background-color:#FFAAAA">aaaaa</div>
	<div style = "background-color:#CCCCCC">aaaaa</div>
	<div style = "background-color:#FFAAAA">aaaaa</div>
	<div style = "background-color:#CCCCCC">aaaaa</div>
	<div style = "background-color:#FFAAAA">aaaaa</div>
	<div style = "background-color:#CCCCCC">aaaaa</div>
	<div style = "background-color:#FFAAAA">aaaaa</div>
</div>

こんな感じで書きたくなりますよね。
でも、こう書くと
list_dc1
ドコモは問題ない

list_au1
でもやっぱりauで問題が出ます。

これも、以下のようなイメージでHTMLを記述することでドコモと同じように見せることが可能です。

s4

htmlはこんな感じで

<div style = "background-color:#FFAAAA">
	aaaaa
	<div style = "background-color:#CCCCCC">aaaaa</div>
	aaaaa
	<div style = "background-color:#CCCCCC">aaaaa</div>
	aaaaa
	<div style = "background-color:#CCCCCC">aaaaa</div>
	aaaaa
	<div style = "background-color:#CCCCCC">aaaaa</div>
	aaaaa
</div>

そうすると、ドコモ、auが以下のように同じように見えます。
list_dc2
list_au2

まぁ、そんな感じで一つ下のdiv要素の色を上の階層に持ってきてやると意図しない隙間をなくすことができます。


色々めんどくさいですけど、結構HTMLだけでも表現できたり色々便利
例えば、以下のような色分けを隙間なく表示したいときとかも
s5

<div style = "background-color:#FFF0E5">
	<div style = "background-color:#FFD0BF">
		<div style = "background-color:#FDDAF0">
			<div style = "background-color:#FABBEA">
				<div style = "background-color:#A3F27B">
					<div style = "background-color:#C0E9FA">
						<div style = "background-color:#FFF09C">
							<div style = "background-color:#F4DA67">
								<div style = "background-color:#ccccff">
									<div style = "background-color:#9966ff">
										<div style = "background-color:#FFB6C1">
											<div style = "background-color:#FF3333">
												<a href ="">
												<span style = "font-size:medium">
												かおもじ友の会</span>
												</a>
												<br />
											</div>
											┗3000個以上の顔文字やAAを収録!オリジナルな作品も投稿できてみんなで共有できちゃう!
										</div>
										<a href ="">
										<span style = "font-size:medium">
										あなたの過ごした時間</span>
										</a>
										<br />
									</div>
									┗時は金なり。あなたが生まれて今日まで過ごした「時間」について色々な角度から詳しく知りたいと思いませんか?
								</div>
								<a href ="">
								<span style = "font-size:medium">
								ちょいネタフーズ</span>
								</a>
								<br />
								</div>
								┗お手軽料理からネタ料理まで、レシピをケータイで簡単検索!オリジナルレシピも投稿しよう
							</div>
							<a href ="">
							<span style = "font-size:medium">
							切なさ成分解析</span>
							</a>
							<br />
						</div>
						┗身近な素材に含まれる「切なさ」を解析。結果を読むと思わず切なくなるかも?
				</div>
				<a href ="">
				<span style = "font-size:medium">
				明日に向かって叫べ</span>
				</a>
				<br />
			</div>
			┗魂の叫びに賞金がかかります!アナタも賞金首となって追われてみる?
		</div>
		<a href ="">
		<span style = "font-size:medium">
		NAME&nbsp;de&nbsp;QUEST</span>
		</a>
		<br />
	</div>
	┗あなたは世界を救う勇者となって、日頃の鬱憤を晴らすべく魔王に戦いを挑みます!
</div>

のびーにょ HTMLとか, Tips, キャリア, 携帯電話