PHPの話」カテゴリーアーカイブ

XAMPPが動作しない

2019年1月1日

新年に入って、時間に余裕が出来たので、PHPの勉強を始めました。

2019年1月3日

本を読んでいて、ちょっと理解しにくいところがあって、実際に動作させたくなって、パソコン上で動作できるXAMPPを利用する事にしました。
https://webkaru.net/php/setup/

Apacheの起動をしてみました。
でも、XAMPPのApacheで使うPort 80が他で使われていてApacheの起動ができません。

https://php1st.com/946
を参考にコマンドプロントでnetstat -nao を動作してローカルアドレスの数字が80のPIDを調べると4でした。
タスクマネージャーの詳細を確認するとSystem (NT Kemel & System)になっていました。

http://lovee7.blog.fc2.com/blog-entry-35.html
を参考に、[コントロールパネル] → [プログラム] → [プログラムと機能] → [Windowsの機能の有効化または無効化]で「Windowsの機能」ダイアログを表示させます。
「インターネット インフォメーション サービス」の項目を開いて、「World Wide Web サービス」のチェックを外しました。

XAMPPを管理者として実行(アイコンを右クリックで管理者として実行)する。
Apacheが起動しました。
Attempting to start Apache service.
が表示されましたが、それ以降進みません。
https://lightning2014.ensyutsubu.com/blog/post-6335/
を参考にして
XAMPP Control Panelで「Apache」の左側についたチェックを押すと×マークになります。
これでApacheの起動するようになりました。 ここまでの道は長かったです。
結局、最初にXAMPPを使わないでApacheが動作しなかった原因も、Port 80が他で使われていた事が原因だったようです。

c:/xampp/htdocs/ に動作するPHPファイル(例えば test.php)を設置してあれば
XAMPP Control PanelでApacheとMySQLをStartさせて
http://localhost/test.php
でtest.phpを動作させることができます。

2019年1月4日

実際にPHPのファイルを動作させてみましたが、日本語は文字化けしました。
c:/xampp/php/ のphp.iniを書き換えると解決するということなんですが、
PHPの絵本では、文字コードEUC-JPにすると書いてあったので、その通りにしても解決しなく
本が古いので、新しい環境(Windows10)に合わせたほうが良いのかなと思って
https://techacademy.jp/magazine/2412 を参考に
文字コードUTF-8にして保存してみたのですが、やっぱり解決しません。

2019年1月5日

結果的には文字コードUTF-8にするのが正解だったのですが、PHPのファイルを作る際にも、UTF-8で入力しなければいけなかったのです。
https://hombre-nuevo.com/programming/%E3%80%90php%E3%80%91%E6%96%87%E5%AD%97%E5%8C%96%E3%81%91%E5%AF%BE%E7%AD%96%E3%81%AE%E3%81%9F%E3%82%81php%E3%82%92%E6%97%A5%E6%9C%AC%E8%AA%9E%E5%8C%96%E3%80%90xampp%E3%80%91/
が参考になりました。

これで、やっと日本語を使ったPHPのファイルをパソコン上で動作させる環境が整いました。
これだけの事で、これほど苦労させられるなんて、先が思いやられます。

次はサーバー上で動作できるように設定です。
サーバーでの設定の変更は、サーバーごとに違うんだと思いますが、自分が利用しているサーバーcoreserverの場合は、coreserverにログインして、サイト設定でPHPのバージョンをphp72に変更です。

早速、XAMPP上で動作したphpファイルをFTPでアップロードして、属性を全部実行可(755)に設定し動作を試してみました。
無事動作しました。やったね!

2019年3月24日

PHPのプログラムの製作に成功し、XAMPP 上のPHPで動作させる必要性に迫られたので、主に使うパソコンすべてにXAMPP 上でPHPを動作する環境を設置する事にしました。

さっそくデスクトップの自作パソコンにXAMPPをインストールしたのですが、動作しません。
「or reconfigure Apache and the Control Panel to listen on a different port」というエラーです。

前回同様
[コントロールパネル] → [プログラム] → [プログラムと機能] → [Windowsの機能の有効化または無効化]で「Windowsの機能」ダイアログを表示させます。
「インターネット インフォメーション サービス」の項目を開いて、「World Wide Web サービス」のチェックを外しました。

XAMPPを管理者として実行(アイコンを右クリックで管理者として実行)する。
XAMPP Control Panelで「Apache」の左側についたチェックを押すと×マークになります。
startボタンをクリックすると、許可画面が表示されるので許可するとApacheが起動しました。
XAMPP Control Panel右上部のConfigをクリックして、Autostart of modulesのApacheにチェックを入れてSaveすると自動起動します。
Start Control Panel MinimizedにチェックしてSaveするとXAMPP Control Panelが表示することなく起動します。

次はPHPのインストールです。
前にダウンロードしてあったphp-7.2.13-Win32-VC15-X64 でインストールします。
展開したフォルダの名前をphpに変更してc:¥phpになるように配置し、phpフォルダの直下にある「php.ini-production」ファイルをコピーし、「php.ini」というファイル名に変更しました。

これでPHPがXAMPPで動作するようになりました。

残りもう1台も同じ設定で動作するようになりました。

ついでに、Windows7のAOA150(液晶サイズ:8.9インチ CPU:Atom N270/1.6GHz/1コア メモリ容量:1GB)にもインストールしました。
特に設定を変えることなく、すんなり動作しました。
PHPの処理も問題なくできました。
寝室用に使おうと思います。



楽天トラベル空室検索APIを使ってPHPで宿泊情報の表示

2019年3月3日

楽天APIを利用して商品検索して表示するPHPプログラムが動作したので、アフィリエイトにも役立てようと、楽天APIを利用した宿泊情報の表示にトライすることにしました。

楽天APIの一覧で使いたいAPIを選んでおきます。使うのは楽天トラベル空室検索APIです。
https://webservice.rakuten.co.jp/document/
新規アプリ登録をして、楽天のデベロッパーIDとアフィリエイトIDを取得するのは同様です。
https://webservice.rakuten.co.jp/
忘れないようにメモしておいた方が良いです。

日付指定をして通常条件で最安値を表示するのが当座の目標です。
最近、最安値で検索した時に上位に表示されて目立つようにバースデーの客限定で特別価格を設定してたりするので本当に誰もが利用できる最安値を検索するのは難しいです。
最終的にはバースデープランを採用しているホテルは除外するようにしようと思います。

https://webservice.rakuten.co.jp/explorer/api/Travel/VacantHotelSearch/
で条件を設定した場合の、出力例を見る事が出来ます。

日付指定して、金沢で、1人、部屋はシングル、2000円以上(バースデー限定などの特殊条件での特別料金を外すために極端な安値は除外)、最安値を1ページ・1データで価格のみ表示という条件設定だと下記のようになります。

https://app.rakuten.co.jp/services/api/Travel/VacantHotelSearch/20170426?format=jsor&checkinDate=2019-04-06&checkoutDate=2019-04-07&smallClassCode=kanazawa&adultNum=1&f_rm_bed=single&hits=1&page=1&sort=%2BroomCharge&largeClassCode=japan&middleClassCode=ishikawa&minCharge=2000&elements=hotelMinCharge&applicationId=1089363386770913344

部屋がツインの場合はf_rm_bed=twin、部屋に拘らない場合はf_rm_bed=*です。

そのままブラウザのアドレスに挿入すると

{"hotels":[{"hotel":[{"hotelBasicInfo":{"hotelMinCharge":1500}}]}]}

と表示されます。設定した最低価格2000円以上なのに1500円と表示されてしまいます。

最安値(elements=hotelMinCharge)は、その日の最安値ではなく、その宿泊施設が登録した最安値なので、あまり意味が無いようです。
天トラベルの空室検索APIでは、その宿泊施設での指定日・指定条件での最低料金というのはAPIのデータとして存在しないようです。
それで、最安値を出力するのではなく、宿泊施設名を出力するようにしました。

https://app.rakuten.co.jp/services/api/Travel/VacantHotelSearch/20170426?format=jsor&checkinDate=2019-04-06&checkoutDate=2019-04-07&smallClassCode=kanazawa&adultNum=1&f_rm_bed=single&hits=1&page=1&sort=%2BroomCharge&largeClassCode=japan&middleClassCode=ishikawa&minCharge=2000&elements=hotelName&applicationId=1089363386770913344&datumType=1&responseType=large&searchPattern=0

ブラウザのアドレス欄に入力すると

{"hotels":[{"hotel":[{"hotelBasicInfo":{"hotelName":"SHAQ BIGHOUSE"}}]}]}

と出力されます。

とりあえず施設名だけを表示させないいけません。

公開API活用ガイド ZAPA著を参考に日付指定した時の最安値の宿泊施設名を表示するPHPプログラムを作ってみました。
https://www.pahoo.org/e-soul/webtech/php06/php06-45-01.shtm
も参考にしました。

チェックイン2019-04-05、チェックアウト2019-04-06、金沢で、部屋はシングル、1人、2000円以上(特殊条件での特別料金を外すために極端な安値は除外)、宿泊施設名を1ページ・1データで表示するプログラムを作ってみました。ファイル名はrakuten4.phpとしました。
SHAQ BIGHOUSE と宿泊施設名だけが表示されました。成功です。
後は、日付やその他の条件を変更して一覧を表示すれば目的を果たせます。

<?php

//楽天トラベルから宿を検索してHTMLタグを返す関数
function yado_rakuten($checkinDate,$checkoutDate,$adultNum,$minCharge,$f_rm_bed){
//developerIdを設定する
$applicationId = ‘1089363386770913344’;

//affiliateIdを設定する
$affiliateId = ‘15040cf4.7d33bce5.15040cf5.078e12d9’;

//URLを生成する
$url = ‘https://app.rakuten.co.jp/services/api/Travel/VacantHotelSearch/20170426?format=xml’.
‘&applicationId=’.$applicationId.
‘&largeClassCode=japan’.
‘&middleClassCode=ishikawa’.
‘&smallClassCode=kanazawa’.
‘&checkinDate=’.$checkinDate.
‘&checkoutDate=’.$checkoutDate.
‘&adultNum=’.$adultNum.
‘&minCharge=’.$minCharge.
‘&hits=1’.
‘&page=1’.
‘&sort=+roomCharge’.
‘&f_rm_bed=’.$f_rm_bed ;

//RESTで返されるXMLファイルを取得する
$str = @file_get_contents($url);

//XMLを解析してオブジェクトにセットする
$xml = simplexml_load_string($str);

//xpathによって、Item要素だけを取り出す
$Items = $xml->hotels->hotel->hotelBasicInfo->hotelName;

return $Items;
}
?>
<?php
$checkinDate = “2019-04-05”;
$checkoutDate = “2019-04-06”;
$minCharge = “2000”;
$adultNum = “1”;
$f_rm_bed = “single”;

echo yado_rakuten($checkinDate,$checkoutDate,$adultNum,$minCharge,$f_rm_bed);
?>

2019年3月4日

最安値の宿泊施設名を取り込むことができたのですが、30日分のデータを表示したいので、日付の設定と曜日入りの日付を表示できるようにする必要があります。

検索のための日付
<?php
$day = date(“Y-m-d”);
echo $day;
?>

表示のための曜日付の日付
<?php
$day = date(“Y-m-d”);
$w = date(“w”);
$week_name = array(“日”, “月”, “火”, “水”, “木”, “金”, “土”);
$day2= date(“Y-m-d”).'(‘.$week_name[$w].’)’;
echo $day2;
?>

1日後の日付
<?php
$day = date(“Y-m-d”,strtotime(‘+ 1 day’));
echo $day;
?>

後は変数を配列にしてデータベースSQLに保存すれば思っていたページができます。
当日のシングル1人・ツイン2人・すべての部屋を対象にした1人 での宿泊の最安の施設名
明日のシングル1人・ツイン2人・すべての部屋を対象にした1人 での宿泊の最安の宿泊名
明後日のシングル1人・ツイン2人・すべての部屋を対象にした1人 での宿泊の最安の宿泊名
3日後のシングル1人・ツイン2人・すべての部屋を対象にした1人 での宿泊の最安の宿泊名
29日後のシングル1人・ツイン2人・すべての部屋を対象にした1人 での宿泊の最安の宿泊名

2019年3月9日

すべての部屋を対象にした1人・シングルルーム1人・ツインルーム2人での宿泊予約の最安値の施設を表示するプログラムを作成しました。
高年齢の人を対象にした誕生日だけの限定激安を設定しているホテルリブマックス金沢医大前(153335)、ホテルリブマックス金沢駅前(165677)、ゆにろーず金沢TS店(136975)、ホテルトレンド金沢駅前(171908)、HOTEL花IchiRinKANAZAWA(160759)の宿泊施設IDは省くようにしました。
当日から30日間の
年月日(曜日) 最安値の宿泊施設名
を表示するプログラムです。

<?php

//楽天トラベルから宿を検索してHTMLタグを返す関数
function yado_rakuten($checkinDate,$checkoutDate,$adultNum,$minCharge,$f_rm_bed){
//developerIdを設定する
$applicationId = ‘1089363386770913344’;

//affiliateIdを設定する
$affiliateId = ‘15040cf4.7d33bce5.15040cf5.078e12d9’;

//URLを生成する
$url = ‘https://app.rakuten.co.jp/services/api/Travel/VacantHotelSearch/20170426?format=xml’.
‘&applicationId=’.$applicationId.
‘&largeClassCode=japan’.
‘&middleClassCode=ishikawa’.
‘&smallClassCode=kanazawa’.
‘&checkinDate=’.$checkinDate.
‘&checkoutDate=’.$checkoutDate.
‘&adultNum=’.$adultNum.
‘&minCharge=’.$minCharge.
‘&hits=1’.
‘&page=1’.
‘&sort=+roomCharge’.
‘&f_rm_bed=’.$f_rm_bed ;

//RESTで返されるXMLファイルを取得する
$str = @file_get_contents($url);

//XMLを解析してオブジェクトにセットする
$xml = simplexml_load_string($str);

//xpathによって、Item要素だけを取り出す
$Items = $xml->hotels->hotel->hotelBasicInfo->hotelName;
$hotelNo = $xml->hotels->hotel->hotelBasicInfo->hotelNo;
if ($hotelNo ==’153335′ or $hotelNo ==’136975′ or $hotelNo ==’171908′ or $hotelNo ==’160759′ or $hotelNo ==’171908′){$Items=”表示しない”;}
return $Items;
}
?>
<?php

echo ‘大人1人で宿泊’;print “<br>\n”;
for($n=0;$n<30;$n++)
{$n1=$n+1;
$n2=’+’.$n.’ day’;
$n3=’+’.$n1.’ day’;
$checkinDate = date(“Y-m-d”,strtotime(“$n2”));
$checkoutDate = date(“Y-m-d”,strtotime(“$n3”));
$minCharge = “1500”;
$adultNum = “1”;
$f_rm_bed = “*”;
$w=date(“w”,strtotime(“$n2”));
$week_name = array(“日”,”月”, “火”,”水”,”木”,”金”,”土”);
$day2=date(“Y-m-d”,strtotime(“$n2”)).'(‘.$week_name[$w].’)’;
echo $day2;
echo yado_rakuten($checkinDate,$checkoutDate,$adultNum,$minCharge,$f_rm_bed);
print “<br>\n”;
}
?>
<?php
print “<br>\n”;
echo ‘大人1人でシングルルームでの宿泊’;print “<br>\n”;
for($n=0;$n<30;$n++)
{$n1=$n+1;
$n2=’+’.$n.’ day’;
$n3=’+’.$n1.’ day’;
$checkinDate = date(“Y-m-d”,strtotime(“$n2”));
$checkoutDate = date(“Y-m-d”,strtotime(“$n3”));
$minCharge = “2000”;
$adultNum = “1”;
$f_rm_bed = “single”;
$w=date(“w”,strtotime(“$n2”));
$week_name = array(“日”,”月”, “火”,”水”,”木”,”金”,”土”);
$day2=date(“Y-m-d”,strtotime(“$n2”)).'(‘.$week_name[$w].’)’;
echo $day2;
echo yado_rakuten($checkinDate,$checkoutDate,$adultNum,$minCharge,$f_rm_bed);
print “<br>\n”;
}
?>
<?php
print “<br>\n”;
echo ‘大人2人でツインルームでの宿泊’;print “<br>\n”;
for($n=0;$n<30;$n++)
{$n1=$n+1;
$n2=’+’.$n.’ day’;
$n3=’+’.$n1.’ day’;
$checkinDate = date(“Y-m-d”,strtotime(“$n2”));
$checkoutDate = date(“Y-m-d”,strtotime(“$n3”));
$minCharge = “3000”;
$adultNum = “2”;
$f_rm_bed = “twin”;
$w=date(“w”,strtotime(“$n2”));
$week_name = array(“日”,”月”, “火”,”水”,”木”,”金”,”土”);
$day2=date(“Y-m-d”,strtotime(“$n2”)).'(‘.$week_name[$w].’)’;
echo $day2;
echo yado_rakuten($checkinDate,$checkoutDate,$adultNum,$minCharge,$f_rm_bed);
print “<br>\n”;
}
?>

2019年3月10日

部屋の種類ごとにデータを表示して初めて気づいたのですが、部屋の種類の指定が効いていないようです。

$f_rm_bed = “twin”; が無効なようです。
$roomClass = “twin”; にしてもダメです。

気合を入れて調べたのですが楽天トラベル空室検索APIでは部屋の種類の指定ができないようです。中途半端だなあ・・・・

表示されたデータを配列に登録してみましたが、登録して次の配列に処理が進むと、前の配列のデータが消えます。何が悪いのかなあ?
最後のecho $data[30];は表示されるのにecho $data[29];はエラーになります。

<?php

//楽天トラベルから宿を検索してHTMLタグを返す関数
function yado_rakuten($checkinDate,$checkoutDate,$adultNum,$minCharge){
//developerIdを設定する
$applicationId = ‘1089363386770913344’;

//affiliateIdを設定する
$affiliateId = ‘15040cf4.7d33bce5.15040cf5.078e12d9’;

//URLを生成する
$url = ‘https://app.rakuten.co.jp/services/api/Travel/VacantHotelSearch/20170426?format=xml’.
‘&applicationId=’.$applicationId.
‘&largeClassCode=japan’.
‘&middleClassCode=ishikawa’.
‘&smallClassCode=kanazawa’.
‘&checkinDate=’.$checkinDate.
‘&checkoutDate=’.$checkoutDate.
‘&adultNum=’.$adultNum.
‘&minCharge=’.$minCharge.
‘&hits=1’.
‘&page=1’.
‘&sort=+roomCharge’.”;

//RESTで返されるXMLファイルを取得する
$str = @file_get_contents($url);

//XMLを解析してオブジェクトにセットする
$xml = simplexml_load_string($str);

//xpathによって、Item要素だけを取り出す
$Items = $xml->hotels->hotel->hotelBasicInfo->hotelName;
$hotelNo = $xml->hotels->hotel->hotelBasicInfo->hotelNo;
if ($hotelNo ==’153335′ or $hotelNo ==’136975′ or $hotelNo ==’171908′ or $hotelNo ==’165677′ or $hotelNo ==’160759′){$Items=”表示しない”;}
return $Items;
}
?>
<?php
echo ‘大人1人での宿泊’;print “<br>\n”;
for($n=0;$n<30;$n++)
{$n1=$n+1;
$n2=’+’.$n.’ day’;
$n3=’+’.$n1.’ day’;
$checkinDate = date(“Y-m-d”,strtotime(“$n2”));
$checkoutDate = date(“Y-m-d”,strtotime(“$n3”));
$minCharge = “2000”;
$adultNum = “1”;
$w=date(“w”,strtotime(“$n2”));
$week_name = array(“日”,”月”, “火”,”水”,”木”,”金”,”土”);
$day2=date(“Y-m-d”,strtotime(“$n2”)).'(‘.$week_name[$w].’)’;
echo $day2;
echo yado_rakuten($checkinDate,$checkoutDate,$adultNum,$minCharge);
print “<br>\n”;
$yado=yado_rakuten($checkinDate,$checkoutDate,$adultNum,$minCharge);
$data = [$n =>$yado];
echo $data[$n];
print “<br>\n”;
}
?>
<?php
echo $data[29];
echo $data[30];
?>

配列はやめて、一気にデータベースに登録する事にしました。
テーブルのカラムはid、No、date、yadomeiにしました。
dateは、曜日付の年月日を文字列(例えば2019-03-10(日))として登録します。
データを取り出す時には処理をしないで済むという作戦です。
とりあえず30件分のデータを手動で入力しました。データーベース名はyasuiyadoにするつもりが間違えてysuiyadoになってしまいました。

2019年3月11日

データベースのデータを一挙に更新する事に成功しました。
残りはデータベースのデータを取り出して宿のページで表示するだけです。

<?php
try {
$db = new PDO(‘mysql:dbname=ysuiyado;host=127.0.0.1;charset=utf8’, ‘root’, ”);
} catch (PDOException $e) {
echo ‘DB接続エラー: ‘ . $e->getMessage();
}
?>

<?php

//楽天トラベルから宿を検索してHTMLタグを返す関数
function yado_rakuten($checkinDate,$checkoutDate,$adultNum,$minCharge){
//developerIdを設定する
$applicationId = ‘1089363386770913344’;

//affiliateIdを設定する
$affiliateId = ‘15040cf4.7d33bce5.15040cf5.078e12d9’;

//URLを生成する
$url = ‘https://app.rakuten.co.jp/services/api/Travel/VacantHotelSearch/20170426?format=xml’.
‘&applicationId=’.$applicationId.
‘&largeClassCode=japan’.
‘&middleClassCode=ishikawa’.
‘&smallClassCode=kanazawa’.
‘&checkinDate=’.$checkinDate.
‘&checkoutDate=’.$checkoutDate.
‘&adultNum=’.$adultNum.
‘&minCharge=’.$minCharge.
‘&hits=1’.
‘&page=1’.
‘&sort=+roomCharge’.”;

//RESTで返されるXMLファイルを取得する
$str = @file_get_contents($url);

//XMLを解析してオブジェクトにセットする
$xml = simplexml_load_string($str);

//xpathによって、Item要素だけを取り出す
$Items = $xml->hotels->hotel->hotelBasicInfo->hotelName;
$hotelNo = $xml->hotels->hotel->hotelBasicInfo->hotelNo;
if ($hotelNo ==’153335′ or $hotelNo ==’136975′ or $hotelNo ==’171908′ or $hotelNo ==’165677′ or $hotelNo ==’160759′){$Items=”表示しない”;}
return $Items;
}
?>
<?php
echo ‘大人1人での宿泊’;print “<br>\n”;
for($n=0;$n<30;$n++)
{$n1=$n+1;
$n2=’+’.$n.’ day’;
$n3=’+’.$n1.’ day’;
$checkinDate = date(“Y-m-d”,strtotime(“$n2”));
$checkoutDate = date(“Y-m-d”,strtotime(“$n3”));
$minCharge = “2000”;
$adultNum = “1”;
$w=date(“w”,strtotime(“$n2”));
$week_name = array(“日”,”月”, “火”,”水”,”木”,”金”,”土”);
$day2=date(“Y-m-d”,strtotime(“$n2”)).'(‘.$week_name[$w].’)’;
echo $day2;
echo yado_rakuten($checkinDate,$checkoutDate,$adultNum,$minCharge);
print “<br>\n”;
$yado=yado_rakuten($checkinDate,$checkoutDate,$adultNum,$minCharge);
$sql=’UPDATE yasuiyado SET yadomei=\”.$yado.’\’,date=\”.$day2.’\’ WHERE id=’.$n1;
$prepare = $db->prepare($sql);
$prepare->execute();
print “<br>\n”;
}
?>

2019年3月12日

今まで、参考書通りでMySQLを操作している時にはデータの変更が画面を見ながら編集できたのですが、自分でプログラム作ってデータを挿入すると、画面での編集が出来なくなっていました。編集ができないと言うより先に、編集、コピー、削除のボタン自体が表示されていませんでした。
これでは都合が悪いという事で調べたら、
Current selection does not contain a unique column. Grid edit, checkbox, Edit, Copy and Delete features are not available.
という表示が出ていました。
日本語に訳すと「現在の選択には一意の列は含まれていません。グリッド編集、チェックボックス、編集、コピー、削除機能は利用できません」ということのようです。
対処としては、「ユニークキーなどのユニークなカラムを作成しなさい」ということのようで、idのカラムを選択し、ユニークキーの設定(主の鍵をクリック)をしたら編集できるようになりました。

とりあえず、データベースからデータを取得して表示してみました。
phpファイルです。

<!DOCTYPE html>
<html lang=”ja”>
</head>
<meta charaset=”UTF-8″>
<title>データベースのデータを取得</title>
</head>
<body>
<div>

<?php
try {
$db = new PDO(‘mysql:dbname=ysuiyado;host=127.0.0.1;charset=utf8’, ‘root’, ”);
} catch (PDOException $e) {
echo ‘DB接続エラー: ‘ . $e->getMessage();
}
?>
<?php
$sql=’SELECT * FROM yasuiyado’;
$prepare = $db->prepare($sql);
$prepare->execute();
echo ‘<pre>’;
$result = $prepare->fetchAll(PDO::FETCH_ASSOC);
print_r($result);
echo ‘</pre>’;
?>
</div>
</body>
</html>

下記のように表示しました(2つのデータのみ掲載しています)。
これから、このデータを見栄えよく表示しなければいけません。

Array
(
[0] => Array
(
[id] => 1
[no] => 1
[date] => 2019-03-12(火)
[yadomei] => SHAQ BIGHOUSE
)

[1] => Array
(
[id] => 2
[no] => 2
[date] => 2019-03-13(水)
[yadomei] => THE SHARE HOTELS HATCHi 金沢
)

データベースのデータを表にして出力しました。これだけできれば後はなんとかなりそうです。

<!DOCTYPE html>
<html lang=”ja”>

<head>
<meta charaset=”UTF-8″>
<STYLE>
<!–
.gyou{
line-height: 18pt ; padding-left:10pt ; padding-right:10pt;
}
–>
</STYLE>
<title>データベースのデータを取得</title>
</head>
<body>
<div>

<?php
try {
$db = new PDO(‘mysql:dbname=ysuiyado;host=127.0.0.1;charset=utf8’, ‘root’, ”);
} catch (PDOException $e) {
echo ‘DB接続エラー: ‘ . $e->getMessage();
}
?>
<?php
$sql=’SELECT * FROM yasuiyado’;
$stmt = $db->query( $sql );

echo “<table bgcolor=\”#fbe48c\”>\n”;
while( $result = $stmt->fetch( PDO::FETCH_ASSOC ) ){
echo “\t<tr>\n”;
echo “\t\t<td bgcolor=\”#ffffff\” class=\”gyou\”>{$result[‘date’]}</td>\n”;
echo “\t\t<td bgcolor=\”#ffffff\” class=\”gyou\”>{$result[‘yadomei’]}</td>\n”;
echo “\t</tr>\n”;
}
echo “</table>\n”;

?>
</div>
</body>
</html>

2019年3月14日

大人1人で泊まった場合の最安値の宿泊施設と大人2人で泊まった場合の最安値の宿泊施設を別の表で出力するように変更しました。

<!DOCTYPE html>
<html lang=”ja”>
<head>
<meta charaset=”UTF-8″>
<STYLE>
<!–
.gyou{
line-height: 18pt ; padding-left:10pt ; padding-right:10pt;
}
–>
</STYLE>
<title>データベースのデータを取得</title>
</head>
<body>
<div>
<?php
try {
$db = new PDO(‘mysql:dbname=ysuiyado;host=127.0.0.1;charset=utf8’, ‘root’, ”);
} catch (PDOException $e) {
echo ‘DB接続エラー: ‘ . $e->getMessage();
}
?>
<?php
echo ‘大人1人での宿泊’;print “<br>\n”;
echo “<table bgcolor=\”#fbe48c\”>\n”;
for($n=1;$n<30;$n++){
$stmt =$db->query(“SELECT * FROM yasuiyado where id=$n”);
$result = $stmt->fetch();
echo “\t<tr>\n”;
echo “\t\t<td bgcolor=\”#ffffff\” class=\”gyou\”>{$result[‘date’]}</td>\n”; echo “\t\t<td bgcolor=\”#ffffff\” class=\”gyou\”>{$result[‘yadomei’]}</td>\n”;
echo “\t</tr>\n”;
}
echo “</table>\n”;
?>
<?php
echo ‘大人2人での宿泊’;print “<br>\n”;
echo “<table bgcolor=\”#fbe48c\”>\n”;
for($n=31;$n<60;$n++){
$stmt =$db->query(“SELECT * FROM yasuiyado where id=$n”);
$result = $stmt->fetch();
echo “\t<tr>\n”;
echo “\t\t<td bgcolor=\”#ffffff\” class=\”gyou\”>{$result[‘date’]}</td>\n”; echo “\t\t<td bgcolor=\”#ffffff\” class=\”gyou\”>{$result[‘yadomei’]}</td>\n”;
echo “\t</tr>\n”;
}
echo “</table>\n”;
?>
</div>
</body>
</html>

次に1人での宿泊について、全ての部屋の種類での最安値とシングルでの最安値の施設を検索するボタンと、2人での宿泊について、全ての部屋の種類とツインに限定しての最安値の施設を検索するボタンを設置します。
さすがに60日分の一覧は長すぎるので、デフォルトは1人での宿泊にして、ボタンで2人での宿泊に切り替えるようにします。
その次は最安値の宿泊施設のデータを更新してページをリロードするボタンも設置します。自分でも毎朝更新しますが、ページを見ている人もデータを更新できるようにすれば更新頻度も増すという作戦です。
あとはモバイル対応に整形して、データベースをサーバー上のMySQLに変更すれば完成です。

<?php
$rel = $_GET[‘reload’];
if ($rel == ‘true’) {
header(“Location: ” . $_SERVER[‘PHP_SELF’]);
}
?>

2019年3月16日

1人用の最安値施設一覧と2人用最安値施設一覧のページから更新ページに飛んだ時に、処理が終わったら元のページに戻る処理が必要です。
そのプログラムが下記になります。

<?php
header(‘HTTP/1.1 303 See Other’);
header(“location:”.$_SERVER[‘HTTP_REFERER’]);
exit();
?>

1人での宿泊について、全ての部屋の種類での最安値とシングルでの最安値の施設を検索するボタンと、2人での宿泊について、全ての部屋の種類とツインに限定しての最安値の施設を検索するボタンを設置しました。
60日分の一覧は長すぎるので、デフォルトは1人での宿泊にして、2人での宿泊に切り替える事ができるようにしました。
最安値の宿泊施設のデータを更新して処理後に元のページに戻るリンクを設置しました。

2019年3月17日

モバイル対応への整形がうまくいきました。
後は、サーバーのMySQLに接続してインターネット上に公開するだけです。

まずはXAMPPのphpMyAdminのデータをエクスポートしました。エクスポートのファイルはyasuiyado.sqlです。
yasuiyado.sqlをFTPでサーバーの_db_dumpフォルダ(public_htmlと同じ階層のフォルダ)にコピー。
CORESERVER.JPにログインしてデータベースをクリックして、新しいMySQLデータベースを追加しました。
データベース名はkimassi_yadoにしました。文字コードはUNICODEに選択しました。
新コントロールパネルの表示から、MySQL一覧で新しく作成したkimassi_yadoのアクションの項目からDBリストアのマークをクリック(不要な操作かも)して、kimassi_yadoのアクションの項目のphpMyAdminのマークをクリックしました。
phpMyAdminの画面に入れますので、インポートをクリックしてyasuiyado.sqlを選択し実行です。
データを確認しましたが、無事にデータベースの引越が完了していました。
データベース名はkimassi_yadoでテーブル名はyasuiyadoです。

phpプログラムのデータベースアドレス関連をCORESERVER.JP用に書き換えてファイルをアップロードすれば完成かな?

データベースにログインするphpプログラムは下記になります。

<?php
try {
$dsn=’mysql:host=localhost;dbname=kimassi_yado’;
$db = new PDO($dsn, ‘ユーザー名’, ’12桁のパスワードを入力’);
} catch (PDOException $e) {
echo ‘DB接続エラー: ‘ . $e->getMessage();
}
?>

ユーザー名はデータベース名と同じでkimassi_yadoになります。本来のユーザー名kimassiではデータベースkimassi_yadoにアクセスできません。
host=localhost;はhost=127.0.0.1; でも動作します。

ところが実際にはPHPのプログラムから、なかなかデータベースにアクセスできませんでした。
CORESERVER.JPに新たにデータベースをMySQLを追加した時に、PhpMyAdminにログインした時に新たなデータベースを反映させるには順序が大切なようです。
CORESERVER.JPに新たにデータベースをMySQLを追加した時に、PhpMyAdminのインストールをクリックしてリセットします。
次にPhpMyAdminをインストールに隣接するログインをクリックする。
そこでユーザー名とパスワードを求められます。
ここで、ユーザー名に新たにデータベース名(自分の場合はkimassi_yado)を入力して、パスワードにCORESERVER.JPの12桁のパスワードを入力します。
これでやっと新しいデータベース(自分の場合はkimassi_yado)にアクセスできまるようになりました。

CORESERVER.JP(バリューサーバー)では標準のPHPが「PHP5.6(モジュール版)」になっていてPHPが7.2だと動作に制限があるようです。
でもPHPが7.2でもMySQLにアクセスできました。

でも、なぜか更新ページで処理が途中で止まってしまうようです。エラーは出てないのですが、すんなりとはいきません。

2019年3月18日

更新ページで処理が途中で止まる理由を調べようとプログラムを単純化してみたのですが、MySQLには関係なく、CORESERVER.JP(バリューサーバー)では処理に時間がかかると負荷の大きさに関わりなく、動作をストップする仕様になっているようです。
やっぱり、XAMPP上で楽天関連の処理を済ませて、その後、オンライン上でデータベースの更新をするしかないようです。
現在は、CORESERVER.JP(バリューサーバー)上のデータベース名(自分の場合はkimassi_yado)を削除して、XAMPP上のデータベース(自分の場合はkimassi_yado)をsql形式でエクスポートして、CORESERVER.JP(バリューサーバー)上でsqlファイルをインポートすることによって、対応していますが、もっと簡単な方法が無いか調べてみようと思います。
念のために、Value-domainのユーザーフォーラム:CGI/PHP/DB関連で問い合わせしました。

2019年3月19日

どうしても判らなくて困った時の最後の頼みはYahoo!知恵袋です。
今回も素敵なアドバイスをいただきました。

なんでもcron 機能っていうのがあって、3件までは正常に動作するようなので、20回のに処理を分割して数分おきに実行するという方法があるようです。
でも、CORESERVER.JP(バリューサーバー)上の仕様で「cronジョブの最短間隔は1時間に1回まで」と掲載されていました。これでは使えません。
念のために、Value-domainのユーザーフォーラム:CGI/PHP/DB関連で問い合わせしました。

2019年3月21日

「ローカルのxampp側のphpスクリプトでデータを取り込む処理をした後に、そのphpスクリプトで必要なSQL文(truncate tabeleしてalter tableでauto_incrementのリセットもしくはdrop tableしてcreate tableとデータをinsertするSQL文)をダウンロードして、coreserver上のPHPファイルでcoreserver上のMySQLにおいてSQLファイルだけ実行する。」
というアイデアもアドバイスしていただけました。
でも、phpスクリプトで必要なSQL文をダウンロードするというのがうまくいかなくて、ダウンロードしたSQL文をcoreserver上のMySQLにおいて実行したら動作が長時間続いてデータは削除されてしまいました。

2019年3月22日

Value-domainのユーザーフォーラム:CGI/PHP/DB関連でもSTAFFからの返答がありました。
「処理時間が長いPHPプロセスが強制終了いたしますのは仕様でございます。API取得先の処理時間が長くなる場合は、運用が苦しいかと存じます。」という返答でした。

2019年3月23日

「作業用テーブルを使い、load data infile で取り込んで本番テーブルとidかnoでJOINしてupdateする」というアドバイスもいただいていました。
具体的には、xampp上のPHPファイルで処理をして、データはxampp上のMySQLに登録しなく別のファイル形式で保存して
coreserver上のPHPファイルで、データを作業用テーブルにload data infile で取り込んで、
update 本番テーブル join 作業用テーブル
on 本番テーブル.id = 作業用テーブル.id
set 本番テーブル.no = 作業用テーブル.no,
本番テーブル.`date` = 作業用テーブル.`date`
本番テーブル.yadomei = 作業用テーブル.yadomei
でcoreserver上のMySQLに登録という処理の流れのようです。

とりあえずは、xampp上のPHPファイルで処理をしてデータをcsvファイルとしてパソコンに出力する事から始めました。

下記のデータベースを開く命令を削除します。

<?php
try {
$db = new PDO(‘mysql:dbname=ysuiyado;host=127.0.0.1;charset=utf8’, ‘root’, ”);
} catch (PDOException $e) {
echo ‘DB接続エラー: ‘ . $e->getMessage();
}
?>

その位置を下記のcsvファイルを開く命令に入れ替えます

<?php
# 保存するファイル名を設定します。
$csvFile = ‘../../../data/output/csv-put.csv’;
if (! is_dir(dirname($csvFile))) {
die(‘保存するディレクトリが存在しません。’);
}

# ファイルを追記モードで開きます(ファイルが存在しない場合は新規作成)。
$fp = fopen($csvFile, ‘c+’);
if (! is_resource($fp)) {
die(‘ファイルを開けませんでした。’);
}

# ファイルをロックします(排他的ロック)。
flock($fp, LOCK_EX);

# ファイルの中身を空にします。
ftruncate($fp, 0); // 追記する場合はこの処理は不要
?>

下記のデータベースをアップデート箇所を削除して

$sql=’UPDATE yasuiyado SET yadomei=\”.$yado.’\’,date=\”.$day2.’\’ WHERE id=’.$n1;
$prepare = $db->prepare($sql);
$prepare->execute();

は下記のように配列にしてCSVファイルとして出力する命令に変更します。

$data=[];
$data[‘id’] =$n1;
$data[‘no’] =$n1;
$data[‘date’] =$day2;
$data[‘yadomei’] =$yado;
echo var_dump($data);
fputcsv($fp, $data);
}

最後にファイルを閉じます。

<?php
# ファイルのロックを解除します。
fflush($fp);
flock($fp, LOCK_UN);

# ファイルを閉じます。
fclose($fp);

# 保存したCSVファイルを読み込み、画面に表示します。
if (file_exists($csvFile)) {
echo ‘CSVファイルは保存されました。<br>’;
echo ‘以下は出力されたCSVファイル(’ . $csvFile . ‘)です。<br>’;
$csv = file_get_contents($csvFile);
} else {
echo ‘CSVファイルは保存されませんでした。’;
}

?>

後は、csvファイルのデータをホームページ上に反映すれば完成です。

でもパソコン上のcsvファイルのデータをPHPのプログラムでcoreserver上のMySQLに登録するのは難しいようです。
LOAD DATA local INFILEを使えばなんとかなると考えましたが、うまくいきません。

2019年3月24日

ここで、現在の処理を整理してみます。
1.ローカルのxampp上のMySQLをスタート(Apacheは自動的にスタートされる)
2.ローカルのxampp上で楽天APIのデータをxampp上のMySQLに登録
http://localhost/rakuten/rakutenyado15.php
3.ローカルのxampp上のMySQL上でデーターベースkimassi_yadoを選択しエクスポート(詳細-可能なオプションをすべて表示でDROP TABLEをコマンドを追加してからエクスポート)。sqlファイルがダウンロードフォルダに出来ている。
4.coreserver上のMySQLにアクセスし、データベースkimassi_yadoを選択し先ほどエクスポートしたsqlファイルをインポートする。

かなり面倒くさいです。
処理の問題で、ローカルのxampp上で楽天APIのデータを得るのは動かせないけど、その他の処理で省力化を図るのが課題です。

それでローカルのxampp上のMySQLを使わない方法を考えました。

1.ローカルのxampp上で楽天APIのデータをcsvファイルとしてハードディスクに保存
http://localhost/rakuten/rakutencsv.php
2.coreserver上のMySQLにアクセスし、テーブルyasuiyadoを選択し先ほどエクスポートしたcsvファイルをインポートする。
(フォーマット特有のオプションUpdate data when duplicate keys found on import (add ON DUPLICATE KEY UPDATE)にチェックを入れてインポート)

試してみましたが、うまくいきました。
最後に宿の名前の長さの上限を設定して取得するようにプログラムを変更します。

$data[‘yadomei’] =$yado;

の部分を

$data[‘yadomei’] =mb_substr($yado,0,34);

に変更して完成です。

完成したページはこちらです

2019年3月26日

今日からPHPの宿泊情報の表示を始めたのですが、楽天トラベル空室検索APIのデータを受け取る際にエラーが頻発して、最後まで処理できませんでした。

Notice: Trying to get property ‘hotelBasicInfo’ of non-object in C:\xampp\htdocs\rakuten\rakutencsv.php on line 55

Notice: Trying to get property ‘hotelName’ of non-object in C:\xampp\htdocs\rakuten\rakutencsv.php on line 55

朝は、楽天側の処理数が多くて、サーバーの処理能力が落ちているのかもしれません。
これでは使い物にならないので、途中で待ち時間を設けるか処理速度を遅くするかの対応が必要だと感じました

//RESTで返されるXMLファイルを取得する
$str = @file_get_contents($url);

の後に

usleep(500000);

を挿入しました。1つのデータ毎に0.5秒待つ命令です。
そしたら途中まで調子よく動作したのですが、

Fatal error: Maximum execution time of 30 seconds exceeded

のエラーが表示されました。
PHPは処理時間の制限が30秒になっているようで、30秒過ぎた時に出るエラーのようです。

set_time_limit(100);

をPHPの処理の先頭に挿入しました。100秒まで処理を続けるという命令です。

これでうまくいきました。後は、正常に動作する待機の最短時間を探せば完成かな?

1つのデータ毎に0.5秒待機だと時々失敗するようなので0.8秒にしました。

usleep(80000);

処理の制限時間は最終的に80秒にしました。

4台のパソコンにXAMPPとPHPの環境を整えたのですが、使わなく放置しておいたWindows7のAOA150(液晶サイズ:8.9インチ CPU:Atom N270/1.6GHz/1コア メモリ容量:1GB)を、この処理のメインに使おうと思います。
寝室で起きた時に操作しようと思います。

2019年3月27日

何故か朝早いと昨日からのデータを求めてしまいます。

<?php
for($n=0;$n<30;$n++)
{
$n2=’+’.$n.’ day’;
$checkinDate = date(“Y-m-d”,strtotime(“$n2”));
echo var_dump($checkinDate);

}
?>

で確認したら、昨日からの日付が表示されました。おかしいなあ。

原因はPHPの設定で、php.iniの2000行あたりで
[Date]
date.timezone=Europe/Berlin
になっているのを
[Date]
date.timezone= Asia/Tokyo
に変更すれば良いみたいです。9時間程度のずれがあったみたいです。

2019年3月30日

ブラウザのアドレスにphpの拡張子が表示されるのはいかがわしいので、phpの拡張子を消すことにしました。
.htaccessファイルに

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^\.]+)$ $1.php [NC,L]
</IfModule>

を追加して消せました。
拡張子なしのアドレス(https://kimassi.net/yadoitiran)でアクセスすると、ブラウザのバーでは拡張子なしのアドレス(https://kimassi.net/yadoitiran)で表示されるし、拡張子付のアドレス(https://kimassi.net/yadoitiran.php)でアクセスすると、ブラウザのバーでは拡張子付
のアドレス(https://kimassi.net/yadoitiran.php)で表示されます。

省力化のために、スタートアップにXAMPP ControlPanel(Apacheは自動起動に設定済)と通常使わないブラウザ(ホームページにlocalhost/rakuten/rakutencsv.php を設定済み)を登録しました。
でもブラウザはセキュリティソフトが立ち上がらないと起動できないので失敗しました。
batファイルのショートカットをステートアップに登録することでスタートアップで起動するプログラムの起動する時間を調整できる事がわかったので試してみることにしました。

@echo off
:遅延起動バッチファイル

echo 遅延起動を開始します。
:20秒待つ
timeout 20
:プログラム実行(カレントディレクトリ指定なし)
start “” “C:\Program Files\Mozilla Firefox\firefox.exe”

うまく動作しました。

2019年6月5日

急にデータの取得が途中で止まるようになりました。
set_time_limit(120);
usleep(100000);
と2箇所の数値を変更して対処しました。

2019年6月30日

AOA150の不具合を修正するためにBIOSをアップデートしたら、firefoxの起動時にXAMPPがまだ起動していない事によるアクセス先につながらないというトラブルが発生し、遅延起動バッチファイルを修正し、起動後150秒後にfirefoxが起動するように変更しました。

@echo off
:遅延起動バッチファイル
:10秒待つ
timeout 10
start “” “C:\xampp\xampp-control.exe”
echo 遅延起動を開始します2。
:150秒待つ
timeout 150
:プログラム実行(カレントディレクトリ指定なし)
start “” “C:\Program Files\Mozilla Firefox\firefox.exe”

最初の10秒待ちは、バッチを中止したい場合に手動で中止できるようにするためです。
ソフトの起動に時間がかかるのは、ウィルス対策ソフトAvast Free Antivirusの影響かもしれません。

2019年7月15日

ウィルス対策ソフトAvast Free Antivirusをアンインストールしたら、ソフトの立ち上がりも速くなったし動作も安定しました。

バッチファイルも

@echo off
:遅延起動バッチファイル
:10秒待つ
timeout 10
start “” “C:\xampp\xampp-control.exe”
echo 遅延起動を開始します2。
:20秒待つ
timeout 20
:プログラム実行(カレントディレクトリ指定なし)
start “” “C:\Program Files\Mozilla Firefox\firefox.exe”

に変更しました。 



PHPで楽天APIを利用

せっかくPHPの勉強をしたので、楽天APIを利用したページ作りにトライしました。

楽天APIの一覧で使いたいAPIを選んでおきます。
https://webservice.rakuten.co.jp/document/

まずは、楽天のデベロッパーIDとアフィリエイトIDを取得しないと始まりません。
https://webservice.rakuten.co.jp/
で新規アプリ登録をします。使うのは楽天トラベルの空室検索APIです。
登録が終わるとデベロッパーIDとアフィリエイトIDが表示されます。
自分の場合は
1089363386770913344
15040cf4.7d33bce5.15040cf5.078e12d9
でした。

公開API活用ガイド(ZAPA)の楽天APIに関するPHPプログラムを動作させてみました。
ソースファイルrakuten.phpは
http://www.kohgakusha.co.jp/support.html
で入手できます。
でも動作しませんでした(笑!)
楽天側の仕様が変わったのだと思います

これじゃあ話にならないという事で、とにかく楽天APIを動作させるPHPのサンプルプログラムをネットで探してみました。いくつか試したのですが、いずれもエラー表示が出るものばかりで使い物になりません。
http://connet.lolipop.jp/agoranet/rakutenaff/
でやっと自分の環境でも動作するPHPファイルを見つけました。
それを参考に、公開API活用ガイド(ZAPA)の楽天APIに関するPHPプログラムを改変して、やっと動作させることに成功しました。
設定した検索ワードに基づいて、5件分の画像が表示され、画像をクリックするとアフィリエイトIDをクッキーに埋め込み、対象ページに移動するプログラムです。

青文字は各自のIDを入れないといけないし、赤文字は今回書き換えた部分です。

<!DOCTYPE html >
<html lang=”ja”>
<head>
<meta charset=utf-8″>
<meta name=”viewport” content=”width=device-width, initial-scale=1, shrink-to-fit=no”>
<title>Rakuten API sample</title>

</head>
<body>
<?php

//楽天から商品を検索してHTMLタグを返す関数
function search_rakuten($keyword,$limit){

//developerIdを設定する
$applicationId = ‘1089363386770913344‘;

//affiliateIdを設定する
$affiliateId = ‘15040cf4.7d33bce5.15040cf5.078e12d9‘;

//バージョンを設定する
$version = ‘2017-07-06‘;

//取得件数を設定する
$hits = $limit;

//検索キーワードをURLエンコードして設定する
$text = urlencode($keyword);

//人気の高い順に検索する
$sort = urlencode(“standard”);

//URLを生成する
$url = ‘https://app.rakuten.co.jp/services/api/IchibaItem/Search/20170706?format=xml’.
‘&applicationId=’.$applicationId.
‘&affiliateId=’.$affiliateId.
‘&version=’.$version.
‘&keyword=’.$text.
‘&hits=’.$hits.
‘&sort=’.$sort;

//RESTで返されるXMLファイルを取得する
$str = @file_get_contents($url);

//XMLを解析してオブジェクトにセットする
$xml = simplexml_load_string($str);

//xpathによって、Item要素だけを取り出す
$Items = $xml->Items->Item;

//divタグでくくる
$ret = ‘<div id=”rakuten_item”>’;

//Item数だけ繰り返す
foreach($Items as $Item){
$ret .= ‘<a href=”‘.$Item->affiliateUrl.'”>’;
$ret .= ‘<img src=”‘.$Item->mediumImageUrls->imageUrl.'” >’;
$ret .= “</a>\n”;
}

//divタグを閉じる
$ret .= ‘</div>’;

//作成したHTMLを返す
return $ret;
}

//検索ワードを設定する
$keyword = “スイーツ”;

//取得数を設定する
$limit = 5;

//楽天から商品を検索して表示する
echo search_rakuten($keyword,$limit);

?>
<br>
<!– Rakuten Web Services Attribution Snippet FROM HERE –>
<a href=”https://webservice.rakuten.co.jp/” target=”_blank”>Supported by 楽天ウェブサービス</a>
<!– Rakuten Web Services Attribution Snippet TO HERE –>
</body>
</html>



オープンデータの情報をPHPでGooglemapに埋め込む

2019年2月24日

Googlemapにオープンデータの情報を入力して表示する為にPHPを利用できないかと頑張ってみました。
オープンデータの情報を取り出してPHPで処理して、下記に必要なデータを埋め込めば楽だと思ったのです。
せっかくPHPの勉強したんだから使わないと上達しません。

{
name: ‘<table><tr><td>金沢駅西口時計駐車場</td></tr><tr><td >24時間<br>収容台数:1500台</td></tr></table>’,
lat: 36.5806,
lng: 136.648722,
icon: ‘tam1.gif’ // 金沢駅西口時計駐車場のイメージpng
},
{
name: ‘<table><tr><td>金沢駅西広場一般車駐車場</td></tr><tr><td >24時間<br>収容台数:68台</td></tr></table>’,
lat: 36.57949,
lng: 136.647391,
icon: ‘tam2.gif’ // 金沢駅西広場一般車駐車場のイメージpng

},

{
name: ‘<table><tr><td>東山観光駐車場</td></tr><tr><td>午前7時~午後10時<br>収容台数:15台</td></tr></table>’,
lat: 36.573087,
lng: 136.665389,
icon: ‘tam3.gif’ // 東山観光駐車場jpg

}

金沢市の駐車場・駐輪場のオープンデータはCSV形式でID,地域,緯度,経度,ジャンル1,サブジャンル1,ジャンル2,サブジャンル2,ジャンル3,サブジャンル3,名称,概略(収納台数),郵便番号,住所,電話番号,FAX番号,E-mail,開館時間,休館日,料金,備考,リンクの項目があります。

そのまま使えるようなPHPプログラムにしても良いのですが、少しでも簡単にという事で、必要なデータだけ残すことにしました。
最初に駐輪場のデータを削除しました。
緯度,経度,名称,概略(収容台数),開館時間の4項目(列)だけ残して残りの項目を削除しました。
1行目の項目名も削除しました。
ファイル名をshisetsu_parkingre.csvにして、datafフォルダに入れました。
h.phpファイルをlibフォルダに入れました。

h.phpファイルの内容は

<?php
function h($var) // HTMLでのエスケープ処理をする関数
{
if (is_array($var)) {
return array_map(‘h’, $var);
} else {
return htmlspecialchars($var, ENT_QUOTES, ‘UTF-8’);
}
}
/* ?>終了タグ省略 ☆レシピ001☆(サーバーのPHP情報を知りたい) */

です。

オープンデータをGooglemap用に埋め込むプログラムはread_csv.phpです。

<?php
# h()関数☆レシピ221☆(安全にブラウザで値を表示したい)を読み込みます☆レシピ041☆(他のファイルを取り込んで利用したい)。
require_once ‘./lib/h.php’;

// CSVファイルはWindowsのExcelで作成したSJISエンコード
$csvFile = ‘./data/shisetsu_parkingre.csv’;
if (! file_exists($csvFile)) {
die(‘ファイルが存在しません。’);
}

// 文字化け対策
# CSVファイルの中身をすべて取り込みます。
$tempCSV = file_get_contents($csvFile);
# 文字エンコードをUTF-8に変換します☆レシピ058☆(文字エンコードを変換したい)。
$tempCSV = mb_convert_encoding($tempCSV, ‘UTF-8’, ‘CP932’);
# 一時ファイルに保存します。
$fp = tmpfile();
fwrite($fp, $tempCSV);
# ファイルポインタを先頭に戻します。
rewind($fp);
# ローケルを設定します。
setlocale(LC_ALL, ‘ja_JP.UTF-8’);

$file = ‘people.txt’;
$n=1;
while ($arr = fgetcsv($fp)) {
if (! array_diff($arr, array(”))) { // 空行を除外
continue;
}
list($lat, $lng, $name,$syuunou,$time) = $arr;
// nl2br()関数で要素内改行を<br>に変換
$person = ‘{name: \'<table><tr><td>’.nl2br(h($name), false) . ‘</td></tr><tr><td >’.nl2br(h($time), false) .'<br>’ . nl2br(h($syuunou), false) . ‘</td></tr></table>\’,’
.’lat:’ . nl2br(h($lat), false).’,’
.’lng: ‘. nl2br(h($lng), false) .’,’
. ‘icon: \’tam’.$n.’.gif\’ //’.nl2br(h($name), false) .’イメージgif’.”\n”.’},’.”\n”

;
file_put_contents($file, $person, FILE_APPEND | LOCK_EX);
$n=$n+1;
}

# ファイルのロックを解除します。
fflush($fp);
flock($fp, LOCK_UN);

# ファイルを閉じます。
fclose($fp);

?>

以上です。people.txtというファイルに出力されます。
一番最後のデータの }, は } に書き換えて埋め込みます。

埋め込みが完了したページは
https://kimassi.net/test/test5F.html
です。

ちなみに、概要のページtest5F.htmlのソースは下記の通りです。

<html>
<head>
<META charset=”UTF-8″>
<META name=”GENERATOR” content=”JustSystems Homepage Builder Version 21.0.5.0 for Windows”>
<STYLE>
<!–
.gyou{
line-height: 18pt ;
}
.gyou2{
line-height: 18pt ; padding-left:10pt ; padding-right:10pt;
}
.gyou3{
line-height: 18pt ; padding-left:10pt;
}
TABLE{
line-height: 18pt;
}
–>
</STYLE>
<STYLE>
<!–
body, th, td{
font-size: 95%;

// 600px以降から、100pxごとに1px大きくなる
@media (min-width: 600px) {
font-size: calc(112.5% + 4 * (100vw – 600px) / 400)
}

// 1,000px以上は、22pxに
@media (min-width: 1000px) {
font-size: calc(137.5%)
}
}

–>
</style>
<STYLE>
<!–
body,html{
max-width:800px;
margin-right: auto;
margin-left : auto;
}

–>
</style>

<style>
<!–
#map{

width: 100%;

height: 400px;

background-color: grey;

}

–>
</style>
<meta name=”viewport” content=”initial-scale=1.0″>
<title>金沢の駐車場GoogleMap </title>

</head>
<body>
<BR>
<center>
<TABLE>
<TBODY>
<TR>
<TD><A href=”https://kimassi.net/” target=”_top”><IMG src=”https://kimassi.net/kimassitoplogo.gif” alt=”金沢観光情報 【 きまっし金沢 】” width=”120″ border=”0″></A></TD>
<TD align=”left” valign=”middle”><H1 style=”font-size:18px; margin:0px;”><FONT color=”#cc0000″>金沢の駐車場 </FONT></h1></TD>
</TR>
</TBODY>
</TABLE>
<BR>
<TABLE>
<TBODY>
<TR>
<TD>
</TD>
</TR>
</TBODY>
</TABLE>
<BR>

<div id=”map”></div>
<script>
var map;
var marker = [];
var infoWindow = [];
var markerData = [ // マーカーを立てる場所名・緯度・経度
{name: ‘<table><tr><td>金沢駅西口時計駐車場</td></tr><tr><td >24時間<br>収容台数:1500台</td></tr></table>’,lat:36.5806,lng: 136.648722,icon: ‘tam1.gif’ //金沢駅西口時計駐車場イメージgif
},
{name: ‘<table><tr><td>金沢駅西広場一般車駐車場</td></tr><tr><td >24時間<br>収容台数:68台</td></tr></table>’,lat:36.57949,lng: 136.647391,icon: ‘tam2.gif’ //金沢駅西広場一般車駐車場イメージgif
},
{name: ‘<table><tr><td>金沢駅東駐車場</td></tr><tr><td >午前7時~午後11時<br>収容台数:352台</td></tr></table>’,lat:36.576206,lng: 136.648134,icon: ‘tam3.gif’ //金沢駅東駐車場イメージgif
},
{name: ‘<table><tr><td>ポルテ金沢駐車場</td></tr><tr><td >24時間<br>収容台数:450台</td></tr></table>’,lat:36.57634,lng: 136.649433,icon: ‘tam4.gif’ //ポルテ金沢駐車場イメージgif
},
{name: ‘<table><tr><td>リファーレ駐車場</td></tr><tr><td >午前7時~午後10時<br>収容台数:268台</td></tr></table>’,lat:36.575865,lng: 136.651441,icon: ‘tam5.gif’ //リファーレ駐車場イメージgif
},
{name: ‘<table><tr><td>武蔵地下駐車場</td></tr><tr><td >午前7時~午後11時<br>収容台数:194台</td></tr></table>’,lat:36.574211,lng: 136.654129,icon: ‘tam6.gif’ //武蔵地下駐車場イメージgif
},
{name: ‘<table><tr><td>石川県立音楽堂</td></tr><tr><td >午前9時~午後10時<br>収容台数:152台</td></tr></table>’,lat:36.57672,lng: 136.647841,icon: ‘tam7.gif’ //石川県立音楽堂イメージgif
},
{name: ‘<table><tr><td>金沢フォーラス駐車場</td></tr><tr><td >24時間<br>収容台数:420台</td></tr></table>’,lat:36.579348,lng: 136.649811,icon: ‘tam8.gif’ //金沢フォーラス駐車場イメージgif
},
{name: ‘<table><tr><td>名鉄スカイパーキング</td></tr><tr><td >午前6時~午後12時<br>収容台数:620台</td></tr></table>’,lat:36.572802,lng: 136.654387,icon: ‘tam9.gif’ //名鉄スカイパーキングイメージgif
},
{name: ‘<table><tr><td>近江町パーキングビル</td></tr><tr><td >午前8時00分~午後6時00分<br>収容台数:228台</td></tr></table>’,lat:36.570437,lng: 136.656682,icon: ‘tam10.gif’ //近江町パーキングビルイメージgif
},
{name: ‘<table><tr><td>めいてつ・エムザ地下駐車場</td></tr><tr><td >午前8時30分~午後8時30分<br>収容台数:60台</td></tr></table>’,lat:36.572674,lng: 136.654991,icon: ‘tam11.gif’ //めいてつ・エムザ地下駐車場イメージgif
},
{name: ‘<table><tr><td>近江町市場</td></tr><tr><td >建て替えのため閉鎖中<br>建て替えのため閉鎖中</td></tr></table>’,lat:36.571631,lng: 136.657648,icon: ‘tam12.gif’ //近江町市場イメージgif
},
{name: ‘<table><tr><td>近江町いちば館駐車場</td></tr><tr><td >午前7時30分~午後11時30分<br>収容台数:94台</td></tr></table>’,lat:36.571844,lng: 136.656398,icon: ‘tam13.gif’ //近江町いちば館駐車場イメージgif
},
{name: ‘<table><tr><td>石川県兼六駐車場</td></tr><tr><td >24時間<br>収容台数:482台</td></tr></table>’,lat:36.564888,lng: 136.664091,icon: ‘tam14.gif’ //石川県兼六駐車場イメージgif
},
{name: ‘<table><tr><td>兼見御亭パーキング</td></tr><tr><td >午前8時30分~午後5時30分<br>収容台数:100台</td></tr></table>’,lat:36.561714,lng: 136.665588,icon: ‘tam15.gif’ //兼見御亭パーキングイメージgif
},
{name: ‘<table><tr><td>石川県石引駐車場</td></tr><tr><td >24時間<br>収容台数:370台</td></tr></table>’,lat:36.557697,lng: 136.665008,icon: ‘tam16.gif’ //石川県石引駐車場イメージgif
},
{name: ‘<table><tr><td>金沢歌劇座有料駐車場</td></tr><tr><td >24時間<br>収容台数:76台</td></tr></table>’,lat:36.558593,lng: 136.658952,icon: ‘tam17.gif’ //金沢歌劇座有料駐車場イメージgif
},
{name: ‘<table><tr><td>金沢市役所・美術館駐車場</td></tr><tr><td >午前8時30分~午後11時<br>収容台数:319台</td></tr></table>’,lat:36.560954,lng: 136.657267,icon: ‘tam18.gif’ //金沢市役所・美術館駐車場イメージgif
},
{name: ‘<table><tr><td>香林坊地下駐車場</td></tr><tr><td >24時間<br>収容台数:813台</td></tr></table>’,lat:36.564272,lng: 136.65473,icon: ‘tam19.gif’ //香林坊地下駐車場イメージgif
},
{name: ‘<table><tr><td>竪町駐車場</td></tr><tr><td >24時間<br>収容台数:205台</td></tr></table>’,lat:36.558446,lng: 136.653684,icon: ‘tam20.gif’ //竪町駐車場イメージgif
},
{name: ‘<table><tr><td>北パーキング</td></tr><tr><td >24時間<br>収容台数:85台</td></tr></table>’,lat:36.56054,lng: 136.651377,icon: ‘tam21.gif’ //北パーキングイメージgif
},
{name: ‘<table><tr><td>タイムズ金沢片町商店街</td></tr><tr><td >24時間<br>収容台数:32台</td></tr></table>’,lat:36.558507,lng: 136.65311,icon: ‘tam22.gif’ //タイムズ金沢片町商店街イメージgif
},
{name: ‘<table><tr><td>OVALパーキング</td></tr><tr><td >24時間<br>収容台数:270台</td></tr></table>’,lat:36.558696,lng: 136.65341,icon: ‘tam23.gif’ //OVALパーキングイメージgif
},
{name: ‘<table><tr><td>にし茶屋観光駐車場</td></tr><tr><td >午前9時~午後10時<br>収容台数:13台</td></tr></table>’,lat:36.557087,lng: 136.648079,icon: ‘tam24.gif’ //にし茶屋観光駐車場イメージgif
},
{name: ‘<table><tr><td>長町観光駐車場</td></tr><tr><td >午前7時30分~午後6時<br>収容台数:20台</td></tr></table>’,lat:36.563104,lng: 136.64958,icon: ‘tam25.gif’ //長町観光駐車場イメージgif
},
{name: ‘<table><tr><td>近江町観光バス駐車場</td></tr><tr><td >午前7時30分~午後9時<br>収容台数:バス4台</td></tr></table>’,lat:36.570363,lng: 136.657602,icon: ‘tam26.gif’ //近江町観光バス駐車場イメージgif
},
{name: ‘<table><tr><td>東山観光バス駐車場</td></tr><tr><td >午前9~午後6時<br>収容台数:バス5台</td></tr></table>’,lat:36.573291,lng: 136.664824,icon: ‘tam27.gif’ //東山観光バス駐車場イメージgif
},
{name: ‘<table><tr><td>東山北観光駐車場</td></tr><tr><td >午前9~午後6時<br>収容台数:7台</td></tr></table>’,lat:36.573799,lng: 136.665524,icon: ‘tam28.gif’ //東山北観光駐車場イメージgif
},
{name: ‘<table><tr><td>東山観光駐車場</td></tr><tr><td >午前7時~午後10時<br>収容台数:15台</td></tr></table>’,lat:36.573087,lng: 136.665389,icon: ‘tam29.gif’ //東山観光駐車場イメージgif
},
{name: ‘<table><tr><td>東山河畔観光駐車場</td></tr><tr><td >午前7時~午後10時<br>収容台数:14台</td></tr></table>’,lat:36.571628,lng: 136.665982,icon: ‘tam30.gif’ //東山河畔観光駐車場イメージgif
}
];
function initMap() {
// 地図の作成
var mapLatLng = new google.maps.LatLng({lat: markerData[0][‘lat’], lng: markerData[0][‘lng’]}); // 緯度経度のデータ作成
map = new google.maps.Map(document.getElementById(‘map’), { // #mapに地図を埋め込む
center: mapLatLng, // 地図の中心を指定
zoom: 15 // 地図のズームを指定
});

// マーカー毎の処理
for (var i = 0; i < markerData.length; i++) {
markerLatLng = new google.maps.LatLng({lat: markerData[i][‘lat’], lng: markerData[i][‘lng’]}); // 緯度経度のデータ作成
marker[i] = new google.maps.Marker({ // マーカーの追加
position: markerLatLng, // マーカーを立てる位置を指定
map: map // マーカーを立てる地図を指定
});

infoWindow[i] = new google.maps.InfoWindow({ // 吹き出しの追加
content: ‘<div class=”map”>’ + markerData[i][‘name’] + ‘</div>’ // 吹き出しに表示する内容
});

markerEvent(i); // マーカーにクリックイベントを追加

marker[i].setOptions({// マーカーのオプション設定
icon: {
url: markerData[i][‘icon’]// マーカーの画像を変更
}
});

}
}

// マーカーにクリックイベントを追加
function markerEvent(i) {
marker[i].addListener(‘click’, function() { // マーカーをクリックしたとき
infoWindow[i].open(map, marker[i]); // 吹き出しの表示
});
}
</script>
<script src=”https://maps.googleapis.com/maps/api/js?key=AIzaSyClHkPIxdkxBg4j7Z7k7yPxmlNyKg8sqOM&callback=initMap”
async defer></script>
<br>番号のマークをクリックすると詳細情報を表示します<br><br>
</center>
</body>
</html>

2019年3月27日

PHPについてスキルが上がってきたので、金沢のオープンデータをそのままデータベースにインポートして、そのデータベースを読み込んでGooglemapに表示するPHPプログラムを作成することにしました。そうすれば、データが更新された時に、金沢のオープンデータをそのままデータベースにインポートするだけで良いので楽です。

何を表示しようか迷ったのですが、公衆トイレにすることにしました。
400件以上あるので、処理能力の問題もあります。

まずは、金沢のオープンデータをそのままデータベースにインポートするために、データベースのテーブルを手動で作ります。
項目数は22あります。その内、経度と緯度と名称だけ取得して、マークは全部同じ・で表示してクリックしたら名称が表示されるようにします。

2019年3月28日

金沢のオープンデータをそのまま手動でデータベースにインポートするのは簡単にできました。全部で430のデータがありました。
IDをprimaryキーに設定しました。
でも、同じ施設が何か所もデータがあるのは地図上に表示するのには不向きです。
仕方が無いので手動で削除する事にしました。入場者だけしか利用できないトイレも削除しました。結局データは146になりました。これくらいなら処理の負荷も心配するほどではないと思います。
金沢城などのトイレは場所が離れていても、緯度と経度が一緒なのは怠慢だと感じました。

よく調べたらGooglemapにマークなどを表示するのはJavascriptなのですが、JavascriptとMySQLとは相性が悪く、PHPを経由してアクセスしないといけないようです。
かなり難易度が高いので断念しました。

せっかくなので、従来の方法でページを作るようにしました。

2019年3月29日

金沢の公衆トイレは、すでにGooglemapに登録されていることに気づきました。しかもマークの色と形まで一緒になっていました。
無駄な労力を費やしてしまいました。



PHPの勉強を始めました

2019年1月1日

新年に入って、時間に余裕が出来たので、PHPの勉強を始めました。
PHPはWeb上で動作するプログラム言語です。

最近、公開APIなどで、いろいろな有益なデータが公開されるようになっているのですが、そのデータをホームページ上で処理して利用するのにPHPが向いているようです。

公開API活用ガイド (I・O BOOKS)
PHPの絵本
よくわかるPHPの教科書 たにぐち まこと著
を購入していたのですが、まずは「PHPの絵本」から読み始めました。

2019年1月3日

本を読んでいて、ちょっと理解しにくいところがあって、実際に動作させたくなって、パソコン上で動作できる環境を整えようと思いました。
メルカリで購入した本で、XP環境で説明してあったりして現状に合わない部分があって、ネットで調べました。

いろいろ設定したのですが、うまくいかなくて、結局XAMPPを利用する事にしました。
https://webkaru.net/php/setup/

これで、やっとスタートしました。ここまで来るのに1日以上かかりました。

とりあえず、XAMPPのShellでコマンドプロンプト上でPHPの動作の確認ができるようになりました。

PHPの絵本を読んでいて変数(ローカル変数とグローバル変数とスタティック変数)の扱いの違いが理解しづらかったです。
判っている人が書いた参考書って、判らない人がどこが判らないのか判らず書いているので、読んでて判らないんですよね・・・
まあ、判らない人が参考書を書ける訳ないんですけど・・・・
こういうのは自分でプログラムの内容を変えてみて結果どうなるか確認するのが一番理解しやすいんですよね。

<?php
$x = 2; $y = 2;

function funcscope(){
$x = 0;
global $y;
static $z;
$x++; $y++; $z++;
print “\$x=$x, \$y=$y, \$z=$z”;
print “\n”;
$x++; $y++; $z++;
$x++; $y++; $z++;
print “\$x=$x, \$y=$y, \$z=$z”;
print “\n”;

}
print “\$x=$x, \$y=$y, \$z=”;print “\n”;
funcscope();
print “\$x=$x, \$y=$y, \$z=”;print “\n”;
funcscope();
print “\$x=$x, \$y=$y, \$z=”;print “\n”;
?>

上記がscope.phpというプログラムの場合に動作した結果

# php scope.php
$x=2, $y=2, $z=
$x=1, $y=3, $z=1
$x=3, $y=5, $z=3
$x=2, $y=5, $z=
$x=1, $y=6, $z=4
$x=3, $y=8, $z=6
$x=2, $y=8, $z=

スタティック変数の場合は初期値は0で関数内のみで存在する値で値はプログラム内では記憶している
グローバル変数の場合は関数外でも存在し値はプログラム内では記憶している
ローカル(普通の)変数の場合は関数内の値と関数外の値は別に存在している。関数内の変数の値は関数外では記憶していない

コマンドプロンプト上で動作させるだけでは、あまり役に立たないのでApache上で動作させたいと思い、Apacheの起動をしてみました。
でも、XAMPPのApacheで使うPort 80が他で使われていてApacheの起動ができません。

https://php1st.com/946
を参考にコマンドプロントでnetstat -nao を動作してローカルアドレスの数字が80のPIDを調べると4でした。
タスクマネージャーの詳細を確認するとSystem (NT Kemel & System)になっていました。

http://lovee7.blog.fc2.com/blog-entry-35.html
を参考に、[Windowsのスタートボタンを右クリックしてコントロールパネル] → [プログラム] → [プログラムと機能] → [Windowsの機能の有効化または無効化]で「Windowsの機能」ダイアログを表示させます。
「インターネット インフォメーション サービス」の項目を開いて、「World Wide Web サービス」のチェックを外しました。

XAMPPを管理者として実行(アイコンを右クリックで管理者として実行)する。
Apacheが起動しました。
Attempting to start Apache service.
が表示されましたが、それ以降進みません。
https://lightning2014.ensyutsubu.com/blog/post-6335/
を参考にして
XAMPP Control Panelで「Apache」の左側についたチェックを押すと×マークになります。
これでApacheの起動するようになりました。 ここまでの道は長かったです。
結局、最初にXAMPPを使わないでApacheが動作しなかった原因も、Port 80が他で使われていた事が原因だったようです。

c:/xampp/htdocs/ に動作するPHPファイル(例えば test.php)を設置してあれば
XAMPP Control PanelでApacheとMySQLをStartさせて
http://localhost/test.php
でtest.phpを動作させることができます。

2019年1月4日

実際にPHPのファイルを動作させてみましたが、日本語は文字化けしました。
c:/xampp/php/ のphp.iniを書き換えると解決するということなんですが、
PHPの絵本では、文字コードEUC-JPにすると書いてあったので、その通りにしても解決しなく
本が古いので、新しい環境(Windows10)に合わせたほうが良いのかなと思って
https://techacademy.jp/magazine/2412 を参考に
文字コードUTF-8にして保存してみたのですが、やっぱり解決しません。

2019年1月5日

結果的には文字コードUTF-8にするのが正解だったのですが、PHPのファイルを作る際にも、UTF-8で入力しなければいけなかったのです。
https://hombre-nuevo.com/programming/%E3%80%90php%E3%80%91%E6%96%87%E5%AD%97%E5%8C%96%E3%81%91%E5%AF%BE%E7%AD%96%E3%81%AE%E3%81%9F%E3%82%81php%E3%82%92%E6%97%A5%E6%9C%AC%E8%AA%9E%E5%8C%96%E3%80%90xampp%E3%80%91/
が参考になりました。

これで、やっと日本語を使ったPHPのファイルをパソコン上で動作させる環境が整いました。
これだけの事で、これほど苦労させられるなんて、先が思いやられます。

次はサーバー上で動作できるように設定です。
サーバーでの設定の変更は、サーバーごとに違うんだと思いますが、自分が利用しているサーバーcoreserverの場合は、coreserverにログインして、サイト設定でPHPのバージョンをphp72に変更です。

早速、XAMPP上で動作したphpファイルをFTPでアップロードして、属性を全部実行可(755)に設定し動作を試してみました。
無事動作しました。やったね!

2019年1月12日

XAMPP上で、phpファイルとhtmlファイルの両方を動作させるプログラムを試してみたのですが、htmlファイルで文字化けしてしまいました。
htmlファイルのみシフトJISにすると正常に動作しました。

「PHPの絵本」を読んでいると、突然、訳のわからない関数やコマンドが出てきて、何の説明もないので、頭がパニックになり頓挫して眠くなり、なかなか進みません。
それで、判らない英単語が出たら、その都度ネットで調べる事にしました。
それで、なんとなく理解できるようになりました。
こんなものは理解しようと思って、どんだけ考えてもダメです。
分らない事は、考えるのではなく調べるのが一番です。

「PHPの絵本」って超初心者向けで評判が良いので購入したのですが、PHP書くと実際にどんなことができる?っていう意味では良い本ですが、実際にプログラムを作ってみたいなあという用途には向いていないようです。
プログラムの参考書って、スキルのない初心者が理解できるようなのって無いんですよねえ・・・

2019年1月13日

「PHPの絵本」を読んで、いきなり知らない関数や構文が出てくると、相変わらずストップしてしまいます。

ネットで調べたりして少しずつ進んできたのですが、ネットで調べても、どうしても意味が分からない部分があったのでYahoo相談室で聞いてみました。

for($i=0; $i<count($enq1); $i++) {
if($_POST[‘quest’][‘Value’] == $i) {
$ans1 = $i;
break;
}
}
でifの条件の意味が分からなく、特に$_POSTの後に[ ][ ]と2つ並んでいるところが、どういう扱いになっているのか理解できなかったのです。

ありがたいことに、すぐに回答していただけました。
$_POSTの後に[ ][ ]と2つ並んでいるところは、二次元の配列を表現しているということでした。
$_POST[‘quest’][‘Value’] の値が、0~ $enq1 の配列の数までのどれであるかを調べて $ans1 にセットしているということです。
お陰で、少しわかってきました。

1行目の$iは数字(もしくは数字のような観念)で、要素の全部をチェックするという働きで、2行目の$iはデータの内容(値 今回の場合は文字列)を表しているって事のようです。

プログラム言語はBASICやFORTRANを基に理解しようと思うのが理解しづらい原因でもあったようです。
PHPって、プログラムを最初から全部作っていくというより、決まった構文(関数)を、いろいろ組み合わせてシステムを構築していく言語のようです。
どういう構文(関数)があるか知っておくことが重要のようです。

サンプルプログラムを見ていると、どの部分が最初から決まった構文(関数)で、どこがそのプログラムのオリジナルな部分なのか見分けがつかないので、決まった構文(関数)を見て、なんでこうなるんだと余計な事を考えて嵌まってしまいます。

2019年1月14日

全部が理解できたわけでは無いけど、「PHPの絵本」をこれ以上追及しても進歩しないと思ったので、次の段階として「よくわかるPHPの教科書 たにぐち まこと著」を読むことにしました。

「よくわかるPHPの教科書 たにぐち まこと著」は初歩的なところから順序を追って説明しているので勉強しやすいと思います。
先に「よくわかるPHPの教科書 たにぐち まこと著」を読んでから「PHPの絵本」を読めばよかったと思います。

実際に、プログラムを打ち込んで動作させてみました。
なんと改行が動作しません。¥nも¥r¥nも動作しません。”ダブルクオートで囲んで
でやっと改行になりました。
print (”
“);
時間の表示をしたら、時間がずれていました。

PHPのバージョンによって動作が違うようです。先が思いやられます。

2019年1月20日

「よくわかるPHPの教科書 たにぐち まこと著」は基礎からわかりやすく説明されていて、学習が順調に進んでいます。
とりあえず基礎編を読み終わりました。

関数を知るために「PHP逆引きレシピ 第2版」をメルカリで入手しました。1280円でした。

公開APIをサイトで利用するという目的に近づいてきているような気がしています。

2019年1月21日

「PHPによるWebアプリケーション 2版 / 西沢直木」をアマゾンで購入しました。454円でした。

PHPの勉強に、かなり気合が入ってきました。

2019年1月22日

「PHPによるWebアプリケーションスーパーサンプル活用編 第3版」をメルカリで購入しました。700円でした。

2019年1月24日

「よくわかるPHPの教科書 たにぐち まこと著」を参考に、実際にコードを打ち込んで動作してみました。

動作しません・・・・・・

PHPがバージョン7(PHP7)になってから、データベース関連のコマンドが全部変わったようです。

mysqlがmysqliに変わって、パラメータの記述方法も変わったようです。

なんで、こんな重要なコマンドを変更するかなあ

参考書も、PHP7に対応した良書が存在しないだし、先が思いやられます。

mysqlをmysqliに変更して動作させると

Warning: mysqli_select_db() expects exactly 2 parameters, 1 given in C:\xampp\htdocs\index.php on line 3
のエラーが表示されました。
mysqli_select_db()は2つのパラメータを期待します。
という内容の表示のようです。

ネットで探しても解決法が見つかりません。

2019年1月25日

「mysqli_select_db()は2つのパラメータを期待します。」の解決法が判りました。
PHP7になって、データーベースの接続に関する書式が全く変わってしまったようです。

以前はxampp(パソコン上でPHPを動作させ練習する環境)では
mysql_connect(‘localhost’,’root’,”)or die(mysqli_error());
mysql_select_db(‘データベース名`) or die(mysqli_error());
でデータベースに接続できたのが
$link = mysqli_connect(“localhost”, “root”, “”) or die(mysqli_error($link));
mysqli_select_db($link,’データベース名’) or die(mysqli_error($link));
としないとけないようです。

mysqli_query(‘SET NAMES UTF8′); もmysqli_query($link,’SET NAMES UTF8’);

に変更しました。

「よくわかるPHPの教科書 たにぐち まこと著」はPHP5用の教科書ですが、これだけ違うと話になりません。
「よくわかるPHPの教科書 PHP7対応版」も発売しているようなので、入手しようと思います。
「よくわかるPHPの教科書」はわかりやすいし、同じ本でPHP5用とPHP7の両方持っていれば、仕様の違いが判って、他の参考書を利用するのにも役に立ちます。
PHP7対応の参考書って本当に少ないんです。

ちなみにPHPには公式のPHPマニュアルというものがあるそうです。
http://php.net/manual/ja/index.php
でも、自分の知りたいことを探すのは簡単ではありません。

2019年1月26日

「よくわかるPHPの教科書 たにぐち まこと著」のサンプルプログラムをPHP7で動作するように改変できました。
「よくわかるPHPの教科書 PHP7対応版」は買わなくても大丈夫かな。

2019年1月30日

「よくわかるPHPの教科書 たにぐち まこと著」の2つめのサンプルプログラム(掲示板)に、かなり苦戦しています。
PHP5とPHP7の違いもあるのですが、記入漏れもあるし、プログラムの不備もあるし、説明不足もあるし、初心者がこの本で勉強しようとすると、かなり躓いて断念する可能性が大きいのではないかと思います。
とはいえ、この本より初心者向けで判りやすい本は無いんですよねえ・・

2019年1月31日

相変わらず「よくわかるPHPの教科書 たにぐち まこと著」の2つめのサンプルプログラム(掲示板)に苦戦しています。
なんとかサンプルプログラムのソースファイルを入手できないか、ネットで調べたら見つかりました。
マイナビBOOKSというサイトにソースファイルの圧縮データと正誤表がありました。
https://book.mynavi.jp/support/pc/php/

購入した本は第9刷で間違ったところは訂正済みの本でした。
でも、ソースファイルと本の内容が一致しません。ソースファイルには本に掲載されていない内容が含まれています。そりゃ無いよって感じです。

ひょっとしたらと思って、「よくわかるPHPの教科書【PHP7対応】」のサンプルプログラムもあるのではないかと思ったらありました。
https://book.mynavi.jp/supportsite/detail/9784839964689.html
さっそくダウンロードしました。このサンプルプログラムを参考に、学習しようと思います。

これで「よくわかるPHPの教科書【PHP7対応】」無しでも学習できそうです。

2019年2月3日

「よくわかるPHPの教科書 」で勉強していると、PHPをマスターする際にはSQLの理解が必須だということがわかり、SQLの参考書「これならわかるSQL 入門の入門 五十嵐貴之著」を購入しました。

2019年2月8日

「よくわかるPHPの教科書【PHP7対応】」の掲示板のサンプルプログラムで、どうしても理解できない部分があって、YAHOO知恵袋で相談しました。すぐに答えてくれる方がいて、参考になりました。

$member = $db->prepare(‘SELECT COUNT(*) AS cnt FROM members WHERE email=?’);
$member->execute(array($_POST[‘email’]));
$record = $member->fetch();
if ($record[‘cnt’] > 0) {
$error[‘email’] = ‘duplicate’;
}

の1行目について最初のemail=?の意味はプリペアドステートメントを利用する際のお約束で、?の内容を後から指定するっていう意味で、メールアドレスの入力で?の中身が変わったり、「自動で」SQL実行時に必要なエスケープを施してくれるメリットがあるから?を使っているそうです。
$db->prepare() でプリペアドステートメントとしてデータベースdbにおいて、email=?の条件に合致するデータの数をcntとするという内容の$memberというSQL文 を指定します。

2行目は画面で入力した値($_POST[‘email’])をemail=?の?に代入し、$memberの内容を実行する。

3行目は結果を取得してcntの値を$recordという配列として登録

4行目は$memberの内容を実行して得られた条件を満たすデータ数$record[‘cnt’]が0より大きい(つまり他にもある)場合には$error[‘email’]にduplicateという文字を登録する

という処理のようです。
プリペアドステートメントの勉強も必要なようです。

https://www.ibm.com/support/knowledgecenter/ja/SSEPGG_9.1.0/com.ibm.db2.udb.apdv.php.doc/doc/r0022472.htm
https://bituse.info/php/35
も参考になりました。

2019年2月9日

「これならわかるSQL 入門の入門 五十嵐貴之著」の勉強を始めました。
なかなか分かりやすいです。ただ、XAMPP上でMySQLを操作する方法が本の操作方法と違うので戸惑いました。
データはネットからダウンロードできるのですが、txtデータなので、UTF-8で保存しなおして、インポートすると使えました。

コマンドラインの入力はXAMPP上でMySQLのAdminからSQLのボタンをクリックして入力します。

2019年2月10日

「これならわかるSQL 入門の入門 五十嵐貴之著」の勉強が完了しました。
入門の入門なので初歩的な内容だと思うけど、SQLについて、かなり理解できたと思います。
読んでよかったです。
これでPHPの理解が深まると思います。
「PHPの絵本」を、もう一度読んでみようと思います。

2019年2月11日

「PHPの絵本」を改めて読んでみました。
PHPのプログラム見て、文法的に、なんかよく理解できないなあと思っていたところが、ちゃんと説明されていたりして勉強になりました。
「PHPの絵本」はサンプルプログラムが理解しづらいし、説明も不親切だし、データのダウンロードもできないのですが、初歩的な文法は丁寧に説明されていてわかりやすいです。
サンプルプログラムは無視して読んだ方が良いと思います。

PHPの勉強を始める場合は、「これならわかるSQL 入門の入門 五十嵐貴之著」を勉強してから、「PHPの絵本」をサンプルプログラムを無視して勉強し、その後「よくわかるPHPの教科書【PHP7対応】」を読むことをお奨めします。それを終わってから「PHPの絵本」を読み直すのも良いと思います。

2019年2月17日

「よくわかるPHPの教科書 」の掲示板のサンプルプログラムについて勉強しています。
テキストの説明が丁寧では無いので、ちょっとしたところで判らなくなります。
ネットやPHPの他の参考書を見ても理解できない場合は、「Yahoo相談室」に相談しました。
PHPの詳しい人が根気よく説明して下さって、かなり理解が深まりました。どれだけ感謝してもしきれません。

POSTデータ($_POST)とセッションデータ($_SESSION[‘セッション名’])が同じ値のデータであっても、header(‘Location: でページが変わった場合、セッションデータは記憶されたままですがPOSTデータは消えてしまう

fetch() を使うのは、データベースから値を取得する際に使い、POSTデータ($_POST)とセッションデータ($_SESSION[‘セッション名’])を使う場合には不要。

のform内の処理が終わると、そのページの先頭に飛ぶ。

ちなみに、「よくわかるPHPの教科書 」の掲示板のサンプルプログラムについて、
サンプルプログラムをダウンロードしてXAMPP上で動作させると、
Notice: Undefined index:
が大量に表示されるし、会員登録で写真の表示がされず、会員登録後の掲示板投稿で投稿内容が登録されず投稿画面に戻ります。
正常に動作しないプログラムだと判ると、ソースファイルで勉強するモジベーションが下がります。

2019年2月21日

会員登録後の掲示板投稿で投稿内容が登録されず投稿画面に戻る件は、投稿データベースのフィールド名が一箇所入力ミスしていました。

会員登録で写真の表示がでない件は、画像のアップロードがされていませんでした。
でも、会員登録のデータベースには画像のファイル名が登録されています。
いろいろ調べて、原因がわかりました。画像ファイルのアップロード先のフォルダmember_pictureの位置が間違っていました。

2019年2月23日

返信投稿した場合、返信元のメッセージという言葉だけの表示では物足りないので、返信元のメッセージの内容の一部を表示するように変更してみました。

返信元のメッセージの部分を

<?php
$countm=$post[‘reply_post_id’];
$sql = “SELECT * FROM posts WHERE id=?”;
$messages = $db->prepare($sql);
$messages->execute(array($countm));
$messagem = $messages->fetch();
echo “返信元 “.substr($messagem[‘message’],0,20).”・・・”;
?>

に書き換えました。正常に動作しました。
reply_post_id は、返信元のIDです。

ちょっと自信がついてきました。

2019年4月14日

PHPも、かなり上達して、PHPを利用した実用的なプログラムもいくつも作りました。
https://kimassi.net/yadoitiran
https://kimassi.net/hudousan/hudousan
https://kimassi.net/hudousan/1/kodate1
https://kimassi.net/toire.html

メルカリで「詳細!PHP7+MySQL入門ノート/大重美幸著」を購入しました。1600円でした。
PHP7になってから、特にMySQLとの接続のコマンドが大幅に変更になったので、古いテキストだと使えない部分が多いんです。
1冊くらいは、PHP7に対応している本を持っていないと不便なんです。

2019年4月15日

「詳細!PHP7+MySQL入門ノート/大重美幸著」が届きました。
サンプルプログラムは無いですが、基本的な重要点がわかりやすく説明されている良書だと思います。