フレンド追加機能の実装
実装概要-簡易的なアプローチ
コンソールベースのフレンドリスト表示機能
- ユーザー認証後、サーバーがフレンド情報一覧を返却し、チャット相手を選択可能。
- フレンド追加処理はクライアントからリクエストを受け、サーバーが
friendテーブルにユーザー関係を記録。
制限事項
本プロジェクトでは厳密なフレンド制約を設けておらず、IDと名前さえ分かれば誰とでもチャット可能。より高度な制約仕様は将来的な改善候補。
テーブル設計-個別処理ファイル対応
friendテーブルはuser_idおよびfriend_idの2カラムのみを含み、複合主キーで重複登録を防ぐ。
業務ロジック-改善余地あり
ユーザーは相手の承認なしに直接フレンド追加可能。追加時にuser_idとfriend_idがDBに挿入され、検索時はJOINクエリで詳細情報を取得(パスワードは除外)。
機能制限の理由
C/C++はJavaやPHPと異なり、高レベルなフレームワークが組み込まれておらず、DB接続やクエリ処理などの詳細管理を自前で行う必要があり、複雑な業務ロジックの拡張に影響する。
最適化案
ログイン時のフレンドリストは頻繁に変化しないため、クライアント側にキャッシュすることでサーバー負荷を軽減。次回ログイン時以降に更新を反映。
SQL結合クエリ
複数テーブルから一度に情報を取得する結合クエリの実装例。
内結合(INNER JOIN):
- 両テーブルに一致するレコードのみを返却。
- 片方にマッチがない場合は結果に含まれない。
SELECT a.id, a.name, a.status
FROM user a
INNER JOIN friend b ON b.friendid = a.id
WHERE b.userid=%d
左結合(LEFT JOIN):
- 左テーブルの全レコードを返却。
- 右テーブルにマッチがない場合、該当フィールドはNULLとなる。
-
SELECT u.id, u.name, f.friendid FROM user u LEFT JOIN friend f ON u.id = f.friendid;
### コード構成
**include/public.hpp**
ADD_FRIEND_MSG // フレンド追加メッセージ種別
**include/server/chatservice.hpp**
// フレンド追加処理 void handleFriendAddition(const TcpConnectionPtr &conn, json &js, Timestamp time); // 接続情報からユーザーを特定
**include/server/friendmodel.hpp**
#ifndef FRIEND_MODEL_H #define FRIEND_MODEL_H #include "user.hpp" #include
// フレンド関係操作インターフェース class FriendModel { public: // フレンド追加 void add(int userId, int friendId);
// フレンドリスト取得(JOINクエリ)
vector<User> getFriends(int userId);
};
#endif
**src/server/friendmodel.cpp**
#include "friendmodel.hpp" #include "db.h"
// フレンド追加処理 void FriendModel::add(int userId, int friendId) { // SQL生成 char sql[1024] = {0}; sprintf(sql, "INSERT INTO friend (userId, friendId) VALUES (%d, %d)", userId, friendId);
// DB実行
MySQL db;
if (db.connect())
{
db.update(sql);
}
}
// フレンドリスト取得 vector<User> FriendModel::getFriends(int userId) { // クエリ作成 char sql[1024] = {0}; sprintf(sql, "SELECT a.id, a.name, a.status FROM user a INNER JOIN friend b ON b.friendId = a.id WHERE b.userId = %d", userId);
// 実行
MySQL db;
if (db.connect())
{
MYSQL_RES *res = db.query(sql);
if (res != nullptr)
{
// 結果解析
MYSQL_ROW row;
vector<User> userList;
while ((row = mysql_fetch_row(res)) != nullptr)
{
User user;
user.setId(atoi(row[0]));
user.setName(row[1]);
user.setStatus(row[2]);
userList.push_back(user);
}
mysql_free_result(res);
return userList;
}
}
return vector<User>();
}
**include/server/chatservice.hpp**
#include "friendmodel.hpp"
// フレンド管理オブジェクト FriendModel _friendManager;
**src/server/chatservice.cpp**
// 処理バインディング