Как создать социальную сеть. Реализуем добавление в друзья на PHP

Недавно ко мне обратился один человек с просьбой написать статью о том, как на PHP самому реализовать систему а-ля "друзья-подписчики" (т.е. сегодня мы начнем разбираться, как создать свою социальную сеть с нуля). Еще он упомянул, что освоил один из движков, но считает это недостаточным для настоящего php-программиста, посему далее дам пару рекомендаций:

1) Все правильно: движок это одно, а понимать и хорошо разбираться в языке - совсем другое, поэтому весьма рекомендуется побольше всего делать с чистого листа.

 

2) Освойте PDO (класс PHP для работы с базами данных) и работайте с prepared statements. Это не так и сложно. И лучше сразу, чем потом переучиваться, и не смотрите, что я в статье везде пишу mysql_query и т.п., это для простоты, а на деле нужно делать все с головой. Туториалов по PDO, кстати, хватает; на крайняк попросите у меня, напишу при необходимости =)

3) Заодно, если вы новичок, осваивайте ООП - даже если сами использовать не будете, пригодится хотя бы в чужом коде разбираться.

Ну а теперь перейдем к созданию нашей системы подписчиков.

Итак, перед тем, как продумать структуру таблиц, нужно определиться, как все должно работать. Допустим, у нас есть пользователи в какой-то таблице `users`, и у каждого свой `id`. Один юзер может подать заявку на добавление в список друзей другого юзера: если тот одобрит - они друзья, если нет - этот первый просто остается подписчиком.

Вот наша таблица пользователей: 
CREATE TABLE `users` (`id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`login` VARCHAR( 25 ) NOT NULL ,
`name` VARCHAR( 255 ) NOT NULL ,
`city` VARCHAR( 255 ) NOT NULL
) ENGINE = MYISAM ;

* Разумнее было бы сделать отдельную таблицу `cities`, чтобы в этой для экономии места хранить только числовой id города, а не строковое полное название, но это сделано для простоты примера, так что не берите в голову.

Сначала я хотел сделать 2 таблицы, потом решил, что их будет 3: для запросов, друзей и для подписок.

На самом деле сделать можно как угодно, не бойтесь экспериментировать, думать и переделывать, пока вы учитесь. Я реализовал один из возможных вариантов - это не значит, что он единственный верный. Если у вас будут идеи получше, буду только рад.

В общем, первая такая:
CREATE TABLE `requests` (
`user1` INT UNSIGNED NOT NULL ,
`user2` INT UNSIGNED NOT NULL ,
PRIMARY KEY ( `user1` , `user2` )
) ENGINE = MYISAM ;

Очень простая таблица, всего два поля. В поле `user1` указывает, кто запрос отправил, в `user2` - от кого ждем подтверждения. Как видите, первичный ключ состоит из двух полей, это значит, что одна и та же комбинация из ID пользователей не может повторяться.

Друзья:
CREATE TABLE `friends` (
`friend1` INT UNSIGNED NOT NULL ,
`friend2` INT UNSIGNED NOT NULL
PRIMARY KEY ( `friend1` , `friend2` )
) ENGINE = MYISAM ;

Подписки:
CREATE TABLE `subscriptions` (
`subscriber` INT UNSIGNED NOT NULL ,
`the_followed` INT UNSIGNED NOT NULL ,
PRIMARY KEY ( `subscriber` , `the_followed` )
) ENGINE = MYISAM ;

По сути, таблицы такие же, как и первая, просто данные в них будут храниться другие, хоть и в том же виде.

Ну-с, давайте к практике! Допустим, мы берем из базы список всех пользователей и выводим подряд вместе с кнопкой:

while ( $row = mysql_fetch_assoc($result) ) {

 echo '<p>' . $row["name"] . " <a href=\"index.php?add=" . $row["id"] . "\">Добавить в друзья</a></p>";
}

Впоследствии это действие мы будем обрабатывать как-то так:

// в самом верху
session_start();

// тоже где-то вверху
$my_id = (int) $_SESSION['user_id']; // помним, что сначала нужно значение этой переменной где-нибудь сохранить в массив $_SESSION

// ну и сама обработка
if ( isset($_GET['add']) ) {
 
 $add = (int)$_GET['add'];
 if ( !empty($add) ) {
 mysql_query( "INSERT INTO `requests` (`user1`, `user2`) VALUES ({$my_id}, {$add})" );
 }
}

На странице со списком наших друзей скрипт будет выполнять что-то наподобие этого:

$result = mysql_query( "SELECT * FROM `requests` WHERE `friend2` = {$my_id}" );

if ( $row = mysql_fetch_assoc($result) ) {
 
 echo "<p>От вас ожидают подтверждения следующие пользователи:</p>";
 
 do {
 
 $user_res = mysql_query("SELECT * FROM `users` WHERE `id` = {$row['friend1']}");
 
 echo "
 <div>
 <p>" . $row["name"] . ", " . $row["city"] . "</p>
 <p><a href=\"index.php?approve=" . $row["id"] . "\">Одобрить</a> <a href=\"index.php?reject=" . $row['id'] . "\">Отклонить</a></p>
 </div>
 ";
 }
 while ( $row = mysql_fetch_assoc($result) );
}

Если кто-то подтверждает вашу заявку на добавление в друзья, наш скрипт будет работать приблизительно по следующему принципу:

$my_id = (int) $_SESSION['user_id'];
$another_id = (int) $_GET['approve'];

$friend1 = min($my_id, $another_id);
$friend2 = max($my_id, $another_id);

/*
Я решил, что так потом будет проще делать выборку из БД, если понадобится (мы знаем, что вначале будет меньший ID), ведь лучше так:
... WHERE `user1` = {$friend1} AND `user2` = {$friend2}
чем так:
... WHERE (`user1` = {$my_id} AND `user2` = {$another_id}) OR (`user1` = {$another_id} AND `user2` = {$my_id})
*/

mysql_query( "INSERT INTO `friends` ( `friend1`, `friend2` ) VALUES ( {$friend1}, {$friend2} )" );
mysql_query( "DELETE FROM `requests` WHERE `user1` = {$another_id} AND `user2` = {$my_id}" );

Как видим, если человек соглашается (ну так и быть) добавить кого-то, то заносим их в таблицу друзей и удаляем из таблицы запросов.

А если отклоняет (сволота этакая), то выполняем что-то типа этого:

$my_id = (int) $_SESSION['user_id'];
$another_id = (int) $_GET['reject'];

mysql_query( "INSERT INTO `subscriptions` ( `subscriber`, `the_followed` ) VALUES ( {$another_id}, {$my_id} )" );
mysql_query( "DELETE FROM `requests` WHERE `user1` = {$another_id} AND `user2` = {$my_id}" );

Надеюсь, все ясно, почему так =)

Еще я забыл предусмотреть вариант, когда человек сначала отправляет вас в подписчики, а потом сам решает вас добавить, но это в принципе не проблема: нужно просто при отправлении заявки проверить в базе, нет ли в таблице `subscribers` записи, где `subscriber` = $another_id и `the_followed` = $my_id, и если есть, удалить оттуда и добавить в таблицу `friends`. Просто чтоб исключить ситуацию, когда оба друг на друга подписаны, а в друзьях не числятся.

Но это уже ваше домашнее задание... по теме "создание социальной сети с нуля" (это типа SEO %)).

На заметку:

При удалении пользователя было бы удобно использовать FOREIGN KEYs, но тогда таблицы не MyISAM нужно создавать, а InnoDB. Материалы по этому в гугле ;)

Всегда желательно минимизировать количество запросов к базе, поэтому старайтесь кэшировать их результаты (по ссылке в конце статьи), но само собой не все подряд.

Исходник можно скачать здесь.

Кстати, вопрос: может кому-то было бы интересно видеоуроки по программированию посмотреть?

 Жду с нетерпением
ваших комментариев!
 

Подписаться на RSS

Вы можете нажать "подписаться", чтобы следить за моими новостями!
Так вы всегда будете в курсе появления новостей на сайте =)
О том, что такое RSS можно прочитать здесь.

Подписаться

Подписаться на Twitter

Я специально зарегистрировался в Твиттере, чтобы вы могли следить за обновлениями на сайте =)

Подписаться

Envato marketplace А эти люди занимаются прокатом карнавальных костюмов и масок в Минске. К слову, я им делал сайт.