exB - extreme B-AREA -

無敵の中年男性!的確な中年男性!難攻不落の中年男性!

ウェブ制作 - PHPとかMySQLとか

たぶん誰の役にも立たない、最近自分ちで使った関数とか構文のメモ。インストールはMySQLというかLAMP環境構築?あたり。

Warnningの意味

Missing argument
引数が省略もしくは見つからないぞ。

XML宣言とPHPのショートタグについて

XHTMでPHPを記述する場合、ショートタグを有効にしているとXML宣言がPHP構文として扱われてしまうことがある。これを回避するにはショートタグを無効にするか、XML宣言をPHPで書き出すとよい。

ショートタグを無効にする

php.iniでshort_open_tag = Offとするか、.htaccessでphp_flag short_open_tag offとする。ただソースのあちこちでショートタグな記述をしていると手直しに苦労するかもしれない。

PHPでXML宣言を記述する

先頭行にこんな感じで。

<?php echo '<?xml version="1.0" encoding="EUC-JP"?>'; ?>

ただファイル数が多いとこれまた非常にめんどうかもしれない。

参考:DOCTYPEスイッチのIE6バグ対策 for XHTML , ISO/IEC 15445:2000 etc

IE6には文書型が何であれ先頭行がDOCTYPE宣言になっていないと後方互換モードになってしまうバグがあるので、ブラウザ変数を取得してIE6の場合にはXML宣言を書き出さないよう

ソース凡例
<?php
$ua = $_SERVER['HTTP_USER_AGENT'];
if (!(ereg("Windows",$ua) && ereg("MSIE",$ua)) || ereg("MSIE 7",$ua)) {
     echo '<?xml version="1.0" encoding="EUC-JP"?>' . "\n";
}
?>

な感じにするとエレガントかもしれない。エンコーディングがUTF-8ならXML宣言を省略するのも手。

過去1週間の掲載タイトルの一覧表示

mktime関数

時刻を作る。書式はmktime(時,分,秒,月,日,年,サマータイム)。左から省略可能、引数を省略した場合は現在の時刻がセットされる。サマータイム時に1、サマータイムでない時に0、不明な時は-1。日付として無効な引数を与えた場合は自動補正。

ソース凡例
$sampledate = mktime(9, 30 , 0 , 8, 15, 1945);
print date("Y/m/d H:i:s", $sampledate) . "\n";
出力凡例
1945/08/15 09:30:00

変数とかデータベース項目

title
タイトル情報テーブル
releasedate
掲載予定日フィールド
visible
表示フラグ(0=非表示、1=表示、デフォルトは1)
$olddate
現在日より1週間前の日付を定義

過去1週間の掲載タイトルのみ表示するためのクエリ構文とか

ソース凡例
$date = date("Ymd");
$yyyy = date("Y");
$mm = date("m");
$dd = date("d");
$olddate = date("Ymd", mktime(0, 0, 0, $mm , $dd - 7, $yyyy));

$query_count = "SELECT * FROM title where visible=1
 and release > '$olddate' and releasedate <= '$date' "; 

8桁の日付(yyyymmdd)に区切りを入れたり0を取ったり和暦にしてみる

substr関数を使って任意の位置の文字を取り出す。

ソース凡例
$yy = substr($releasedate, 0, 4);
$mm = substr($releasedate, 4, 2);
$dd = substr($releasedate, 6, 2);
$jy = ($yy - 1988);
//西暦
$dateview = $yy . "/" . $mm . "/" . $dd";
//西暦(頭に0を付けない)
$dateviewS = date("Y/n/j", mktime(0, 0, 0, $mm, $dd, $yy));
//和暦
$dateviewJ = "平成" . $jy . "年" . $mm . "月" . $dd . "日";

和暦変換は昭和を扱わないのであれば単純に西暦から1988を引くだけでよい。1988年以前も扱う場合は元号が変わった日付まで処理しないといけないので、西暦のままだとかなり面倒な条件分岐をしないといけないが、平成に切り替わった1989年1月8日を一度strtotime関数でUNIXタイムスタンプに変換し、617900400以前であれば1925を引く、大正や明治もこの繰り返し(ポリリズム(リズム(むむむ、といった処理をしてはどうか。

…昭和なんて関係ねーよ、と言うなかれ。今上天皇がお隠れあそばれるようなことになったときのことを考えてみろ(不謹慎。

参考:元号変更日とUNIXタイムスタンプ
明治→大正
西暦:1912年7月30日、UNIXタイムスタンプ:-1785229200
大正→昭和
西暦:1925年12月25日、UNIXタイムスタンプ:-1356080400
昭和→平成
西暦:1989年1月8日、UNIXタイムスタンプ:617900400
ソース凡例
$start_showa  = date("Ymd", mktime(0, 0, 0, 8, 1, 1989));
$start_taisho = date("Ymd", mktime(0, 0, 0, 25, 12, 1925));
$start_meiji  = date("Ymd", mktime(0, 0, 0, 30, 7, 1911));
print strtotime("$start_showa");
print strtotime("$start_taisho");
print strtotime("$start_meiji");

掲載済みタイトルの一覧表示

すべてのリスト表示の基本クエリ。

変数とかデータベース項目

titlename
タイトル情報テーブルのタイトル名フィールド
$totalrows
現在の登録タイトル数を定義
$totalrows2
現在の掲載タイトル数を定義
$titleviewlimit
1ページ表示数を定義(10件、setting.incで定義)
$limitvalue
掲載済みタイトルの中から抽出するレコードを定義

現在の掲載タイトルを名前順で一覧表示するためのクエリ構文とか

ソース凡例
$date = date("Ymd");

//登録済み件数用のクエリ
$query_count = "SELECT * FROM title where visible=1"; 
$result_count = @mysql_query($query_count); 
$totalrows = @mysql_num_rows($result_count); 

@$page = $_GET['page']; //GETの$pageを変数に代入
if(empty($page)){        //$page がなかったら1ページ目
$page = 1;
}

//リスト表示用のクエリ
$limitvalue = $page * $titleviewlimit - ($titleviewlimit);
$titlequery = "SELECT * FROM title where visible=1
 and release <= '$date' order by titlename LIMIT $limitvalue, $titleviewlimit";;
$titleresult = mysql_query($titlequery);

//掲載済み件数用のクエリ
$titlequery2 = "SELECT * FROM title where visible=1 and release <= '$date'";
$titleresult2 = mysql_query($titlequery2);
$totalrows2 = mysql_num_rows($titleresult2); 

登録/掲載件数の表示

ソース凡例
echo("現在の登録数:"$totalrows"件 掲載分:"$totalrows2"件"); 

PHPのマルチバイト文字列関数を使って文字数調整をする

あらかじめphp.iniでmb_stringライブラリを有効にしておく。

mb_substr

文字列内の開始位置からの部分文字列を返す関数。substrのマルチバイト版。書式はmb_substr(文字列, 開始位置,長さ,エンコーディング) 。半角全角関係なし。エンコーディングを省略すると内部文字エンコーディングが使われる。

mb_strlen

文字列の長さを返す。strlenのマルチバイト版。

変数とかデータベース項目

comment
タイトル情報テーブルのコメントフィールド
$comview
表示コメント

コメント文字数調整のクエリ構文とコード

ソース凡例
$titlequery = "SELECT * FROM title where visible=1";
$titleresult = mysql_query($titlequery);

//繰り返し処理
while($row = @mysql_fetch_array($titleresult)){ 

//配列からコメントを取り出す
$comment = $row["comment"];

//コメントの先頭から150文字までを取り出す
//MySQLの内部エンコーディングがUTF-8なのでEUC-JPを指定してやる
$comviewtmp = mb_substr($comment, 0, 150, "EUC-JP");

//取り出した文字数をカウント
$comnum = mb_strlen($comment);

//コメントが150文字以上だった場合、末尾に…を挿入
if($comnum <= "150"){
	$compreview = $comviewtmp;
}else{
	$compreview = $comviewtmp . "…";
}

mb_strimwidth

ちゃんと文字切り詰め用の関数があるじゃないか。構文書式はmb_strimwidth(文字列, 開始位置,長さ,サフィックス,エンコーディング) 。

ソース凡例
$titlequery = "SELECT * FROM title where visible=1";
$titleresult = mysql_query($titlequery);

//配列からコメントを取り出す
$comment = $row["comment"];

//コメントの先頭から150文字までを取り出す
//MySQLの内部エンコーディングがUTF-8なのでEUC-JPを指定してやる
$compreview = mb_strimwidth($comment, 0, 150, "…" , "EUC-JP");

出力結果は同じ。

strip_tags

文字列からタグを除去する。mb_strimwidthの前に処理しておくべき。

//配列からコメントを取り出す
$comment = $row["comment"];
//タグの除去
$comment = strip_tags($comment);
//コメントの先頭から150文字までを取り出す
//MySQLの内部エンコーディングがUTF-8なのでEUC-JPを指定してやる
$compreview = mb_strimwidth($comment, 0, 150, "…" , "EUC-JP");

あとでタグ付きコメントを使うなら、unsetして取り出しなおすのは面倒なので変数名を変えたほうがてっとり早い。

//配列からコメントを取り出す
$comment = $row["comment"];
//タグの除去
$comment1 = strip_tags($comment);
//コメントの先頭から150文字までを取り出す
//MySQLの内部エンコーディングがUTF-8なのでEUC-JPを指定してやる
$compreview = mb_strimwidth($comment1, 0, 150, "…" , "EUC-JP");

掲載タイトルに女優名を挿入する

タイトル情報テーブルへのクエリ結果に含まれる女優IDを女優情報テーブルに問い合わせて女優名を補完するための処理。

変数とかデータベース項目

actress
女優情報テーブル
actid
女優ID
actname
女優名
$actidserch
$titleresult中の女優ID

クエリ構文とコード

ソース凡例
//タイトル情報へのクエリ
$titlequery = "SELECT * FROM title where visible=1:"
$titleresult = mysql_query($titlequery);

//繰り返し
while($row = @mysql_fetch_array($titleresult)){ 

//配列から女優IDを取り出す
$actid = $row["actid"];

//複数の女優IDが含まれた場合の処理
if(!empty($actid)){
$actidrow = split(",",$actid);
$actidcount = count($actidrow);
for($p=0; $p < $actidcount; $p++) {

//検索する女優IDを定義
$actidserch = $actidrow[$p];

//女優情報テーブルへのクエリ
$queryact = "SELECT actname FROM actress where actid = '$actidserch'"; 
$result_act = @mysql_query($queryact); 

//女優名1の処理
$actname1 = mysql_fetch_array($result_act);
//女優名2の処理
$actname2 = $actname1[0];

//女優IDが1つだった場合の処理
if (empty($actname)){
$actname = $actname2;
}
//女優IDが2つだった場合の処理
else 	{
$actname = $actname . "," . $actname2;
}
}//for
}//if(!empty
//女優IDが存在しない場合の処理
else {
$actname = "未登録";
}
//3つ以上は面倒なのでやらない

これでは結果表示したときに女優名にアンカーをマークアップするのが面倒になるのでいつか改良する。

改良版

女優名にアンカーをマークアップしてみる。

出演女優が複数の場合、actidがタイトル情報テーブルにカンマ区切りで格納されているのでsplitで取り出したactidをもとにforで繰り返し処理、でいいんだと思う。

ソース凡例
if(!empty($actid)){
$actidsearch = split(",",$actid);
$actsearchrow = count($actidsearch);
for($m=0;$m < $actsearchrow;$m++){
	$actsearch = $actidsearch[$m];
	$actnames = split(",",$actname);
	$actnameview = $actnames[$m];
	echo "<a href=\"/list_act.html?actid=$actsearch\">$actnameview</a> ";
}
}

どうやらうまくいったらしい。

最近使ったSQL構文

掲載済みタイトルを公開年度と名前順でソート

title
タイトル情報テーブル
visible
表示フラグ(0=非表示、1=表示、デフォルトは1)
release
掲載予定日フィールド
$date
変数で現在日を定義
releaseyear
公開年フィールド
titlename
タイトル名フィールド

whereでマッチする条件を指定、<=は指定した値以内に限定、order by でソートする対象フィールドを指定、descで逆順に、カンマ以降は同一値でのソート順を指定。

ソース凡例
SELECT * FROM title where visible=1 and release <= '$date'
 order by releaseyear desc , titlename

フィールドのコピー

テーブル「sampletable」のフィールド「field_a」のデータを「field_b」にコピーしたいのだが、phpMyAdminにはその機能がなかったので直接SQL文を打つ。

SQL文
> update sampletable set field_b = field_a ;