phpでのPDO

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
まーくん
記事: 11
登録日時: 11年前

phpでのPDO

#1

投稿記事 by まーくん » 11年前

始めまして。会員登録して初めての投稿となります。フォーラムルールは読んできましたが、間違いがあればご指摘願います。
ちなみにドットインストール様の講義?を受けてのコードです。

<訂正>
2014/01/08 9:24 phpタグの書き忘れを追加

<今回使用するphp,htmlファイル>
confing.php : requireするための設定用ファイル。
index.php : 表示用
thanks.html : 登録完了用(今回は「登録完了しました」と表示するのみなので割愛しました。)
function.php : よく使う関数をまとめたもの。

"http://develop.com/"は私のローカル開発環境です

config.php

コード:


<?php

/*

create database dotinstall_contacts_php;
grant all on dotinstall_contacts_php.* to root@localhost identified by 'masataka';

use dotinstall_contacts_php

create table entries(
	id int not null auto_increment primary key,
	name nvarchar(255),
	email nvarchar(255),
	memo text,
	created datetime,
	modified datetime
);

*/

define('DSN', 'mysql:host=localhost;dbname=dotinstall_contacts_php');
define('DB_USER', 'root');
define('DB_PASSWORD', '********');

define('SITE_URL', 'http://develop.com/');
define('ADMIN_URL', SITE_URL.'admin/');

error_reporting(E_ALL & ~E_NOTICE);

session_set_cookie_params(0,'/contacts_php/');

?>
functions.php
<?php

コード:

function connectDb(){
	try {
		return new PDO(DSN,DB_NAME,DB_PASSWORD);
	} catch (PDOException $e) {
		echo $e->getMessage();
		exit;
	}
}

function h($s){
	return htmlspecialchars($s, ENT_QUOTES, "UTF-8");
}

function setToken(){
	if (!isset($_SESSION['token'])){
		$_SESSION['token'] = sha1(uniqid(mt_rand(),true));
	}
}

function checkToken(){
	if (empty($_POST['token']) || $_POST['token'] != $_SESSION['token']){
		echo "不正な処理";
		exit;
	}
}
?>
index.php

コード:

<?php
require_once('config.php');
require_once('functions.php');

session_start();


if($_SERVER['REQUEST_METHOD'] != "POST"){
	//CSRF対策:トークン(一意の文字列)を生成、投稿前後で整合性チェック
	##投稿前
	setToken();
}else{
	##投稿後
	checkToken();

	$name = $_POST['name'];
	$email = $_POST['email'];
	$memo = $_POST['memo'];

	$error = array();

	##エラー処理
	if (!filter_var($email,FILTER_VALIDATE_EMAIL)){
		$error['email'] = 'メールアドレスの形式が不正です。';
	}
	if ($email == ""){
		$error['email'] = 'メールアドレスを入力してください。';
	}
	if ($memo == ""){
		$error['memo'] = "内容を入力してください。";
	}

	if (empty($error)){
		##DB格納
		$dbh = connectDb();

		$sql = "insert into entries (name, email, memo, created, modified) values (:name, :email, :memo, now(), now())";

		$stmt = $dbh -> prepare($sql);

		$params = array(
			":name" => $name,
			":email" => $email,
			":memo" => $memo
			);

		$stmt -> execute($params);

		//go to thanks page
		header('Location:'.SITE_URL.'thanks.html');
		exit;

	}
}

 ?>
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>お問い合わせフォーム</title>
	</head>
	<body>
		<h1>お問い合わせフォーム</h1>
		<form method="POST" action="">
			<p>お名前:<input type="text" name="name" value=""></p>
			<p>メールアドレス*<input type="text" name="email">
			<?php if ($error['email']) { echo h($error['email']); } ?>
			</p>
			<p>内容*:</p>
			<p><textarea name="memo" cols="40" rows="5"></textarea></p>
			<?php if ($error['memo']) { echo h($error['memo']); } ?>

			<p><input type="submit" value="送信"></p>

			<input type="hidden" name="token" value="<?php echo h($_SESSION['token']); ?>">
		</form>
	</body>
</html>
ここまで大前提のコードです。
以下大きく2点のエラーがあります。googleでは検索済みですが、解決策が見当たらず、自分なりに試行錯誤してみました。

<エラー1-PDO->
見ての通り、config.phpでPDO用にDB_NAME,DB_PASSWORD,DSNをdefineし、functions.phpでconnectDbでPDOをnewしています。
DB_NAME,DB_PASSWORD,DSN全てに間違いはないのですが、index.phpのフォームでPOST送信するとinvalid data source nameとエラーを吐きます。

自分なりの対応策として、まずconfig.phpの

コード:

define('DSN', 'mysql:host=localhost;dbname=dotinstall_contacts_php');
define('DB_USER', 'root');
define('DB_PASSWORD', '********');
をindex.php内先頭に移しました。すると、invalid data source nameは消えるもSQLSTATE[28000] [1045] Access denied for user 'DB_NAME'@'localhost' (using password: YES)と出てきます。DB_NAMEは間違っていません。
試しにfunction.php内部に移しても同じSQLSTATE[28000] [1045] Access denied for user 'DB_NAME'@'localhost' (using password: YES)と出てきます。

但し、function.phpで

コード:

define('DSN', 'mysql:host=localhost;dbname=dotinstall_contacts_php');
// define('DB_USER', 'root');
define('DB_PASSWORD', '********');


function connectDb(){
	try {
		return new PDO(DSN,'root',DB_PASSWORD);
	} catch (PDOException $e) {
		echo $e->getMessage();
		exit;
	}
}
と、defineをコメントアウトし、new宣言するときに直にrootと入力すると成功しました。
つまり、ユーザ名は間違っていないと考えるのですがおかしいでしょうか。


<エラー2>

コード:

define('SITE_URL', 'http://develop.com/contacts_php/');
header('Location:'.SITE_URL.'thanks.html');
とすると、飛んだ先のURLがhttp://develop.com/contacts_php/SITE_URLthanks.htmlとなってしまいます。
ほしい結果は、http://develop.com/contacts_php/thanks.htmlです。
エラー1からの直感で、このdefineをindex.php先頭に持って行きました。
すると、正常に行きます。

<問題点のまとめ>
  • config.php内においてのみinvalid data source nameがでてくること
  • DB_NAMEは正しいのにdefineされている時のみSQLSTATE[28000] [1045] Access denied for user 'DB_NAME'@'localhost' (using password: YES)が出てくること
以上です。
解決策と、どうしてconfig.php内部でdefineするときのみ失敗するのか知りたいです。不慣れで稚拙な文で申し訳ありませんがよろしくお願いいたします。

OS;Window
知識:基本情報技術者取得済み,プログラミングは2年。
最後に編集したユーザー まーくん on 2014年1月08日(水) 09:25 [ 編集 2 回目 ]

Poco
記事: 161
登録日時: 14年前

Re: phpでのPDO

#2

投稿記事 by Poco » 11年前

PHPは良くわかっていませんが、localhostを127.0.0.1に変更するとどうでしょうか?
「mysql localhost 」をgoogle検索にかけると、「127.0.0.1 違い」が補完候補に挙がります。

アバター
h2so5
副管理人
記事: 2212
登録日時: 14年前
住所: 東京
連絡を取る:

Re: phpでのPDO

#3

投稿記事 by h2so5 » 11年前

config.phpのエラーはスクリプトが <?php で始まっていないのが原因では?

まーくん
記事: 11
登録日時: 11年前

Re: phpでのPDO

#4

投稿記事 by まーくん » 11年前

Poco さんが書きました:PHPは良くわかっていませんが、localhostを127.0.0.1に変更するとどうでしょうか?
「mysql localhost 」をgoogle検索にかけると、「127.0.0.1 違い」が補完候補に挙がります。
返事有り難うございます。
試した所、結果は変わらずでした。

まーくん
記事: 11
登録日時: 11年前

Re: phpでのPDO

#5

投稿記事 by まーくん » 11年前

h2so5 さんが書きました:config.phpのエラーはスクリプトが <?php で始まっていないのが原因では?
返事有り難うございます。
申し訳ありません、投稿記事に"<?php ?>"を書き忘れていましたが、実際のコードには書かれています。
なので、その原因ではありません。

訂正できるようでしたら元記事を訂正しておきます。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: phpでのPDO

#6

投稿記事 by みけCAT » 11年前

config.phpにDB_NAMEの定義が無いようです。
DB_USERの間違いではないですか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

まーくん
記事: 11
登録日時: 11年前

Re: phpでのPDO

#7

投稿記事 by まーくん » 11年前

みけCAT さんが書きました:config.phpにDB_NAMEの定義が無いようです。
DB_USERの間違いではないですか?
返事有り難うございます。
仰るとおりDB_USERとDB_NAMEの間違いでした。

コードを見なおせばわかったことなのに、うっかり見落としてしまっていました。お恥ずかしい限りです。

config.phpを

コード:

		return new PDO(DSN,DB_USER,DB_PASSWORD)
と直した所、名前を直打ちすると成功する、というエラーは解消されました。ありがとうございました。

只、
相変わらずconfig.php内でdifineする場合のみ、invalid data source nameと表示されてしまいます。

以前も似たようなエラーがあったのですが、DSNをindex.phpに置くと成功していました。requireするとだめなのでしょうか。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: phpでのPDO

#8

投稿記事 by みけCAT » 11年前

参考にしているのはここですね?
お問合せ管理システムを作ろう (全21回) - プログラミングならドットインストール

invalid data sourceが出るというのはDB接続の設定ミス(typoなど)が疑われますが、直打ちするとでないというのは気になりますね。
echoなどでDSNの中身が正しいかを確認してみてください。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

まーくん
記事: 11
登録日時: 11年前

Re: phpでのPDO

#9

投稿記事 by まーくん » 11年前

返事有り難うございます、お付き合いいただいて申し訳ないです。

はい、そのリンク先で間違いないです。

echo でDSNを表示させてみました
index.php上部に

コード:

echo DSN;
を入力した所、
mysql:host=localhost;dbname=dotinstall_contacts_php
と出ました。

私が見る限りあっているように思います。
念のためmysqlのdbnameを確認しましたが間違っていないです。

まーくん
記事: 11
登録日時: 11年前

Re: phpでのPDO

#10

投稿記事 by まーくん » 11年前

応えてくださった皆様ありがとうございます。

少しエラーの改善と、エラーの起きる条件が判明しましたので報告させていただきます。

<エラー2>
今回はエラー2についてです。

問題点は親記事を見ていただきたいのですが、
define('ADMIN_URL', SITE_URL.'admin/');
と定義されていて、
<a href="<?php echo ADMIN_URL ?>">管理者メニューへ</a>
とタグを貼ると、
"http://develop.com/contacts_php/admin/"
となってほしいのですが、何故か
http://develop.com/contacts_php/ADMIN_URL
となってしまうのが現状です。

試行錯誤した結果ですが、
直接トップページに当たるindex.phpのみ、このエラーが発生することがわかりました。
他のページでリンクを張った際、そのページの頭で定義しなおさなくても正常に飛ぶことができました。
但し、トップページのindex.phpのみrequire_onceでconfig.phpを読み込んでも、エラーが起き、index.php頭で定義し直す必要がありました。

こういったエラー条件の特定はあまり役に立ちませんかね…
どうしてでしょうか…

閉鎖

“C言語何でも質問掲示板” へ戻る