ちなみにドットインストール様の講義?を受けてのコードです。
<訂正>
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/');
?>
<?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;
}
}
?>
<?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', '********');
試しに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;
}
}
つまり、ユーザ名は間違っていないと考えるのですがおかしいでしょうか。
<エラー2>
define('SITE_URL', 'http://develop.com/contacts_php/');
header('Location:'.SITE_URL.'thanks.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('SITE_URL', 'http://develop.com/contacts_php/');をおくとhttp://develop.com/contacts_php/SITE_URLthanks.htmlとなってしまうこと。
解決策と、どうしてconfig.php内部でdefineするときのみ失敗するのか知りたいです。不慣れで稚拙な文で申し訳ありませんがよろしくお願いいたします。
OS;Window
知識:基本情報技術者取得済み,プログラミングは2年。