更新した項目のみプロフィールを更新する

項目がemptyでpostされた場合は、更新なし(元のデータでupdate set)する。

$stmt2 = $dbh -> prepare("update users set age = :age, job = :job, area = :area, message = :message, icon = :icon where username = '".$username."'");
	if(!empty($_POST["age"])){
		$stmt2->bindParam(':age', $age, PDO::PARAM_STR);
	} else {
		$stmt2->bindParam(':age', $result['age'], PDO::PARAM_STR);
	}
	if(!empty($_POST["job"])){
		$stmt2->bindParam(':job', $job, PDO::PARAM_STR);
	}else {
		$stmt2->bindParam(':job', $result['job'], PDO::PARAM_STR);
	}
	if(!empty($_POST["area"])){
		$stmt2->bindParam(':area', $area, PDO::PARAM_STR);
	} else {
		$stmt2->bindParam(':area', $result['area'], PDO::PARAM_STR);
	}
	$stmt2->bindParam(':message', $message, PDO::PARAM_STR);
	if(!empty($_FILES["file"]["name"])){
		$stmt2->bindParam(':icon', $file, PDO::PARAM_STR);
	} else {
		$stmt2->bindParam(':icon', $result['icon'], PDO::PARAM_STR);
	}
    $stmt2->execute();

更新前

更新後

マッチング画面
一言メッセージがある場合のみ、表示

if(!empty($value["message"])){
						echo $value['job']."(".$value['area'].") 一言メッセージ:".$value["message"]."</div><br><br>";
					} else {
						echo $value['job']."(".$value['area'].")</div><br><br>";
					}

割とすぐできた!

あとは、1.メールの違反報告機能、2.会員検索機能 といったところでしょうか。

以下はtextreamの違反報告
なるほど、mordalか~~~

array_multisortで同じエリア・年齢のuserを、上に表示されやすくする

1.新しく登録されたユーザー順に抽出(mysqlのidをorder by id desc)
2.ログイン中のユーザーと同じ登録エリアかつ年齢が同じなら、id x 1.3 のスコア
3.ログイン中のユーザーと同じ登録エリアなら、 id x 1.2 のスコア
4.ログイン中のユーザーと同じ年齢なら id x 1.1 のスコア
5.array_multisortでスコア順にソート
6.ログイン中のユーザーと異なる異性をスコア順に表示
※新しく登録された同じエリア・年齢のユーザーが上に表示されやすくなる

<style>
#fs-s{
	font-size:small;
	color:gray;
}
#icon{
	vertical-align:top;
	float:left;
}
#profile{
	display: inline;
}
</style>
<?php
session_start();
$username = $_SESSION&#91;"username"&#93;;

$dsn = "mysql:dbname=mail;host=localhost";
$user = "hoge";
$password = "hogehoge";
 
try {
    $dbh = new PDO($dsn, $user, $password);
} catch (PDOException $e){
    print('connection failed:'.$e->getMessage());
} 

$sql = "select * from users order by id desc";
$stmt = $dbh->query($sql);

$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
// var_dump($result);

$sql2 = "select * from users where username = '".$username."'";
$stmt2 = $dbh->query($sql2);

$result2 = $stmt2->fetch(PDO::FETCH_ASSOC);
$gender = $result2["gender"];
$area = $result2["area"];
$age = $result2["age"];

$i = 0;
foreach($result as $value){
	if($value["area"] == $area){
		if($value["age"] == $age){
			$result[$i]["score"] = (int)$value["id"] * 1.3;
			$score[$i] = $result[$i]["score"];
		} else{
			$result[$i]["score"] = (int)$value["id"] * 1.2;
			$score[$i] = $result[$i]["score"];
		}	
	} else {
		if($value["age"] == $age){
			$result[$i]["score"] = (int)$value["id"]  * 1.1;
			$score[$i] = $result[$i]["score"];
		} else{
			$result[$i]["score"] = (int)$value["id"];
			$score[$i] = $result[$i]["score"];
		}
	}
	$i++;
}
array_multisort($score, SORT_DESC, $result);

switch($gender){
	case '男性':
		$img = "asset/img/female.png";
		break;
	case '女性':
		$img = "asset/img/male.png";
}

$i = 0;
foreach($result as $value){
	if($gender != $value['gender']){
		echo "<img src=\"".$img."\" id=\"icon\">";
		echo "<div id=\"profile\"><a href=\"\">".$value['username'] ."</a>:".$value['age']." <span id=\"fs-s\">".$value['gender'] ."</span><br>";
		echo $value['job']."(".$value['area'].")</div><br><br>";
	}
	$i++;
}
?>

神奈川県 男性 25-29歳がログインしていた場合

つなげると、

名前をクリックすると、相手にメールを送れるようにする。

foreach($result as $value){
				if($gender != $value['gender'] and $i < 10){
					echo "<img src=\"".$icon."\" id=\"icon\">";
					echo "<div id=\"profile\"><a href=\"?compose=new&to=".$value&#91;'username'&#93;."\">".$value['username'] ."</a>:".$value['age']." <span id=\"fs-s\">".$value['gender'] ."</span><br>";
					echo $value['job']."(".$value['area'].")</div><br><br>";
					$i++;
				}
			}

女性で登録してログインした場合

送信後

あれあれあれ?もしかして、結構できてきた!???
プロフィール編集画面をつくって、「プロフィール写真」と「一言メッセージ」を加えて、法律とセキュリティを見直したら、基本的なところはほぼ完成か?

mysql カラムを先頭に追加

Alter table add firstですね。

ALTER TABLE users ADD id int unsigned auto_increment primary key FIRST;

input formも修正します。

<input type="radio" name="gender" value="男性" checked>男性
	<input type="radio" name="gender" value="女性">女性<br>
	年齢:
	<select name="age">
	<option value="">選択してください</option>
	<option value="20歳未満">20歳未満</option>
	<option value="20-24歳">20-24歳</option>
	<option value="25-29歳">25-29歳</option>
	<option value="30-34歳">30-34歳</option>
	<option value="35-39歳">35-39歳</option>
	<option value="40-44歳">40-44歳</option>
	<option value="45-49歳">45-49歳</option>
	<option value="50-54歳">50-54歳</option>
	<option value="55-59歳">55-59歳</option>
	<option value="60-64歳">60-64歳</option>
	<option value="65-69歳">65-69歳</option>
	<option value="70-74歳">70-74歳</option>
	<option value="75-79歳">75-79歳</option>
	<option value="80歳以上">80歳以上</option>

sqlもorder by id descとします。

$sql = "select * from users order by id desc";

女性でログインすると、男性だけ表示されます。

画像を追加

switch($gender){
	case '男性':
		$img = "asset/img/female.png";
		break;
	case '女性':
		$img = "asset/img/male.png";
}

$i = 0;
foreach($gender_lists as $value){
	if($gender != $value){
		echo "<img src=\"".$img."\" id=\"icon\">";
		echo "<div id=\"profile\"><a href=\"\">".$name_lists[$i] ."</a>:".$age_lists[$i]." <span id=\"fs-s\">".$gender_lists[$i] ."</span><br>";
		echo $job_lists[$i]."(".$area_lists[$i].")</div><br><br>";
	}
	$i++;
}

問題は、年齢が近い人と、エリアが近い人をどういうロジックで計算させるかなんだが、
あれ? これはよくわからんぞ。
autoincrementのidをbase scoreにして、それにsliceした先頭2桁の年齢が近ければ点数を加算して、in_arrayで都道府県が近隣であれば更に点数を加算でOK?

usersテーブルを呼び出して異性のデータを表示する

まず、ログイン中ユーザのgenderを取得し、男性であれば女性を、女性であれば男性のプロフィールを表示して、メールを送れるようにする。

<style>
#fs-s{
	font-size:small;
	color:gray;
}
</style>
<?php
session_start();
$username = $_SESSION&#91;"username"&#93;;

$dsn = "mysql:dbname=mail;host=localhost";
$user = "hoge";
$password = "hogehoge";
 
try {
    $dbh = new PDO($dsn, $user, $password);
} catch (PDOException $e){
    print('connection failed:'.$e->getMessage());
} 

$sql = "select * from users";
$stmt = $dbh->query($sql);

while($result = $stmt->fetch(PDO::FETCH_ASSOC)){
	if($result['username'] == $username){
		$gender = $result['gender'];
	} else {
		$name_lists[] = $result['username'];
		$gender_lists[] = $result['gender'];
		$age_lists[] = $result['age'];
		$area_lists[] = $result['area'];
		$job_lists[] = $result['job'];
	}
}

$i = 0;
foreach($gender_lists as $value){
	if($gender != $value){
		echo "<a href=\"\">".$name_lists[$i] ."</a>:".$age_lists[$i]." <span id=\"fs-s\">".$gender_lists[$i] ."</span><br>";
		echo $job_lists[$i]."(".$area_lists[$i].")<br><br>";
	}
	$i++;
}

1.mail, femaleではなく、”男性”、”女性”
2.ソートにorder by を使いたいので、usersにもidのカラムが必要
3.年齢は5歳刻み
4.やはりアイコン写真が欲しい

usersテーブルにipアドレスを登録

public function register($username, $password, $gender, $age, $area, $job){
		$ip = $_SERVER["REMOTE_ADDR"];
		$password = password_hash($_POST["password"], PASSWORD_DEFAULT);
		$stmt = $this->mysqli->prepare("INSERT INTO users (username, password, gender, age, area, job, ip) VALUES(?, ?, ?, ?, ?, ?, ?)");
		$stmt->bind_param('sssssss', $_POST["username"], $password, $_POST["gender"], $_POST["age"], $_POST["area"], $_POST["job"], $ip);
		return $stmt->execute();
	}

mysql
int型だと、”.”がはじかれるので、varcharに変更します。
| student | $2y$10$kJtKFIht9YDow8rOwx…hoge | male | 20歳未満 | 東京都 | 学生 | 192168 |

alter table users change ip ip varchar(41);

OKですね。後で、ipをuniqueにすれば、同じipアドレスで重複して登録できなくなります。
| endo | $2y$10$66Cp8MFw9..hoge | male | 20-29歳 | 東京都 | 学生 | 192.168.33.1 |

さぁ~、いよいよ マッチングの設計をしていきましょう!!!

一応、facebookの「知り合いかも」のUIを見てみましょう。
「写真」「名前」「職業」「友達になる」「共通の知り合い」が表示されてますね。

プロフィール写真の表示は後からuploadする機能を追加するとして、表示項目としては、異性の「username」「age」「job」「メールを送る」ってところですかね。
あ、「一言メッセージ」も追加しときますかね。
初期の表示アルゴリズムは、「新しく登録された順」、「年齢が近い」、「登録エリアが近い」に毎回シャッフルした係数を掛けてsort って感じがいいかな。

register.php, auth.phpに性別、年齢、職業を追加

html

<?php elseif($status == "none"): ?>
	<p>ユーザ名(英数字3~32文字)、推測されにくいパスワード(英数字8~32文字)を入力してください。</p>
	<form method="POST" action="">
	ユーザ名:<input type="text" name="username">
	パスワード:<input type="password" name="password"><br>
	性別:
	<input type="radio" name="gender" value="male" checked>男性
	<input type="radio" name="gender" value="femail">女性<br>
	年齢:
	<select name="age">
	<option value="">選択してください</option>
	<option value="20歳未満">20歳未満</option>
	<option value="20-29歳">20-29歳</option>
	<option value="30-39歳">30-39歳</option>
	<option value="40-49歳">40-49歳</option>
	<option value="50-59歳">50-59歳</option>
	<option value="60-69歳">60-69歳</option>
	<option value="70-79歳">70-79歳</option>
	<option value="80歳以上">80歳以上</option>
	</select><br>
	職業:
	<select name="job">
	<option value="">選択してください</option>
	<option value="公務員">公務員</option>
	<option value="経営者・役員">経営者・役員</option>
	<option value="会社員">会社員</option>
	<option value="自営業">自営業</option>
	<option value="自由業">自由業</option>
	<option value="専業主婦">専業主婦</option>
	<option value="パート・アルバイト">パート・アルバイト</option>
	<option value="学生">学生</option>
	<option value="その他">その他</option>
	</select><br><br>
	<input type="submit" value="登録">
	</form>
	<a href="login.php">ログイン</a>
<?php else: ?>

php

($auth->register($_POST["username"], $_POST["password"], $_POST["gender"], $_POST["age"], $_POST["job"]))

auth.phpのclass

public function register($username, $password, $gender, $age, $job){
		$password = password_hash($_POST["password"], PASSWORD_DEFAULT);
		$stmt = $this->mysqli->prepare("INSERT INTO users (username, password, gender, age, job) VALUES(?, ?, ?, ?, ?)");
		$stmt->bind_param('sssss', $_POST["username"], $password, $_POST["gender"], $_POST["age"], $_POST["job"]);
		return $stmt->execute();
	}

mysql
入ってます。OK, いいね!

| kurumada   | $2y$10$3w/ZczuQsPD/xy6LThA0DuXM5KJ8T2U45nWSRq..hogehoge | male   | 40-49歳     | NULL | 経営者・役員       | NULL |

続いて、居住地を追加します。

登録地域:
	<select name="area">
	<option value="">選択してください</option>
	<option value="北海道">北海道</option>
	<option value="青森県">青森県</option>
	<option value="岩手県">岩手県</option>
	<option value="宮城県">宮城県</option>
	<option value="秋田県">秋田県</option>
	<option value="山形県">山形県</option>
	<option value="福島県">福島県</option>
	<option value="茨城県">茨城県</option>
	<option value="栃木県">栃木県</option>
	<option value="群馬県">群馬県</option>
	<option value="埼玉県">埼玉県</option>
	<option value="千葉県">千葉県</option>
	<option value="東京都" selected>東京都</option>
	<option value="神奈川県">神奈川県</option>
	<option value="新潟県">新潟県</option>
	<option value="富山県">富山県</option>
	<option value="石川県">石川県</option>
	<option value="福井県">福井県</option>
	<option value="山梨県">山梨県</option>
	<option value="長野県">長野県</option>
	<option value="岐阜県">岐阜県</option>
	<option value="静岡県">静岡県</option>
	<option value="愛知県">愛知県</option>
	<option value="三重県">三重県</option>
	<option value="滋賀県">滋賀県</option>
	<option value="京都府">京都府</option>
	<option value="大阪府">大阪府</option>
	<option value="兵庫県">兵庫県</option>
	<option value="奈良県">奈良県</option>
	<option value="和歌山県">和歌山県</option>
	<option value="鳥取県">鳥取県</option>
	<option value="島根県">島根県</option>
	<option value="岡山県">岡山県</option>
	<option value="広島県">広島県</option>
	<option value="山口県">山口県</option>
	<option value="徳島県">徳島県</option>
	<option value="香川県">香川県</option>
	<option value="愛媛県">愛媛県</option>
	<option value="高知県">高知県</option>
	<option value="福岡県">福岡県</option>
	<option value="佐賀県">佐賀県</option>
	<option value="長崎県">長崎県</option>
	<option value="熊本県">熊本県</option>
	<option value="大分県">大分県</option>
	<option value="宮崎県">宮崎県</option>
	<option value="鹿児島県">鹿児島県</option>
	<option value="沖縄県">沖縄県</option>
	<option value="海外">海外</option>
</select>

register.php

mysql

| kotori     | $2y$10$rWJ6TMpdc51Gm5aTdQocFuXG8mhjoS7...hoge | male   | 20-29歳     | 東京都    | 経営者・役員  

Yes! Good job!

続いて、ipアドレスですが、以下で取得できますね。

$_SERVER["REMOTE_ADDR"];

新規登録画面の項目をmysqlに追加していく

ここら辺は適当につくってきます。
性別、生年月日、エリア、職業あたりでしょうか。

重複登録を避けるため、ipアドレスを登録して、同じipアドレスから重複して登録できないようにしたいと思います。

ALTER TABLE users ADD gender int;
ALTER TABLE users ADD birth int;
ALTER TABLE users ADD area varchar(41);
ALTER TABLE users ADD job varchar(255);
ALTER TABLE users ADD ip int(41);

mysql> desc users;
+———-+————–+——+—–+———+——-+
| Field | Type | Null | Key | Default | Extra |
+———-+————–+——+—–+———+——-+
| username | varchar(41) | YES | UNI | NULL | |
| password | varchar(255) | YES | | NULL | |
| gender | int(11) | YES | | NULL | |
| birth | int(11) | YES | | NULL | |
| area | varchar(41) | YES | | NULL | |
| job | varchar(255) | YES | | NULL | |
| ip | int(41) | YES | | NULL | |
+———-+————–+——+—–+———+——-+
7 rows in set (0.00 sec)

現在の登録画面

<?php elseif($status == "none"): ?>
	<p>ユーザ名(英数字3~32文字)、推測されにくいパスワード(英数字8~32文字)を入力してください。</p>
	<form method="POST" action="">
	ユーザ名:<br>
	<input type="text" name="username"><br>
	パスワード:<br>
	<input type="password" name="password"><br>
	性別:<br>
	<input type="radio" name="example" value="male" checked>男性
	<input type="radio" name="example" value="femail">女性<br>
	年齢:<br>
	<select name="age">
	<option value="">選択してください</option>
	<option value="20歳未満">20歳未満</option>
	<option value="20-29歳">20-29歳</option>
	<option value="30-39歳">30-39歳</option>
	<option value="40-49歳">40-49歳</option>
	<option value="50-59歳">50-59歳</option>
	<option value="60-69歳">60-69歳</option>
	<option value="70-79歳">70-79歳</option>
	<option value="80歳以上">80歳以上</option>
	</select><br>
	年齢:<br>
	<select name="job">
	<option value="">選択してください</option>
	<option value="公務員">公務員</option>
	<option value="経営者・役員">経営者・役員</option>
	<option value="会社員">会社員</option>
	<option value="自営業">自営業</option>
	<option value="自由業">自由業</option>
	<option value="専業主婦">専業主婦</option>
	<option value="パート・アルバイト">パート・アルバイト</option>
	<option value="学生">学生</option>
	<option value="その他">その他</option>
	</select><br><br>
	<input type="submit" value="登録">
	</form>
	<a href="login.php">ログイン</a>
<?php else: ?>

マッチングサイトの新規登録画面

東カレデート、pairs、omiaiにしてもfacebook連携ばっかりだな。。

YYC
性別、ニックネーム、パスワード、生年月日、登録地域、職業、利用目的

なるほど、性別・生年月日は必須として、登録地域・職業もあるといいですね。

ハッピーメール
性別、居住地、年齢、ニックネーム、求めるお相手(メル友、遊び友達、恋人)

ハッピーメールは項目が少なくライトですね。

ゼクシィ縁結び
名前、フリガナ、ニックネーム、生年月日、性別、居住地、パスワード、キャンペーンコード

マッチングでは、写真・年収あたりが大事な気がしますが、どこも写真のアップロードはないですね。。

in_arrayで送信したアドレスが存在するかチェックする

$sql = "select * from users";
			$stmt = $dbh2->query($sql);
			while($result = $stmt->fetch(PDO::FETCH_ASSOC)){
				$users[] = $result['username'];
			}

   			$sql2 = "select * from sends where username = '".$username."' order by sendtime desc";
			$stmt2 = $dbh2->query($sql2);

			while($result = $stmt2->fetch(PDO::FETCH_ASSOC)){
				$id[] = $result['mid'];
				$to = $result['destination'];
				if(in_array($to, $users)){
					$suc[] = "送信済み"; 
				} else {
					$suc[] = "宛先のアドレスが存在しません"; 
				}
				$destination[] = $to;
				$subject[] = $result['subject'];
				$sendtime[] = $result['sendtime'];
			}

			$i= 0;
			echo "<table>";
			foreach($destination as $value){
				echo "<tr><td> <img src=\"icon.png\"> <a href=\"?path=mailrp&inbox=".$id&#91;$i&#93;."\">".$value ."</a></td><td><a href=\"?path=mailrp&inbox=".$id&#91;$i&#93;."\">". $subject[$i]."</a> </td><td>" .$sendtime[$i]. " </td><td>".$suc[$i]."</td></tr>";
				$i++;
			}
			echo "</table>";

おお、メール機能の基本的なところは大分出来てきた!

次は、register時における性別、年齢などusersのカラムを増やして、メールボックスにfacebookのように、「知り合いかも?」で、異性のプロフィールを表示させてマッチングさせる機能を付けたいですね。

phpでメールボックスをつくろう8 メールのユニークIDをautoincrementからランダムな英数字にする

推測されないようにします。

$str = array_merge(range('a','z'), range('0', '9'), range('A', 'Z'));
	$r_str = null;
	for($i = 0; $i < 8; $i++){
		$r_str .= $str[rand(0, count($str) - 1)];
	}
	$mid = $r_str;

いいですね~!

続いて、send itemsで、メールが送信できたか否かを表示したいと思います。