PHP Урок 29. Сообщества.
Предыдущие уроки:
Программируем на PHP - Введение
PHP - Запросы от браузера к серверу
PHP - Как работает сервер
PHP - Урок 4. PHP - интерпретатор
PHP - Урок 5. Переменные сервера и глобальные переменные
PHP - Урок 6. Конструкции print и echo. Кавычки одинарные и двойные и конкатенация строк
PHP - Урок 7. Переменные, константы и условия
PHP - Урок 8. Точка входа в приложение. Настройка mod_rewrite и файл .htaccess
PHP - Урок 9. Массивы и switch. Кодим основной каркас
PHP - Урок 10. COOKIE
PHP - Урок 11. Функции. Добавляем ядро системы core.php
PHP - Урок 12. Обзор модели MVC. Добавляем шаблоны страниц в наше приложение
PHP - Урок 13. Введение в базы данных и SQL. СУБД MySQL. Подключаемся к БД из нашего приложения
PHP - Урок 14. Регистрация пользователей на сайте
PHP Урок 15. Авторизация пользователей
PHP. Урок 16. Проверка авторизации. Функция check().
PHP Урок 17. Добавляем CSS фреймворк Bootstrap и jQuery
PHP Урок 18. Загрузка файлов на сервер
PHP Урок 19. Добавляем меню навигации
PHP Урок 20. Создаем AJAX (JavaScript) API
PHP Урок 21. Циклы
PHP Урок 22. Данные пользователя.
PHP Урок 23. Подписчики и подписки
PHP Урок 24. Отправка и сохранение пользовательских постов
PHP Урок 25. Лента новостей.
PHP Урок 26. Прикрепление контента к постам
PHP Урок 27. Комментарии к постам
PHP Урок 28. Лайки
Теория
Сообщества были придуманы для оъединения людей по их интересам. Одна из функций соцсетей не только читать новости от знакомых или интересных вам людей, а также находить новых. В этом помогают сообщества. Хотя не во всех соцсетях сообщества имеются как таковые. Например в Твиттера и ыв Голосе люди находят посты друг друга по тегам (в твиттере их называют хеш-тегами и пишут внутри сообщения с символом решетки впереди). А например в ВК есть и то и другое. В своей сети хэш-теги я не доделал, так что оставляю это интузиастам. А вот сообщества в ней изначально планировались как медиацентры. Идея стояла следующая: Любой участник может отправлять свои посты в любой медиацентр (аналогично репостам в группы в ВК). Однако администратор медиацентра может отклонить пост автора, если посчитает его негодным (не соответствующим тематике медиацентра). К таким сообществам можно добавить некоторые фишки. Например RSS-ленту для добавления в агрегаторы типо Яндекс.Новостей либо иного парсинга сторонними приложениями. Также на базе медиацентров, если позволить их администраторам управлять настройками дизайна таких медиацентров вполне можно реализовать что-то наподобие новостного сайта-агенства. В котором работают авторы и главный редактор. В общем на что хватит фантазии. Давайте посмотрим как это можно реализовать.Практика
В этом предпоследнем уроке будет достаточно много разного кода. В пинципе основное мы изучили. Так как медиацентры изначально планировались главной фишкой соцсети, то и кода в них предостаточно. К тому же их можно представить, как некоторое дополнение (соцсеть на соцсети). Они осуществляют свою иную логику и также реализуют дополнительные связи между таблицами. Посмотрим на таблицы.Таблицы БД
Сами медиацентры
Здесь просто таблица с информацие о медиацентре.
Она используется когда создается новый или изменяется информация о сущечтвующем медиацентре.
CREATE TABLE IF NOT EXISTS `mc_mct`
(
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`
user_id` int(10) unsigned NOT NULL,
`mct_name` varchar(255) NOT NULL,
`mct_about` text NOT NULL,
`status` tinyint(3) unsigned NOT NULL DEFAULT '1',
PRIMARY KEY (`id`),
UNIQUE KEY `mct_name` (`mct_name`),
KEY `user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=12 ;
Посты от авторов в медиацентрах
Когда автор отправляет пост из своего блога в медиацентр, то связь в этой таблице.
CREATE TABLE IF NOT EXISTS `mc_mct_post`
(
`mct_id` int(10) unsigned NOT NULL,
`post_id` bigint(20) unsigned NOT NULL,
`user_id` int(10) unsigned NOT NULL,
`status` tinyint(3) unsigned NOT NULL DEFAULT '1',
PRIMARY KEY (`mct_id`,`post_id`),
KEY `user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Сайты основанные на медиацентре
Если основатель медиацентра захочет создать сайт на основе новостей медиацентра, то сюда заносятся данные о таком сайте.
CREATE TABLE IF NOT EXISTS `mc_mct_site`
(
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`mct_id` int(10) unsigned NOT NULL,
`site_alias` varchar(80) NOT NULL,
`site_name` varchar(255) NOT NULL,
`template_id` int(10) unsigned NOT NULL,
`site_about` text NOT NULL,
`status` tinyint(3) unsigned NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `site_alias` (`site_alias`),
KEY `mct_id` (`mct_id`),
KEY `site_name` (`site_name`),
KEY `site_name_2` (`site_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
Шаблоны сайтов медиацентров
Когда создали сайт, можно выбрать шаблон. Тут хранятся данные о шаблонах для сайтов.
CREATE TABLE IF NOT EXISTS `mc_mct_templates`
(
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`template_name` varchar(255) NOT NULL,
`status` tinyint(3) unsigned NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
Участники медиацентров (кто в каких состоит)
Когда пользователь добавляется в медиацентр, связь сохраняется в этой таблице.
CREATE TABLE IF NOT EXISTS `mc_mct_user`
(
`mct_id` int(10) unsigned NOT NULL,
`user_id` int(10) unsigned NOT NULL,
`user_role` tinyint(3) unsigned NOT NULL DEFAULT '1',
`status` tinyint(3) unsigned NOT NULL DEFAULT '1',
PRIMARY KEY (`mct_id`,`user_id`),
KEY `mct_id_2` (`mct_id`),
KEY `user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Функции core.php
Вот необходимый минимум функций для работы с медиацентрами.
Принцип их постраение такой же как у рассмотренных нами ранее.
function getUserMcts($pdo, $user_id, $from, $len){
$user_id = $pdo->quote($user_id);
$sql = "SELECT id, user_id, mct_name, mct_about FROM mc_mct WHERE user_id=$user_id AND status != 0 LIMIT $from, $len";
$stmt = $pdo->query($sql);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
function getInsUserMctsCount($pdo, $user_id){
$user_id = $pdo->quote($user_id);
$sql = "SELECT COUNT(mct_id) FROM mc_mct_user WHERE user_id = $user_id AND status != 0";
$stmt = $pdo->query($sql);
$row = $stmt->fetch(PDO::FETCH_NUM);
return $row[0];
}
function getInsUserMcts($pdo, $user_id){
$user_id = $pdo->quote($user_id);
$sql = "SELECT id, mct_name, mct_about FROM mc_mct WHERE id IN (SELECT mct_id FROM mc_mct_user WHERE user_id = $user_id AND status != 0)";
$stmt = $pdo->query($sql);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
function getMctData($pdo, $mct_id){
$mct_id = $pdo->quote($mct_id);
$sql = "SELECT user_id, mct_name, mct_about FROM mc_mct WHERE id=$mct_id AND status != 0";
$stmt = $pdo->query($sql);
return $stmt->fetch(PDO::FETCH_ASSOC);
}
function getMctUsers($pdo, $mct_id){
$mct_id = $pdo->quote($mct_id);
$sql = "SELECT user_id, first_name, last_name FROM mc_profile WHERE user_id IN (SELECT user_id FROM mc_mct_user WHERE mct_id=$mct_id AND status=1)";
$stmt = $pdo->query($sql);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
function createMctData($pdo, $user_id, $mct_name, $mct_about){
$user_id = $pdo->quote($user_id);
$mct_name = $pdo->quote($mct_name);
print strlen($mct_name);
if(strlen($mct_name) < 4) return false;
$mct_about = $pdo->quote($mct_about);
$sql_insert = "INSERT INTO mc_mct (user_id, mct_name, mct_about) VALUES ($user_id, $mct_name, $mct_about)";
//print $sql_insert;
if($pdo->exec($sql_insert)){
return true;
}else{
return false;
}
}
function updateMctData($pdo, $user_id, $mct_id, $mct_name, $mct_about){
$user_id = $pdo->quote($user_id);
$mct_id = $pdo->quote($mct_id);
$mct_name = $pdo->quote($mct_name);
if(strlen($mct_name) < 4) return false;
$mct_about = $pdo->quote($mct_about);
$sql_update = "UPDATE mc_mct SET mct_name=$mct_name, mct_about=$mct_about WHERE id=$mct_id AND user_id=$user_id";
//print $sql_insert;
if($pdo->exec($sql_update)){
return true;
}else{
return false;
}
}
function insertMctData($pdo, $user_id, $mct_id){
$user_id = $pdo->quote($user_id);
$mct_id = $pdo->quote($mct_id);
// check of status
$sql = "SELECT COUNT(status) FROM mc_mct_user WHERE mct_id=$mct_id AND user_id=$user_id";
$stmt = $pdo->query($sql);
$row = $stmt->fetch(PDO::FETCH_NUM);
//print $row[0];
if($row[0]){
$sql_update = "UPDATE mc_mct_user SET status='1' WHERE mct_id=$mct_id AND user_id=$user_id";
//print $sql_insert;
if($pdo->exec($sql_update)){
return true;
}else{
return false;
}
}else{
$sql_insert = "INSERT INTO mc_mct_user (mct_id, user_id) VALUES ($mct_id, $user_id)";
//print $sql_insert;
if($pdo->exec($sql_insert)){
return true;
}else{
return false;
}
}
}
function outMctData($pdo, $user_id, $mct_id){
$user_id = $pdo->quote($user_id);
$mct_id = $pdo->quote($mct_id);
$sql_update = "UPDATE mc_mct_user SET status='0' WHERE mct_id=$mct_id AND user_id=$user_id";
//print $sql_insert;
if($pdo->exec($sql_update)){
return true;
}else{
return false;
}
}
function addMctPostData($pdo, $user_id, $mct_id, $post_id){
$user_id = $pdo->quote($user_id);
$mct_id = $pdo->quote($mct_id);
$post_id = $pdo->quote($post_id);
$sql_insert = "INSERT INTO mc_mct_post (mct_id, post_id, user_id) VALUES ($mct_id, $post_id, $user_id)";
//print $sql_insert;
if($pdo->exec($sql_insert)){
return true;
}else{
return false;
}
}
function isInsMctUser($pdo, $user_id, $mct_id){
$user_id = $pdo->quote($user_id);
$mct_id = $pdo->quote($mct_id);
$sql = "SELECT status FROM mc_mct_user WHERE mct_id=$mct_id AND user_id=$user_id";
$stmt = $pdo->query($sql);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$result = $row['status'];
if($result >= 1) return true;
return false;
}
// в каких медиацентрах пост
function getPostMcts($pdo, $post_id){
$post_id = $pdo->quote($post_id);
$sql = "SELECT id, mct_name FROM mc_mct WHERE id IN (SELECT mct_id FROM mc_mct_post WHERE post_id=$post_id AND status!=0)";
$stmt = $pdo->query($sql);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
// посты добавленные в медиацентр
function getMctPosts($pdo, $mct_id){
$mct_id = $pdo->quote($mct_id);
$sql = "SELECT mc_post.id, mc_post.user_id, first_name, last_name, post_time, LEFT(text, 180)as text, content_time FROM mc_post INNER JOIN mc_profile ON mc_post.user_id = mc_profile.user_id LEFT OUTER JOIN mc_content ON mc_content.id = mc_post.content_id WHERE mc_post.id IN (SELECT post_id FROM mc_mct_post WHERE mct_id=$mct_id AND status!=0) ORDER BY post_time DESC";
$stmt = $pdo->query($sql);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
Чтобы посмотреть в какие медиацентры добавлен пост, мы используем ту же конструкцию, что и при формировании ленты новостей (вложенный SELECT): SELECT id, mct_name FROM mc_mct WHERE id IN (SELECT mct_id FROM mc_mct_post WHERE post_id=$post_id AND status!=0)
.
Вызов в контроллере
Здесь целых два пункта case - то есть две страницы приложения и соответствующих пунктов меню отведено для управления медиацентрами:
case 'mct':
$title = "Управление медиацетрами";
$tpl = 'mct';
$mcts = getUserMcts($pdo, $this_id, 0, 100);
$ins_mcts = getInsUserMcts($pdo, $this_id);
break;
case 'media':
$tpl = 'media';
$mct_id = clearInt(route(2));
$mct_data = getMctData($pdo, $mct_id);
//var_dump($mct_data);
if(!$mct_data) header('location: /404');
$title = "Обзор медиацентра > ".$mct_data['mct_name'];
$admin_id = $mct_data['user_id'];
$admin_data = getUserData($pdo, $admin_id);
$mct_users = getMctUsers($pdo, $mct_id);
$mct_posts = getMctPosts($pdo, $mct_id);
$is_ins_mct = isInsMctUser($pdo, $this_id, $mct_id);
break;
Первое - это управление медиацентрами текущего (авторизованного) пользователя (создание, редактирование),
а второе эта страница конкретного медиацентра, где и выводятся новости от авторов.
API
/assets/js/mct.js
$("#mct_create").on("click", function(){
var mct_name = $("#mct_name").val();
var mct_about = $("#mct_about").val();
//alert('mct create: ' + mct_name + ' ' + mct_about);
$.post(
'/api/createMct',
{
"user_id": this_id,
"user_hash": this_hash,
"mct_name": mct_name,
"mct_about": mct_about,
},
function(data){
// тут добавляем наш пост сверху выборки
//alert(data);
location.reload(true);
}
);
});
// Изменение насироек медиацентра
$("#mct-settings-save").on("click", function(){
var mct_name = $("#mct-settings-name").val();
var mct_about = $("#mct-settings-about").val();
//alert('mct create: ' + mct_name + ' ' + mct_about);
$.post(
'/api/updateMct',
{
"user_id": this_id,
"mct_id": mct_id,
"user_hash": this_hash,
"mct_name": mct_name,
"mct_about": mct_about,
},
function(data){
// тут добавляем наш пост сверху выборки
//alert(data);
location.reload(true);
}
);
});
// Вступление в медиацентр
$("#mct_insert").on("click", function(){
//alert('insert: ' + this_id + ' ' + this_hash);
$.post(
'/api/insertMct',
{
"user_id": this_id,
"user_hash": this_hash,
"mct_id": mct_id,
},
function(data){
// тут добавляем наш пост сверху выборки
//alert(data);
location.reload(true);
}
);
});
// выход из медиацентра
$("#mct_out").on("click", function(){
//alert('out: ' + mct_id + ' ' + this_id + ' ' + this_hash);
$.post(
'/api/outMct',
{
"user_id": this_id,
"user_hash": this_hash,
"mct_id": mct_id,
},
function(data){
// тут добавляем наш пост сверху выборки
//alert(data);
location.reload(true);
}
);
});
В принципе понятно что делают функции. Посмотрим как они вызываются в coreapi:
sys/coreapi.php
/* Управление медиацентрами */
// Создание медиацентра
function createMct($pdo){
$user_id = clearInt($_POST['user_id']);
$user_hash = clearStr($_POST['user_hash']);
// TODO: validate min 3 chars
$mct_name = clearStr($_POST['mct_name']);
$mct_about = clearStr($_POST['mct_about']);
//print_r($_POST);
if(check($pdo, $user_id, $user_hash)){
//print_r($_POST);
if(createMctData($pdo, $user_id, $mct_name, $mct_about)){
print '{"response":1}';
}else{
print '{"response":0, "error":"Error added post"}';
}
}else{
print '{"response":0, "error":"No avtorized user"}';
}
}
// Изменение настроек медиацентра
function updateMct($pdo){
$user_id = clearInt($_POST['user_id']);
$mct_id = clearInt($_POST['mct_id']);
$user_hash = clearStr($_POST['user_hash']);
// TODO: validate min 3 chars
$mct_name = clearStr($_POST['mct_name']);
$mct_about = clearStr($_POST['mct_about']);
//print_r($_POST);
if(check($pdo, $user_id, $user_hash)){
//print_r($_POST);
if(updateMctData($pdo, $user_id, $mct_id, $mct_name, $mct_about)){
print '{"response":1}';
}else{
print '{"response":0, "error":"Error added post"}';
}
}else{
print '{"response":0, "error":"No avtorized user"}';
}
}
// Вступление в медиацентр
function insertMct($pdo){
$user_id = clearInt($_POST['user_id']);
$user_hash = clearStr($_POST['user_hash']);
$mct_id = clearInt($_POST['mct_id']);
//print_r($_POST);
if(check($pdo, $user_id, $user_hash)){
//print_r($_POST);
if(insertMctData($pdo, $user_id, $mct_id)){
print '{"response":1}';
}else{
print '{"response":0, "error":"Error added post"}';
}
}else{
print '{"response":0, "error":"No avtorized user"}';
}
}
// Выход из медиацентра
function outMct($pdo){
$user_id = clearInt($_POST['user_id']);
$user_hash = clearStr($_POST['user_hash']);
$mct_id = clearInt($_POST['mct_id']);
//print_r($_POST);
if(check($pdo, $user_id, $user_hash)){
//print_r($_POST);
if(outMctData($pdo, $user_id, $mct_id)){
print '{"response":1}';
}else{
print '{"response":0, "error":"Error added post"}';
}
}else{
print '{"response":0, "error":"No avtorized user"}';
}
}
// Добавление поста в медиацентр
function addMctPost($pdo){
//print_r($_POST);
$user_id = clearInt($_POST['user_id']);
$user_hash = clearStr($_POST['user_hash']);
$mct_id = clearInt($_POST['mct_id']);
$post_id = clearInt($_POST['post_id']);
if(check($pdo, $user_id, $user_hash)){
//print_r($_POST);
if(addMctPostData($pdo, $user_id, $mct_id, $post_id)){
print '{"response":1}';
}else{
print '{"response":0, "error":"Error added post"}';
}
}else{
print '{"response":0, "error":"No avtorized user"}';
}
}
Вот такие функции вызываются из JavaScript (через API) для работы с медиацентрами (сообществами) нашей соцсети.
@rusldv Поздравляю! Вы добились некоторого прогресса на Голосе и были награждены следующими новыми бейджами:
Награда за количество голосов
Вы можете нажать на любой бейдж, чтобы увидеть свою страницу на Доске Почета.
Чтобы увидеть больше информации о Доске Почета, нажмите здесь
Если вы больше не хотите получать уведомления, ответьте на этот комментарий словом
стоп
Ваш пост поддержали следующие Инвесторы Сообщества "Добрый кит":
niiu, vadbars, voltash, wedge
Поэтому я тоже проголосовал за него!
Узнать подробности о сообществе можно тут:
Разрешите представиться - Кит Добрый
Правила
Инструкция по внесению Инвестиционного взноса
Вы тоже можете стать Инвестором и поддержать проект!!!
Если Вы хотите отказаться от поддержки Доброго Кита, то ответьте на этот комментарий командой "!нехочу"
Спасибо, Руслан! Очень много всего добавилось. И почти все ясно. Осталось лишь рассказать о наполнении темплейтов news.tpl.php, mct.tpl.php, media.tpl.php. И раскрыть код функции getUserData().
Еще вопрос - как наши $.post() ajax-запросы "увидят" функции из coreapi.php, если вызов URL там такой '/api/createMct', а расположение самого coreapi.php с функцией createMct() - в папке /sys/coreapi.php? Может все-таки в папке /api/ должно быть?
В целом хотелось все таки увидеть работающую соц.сеть - а это все же без html/php темплейтов не увидеть :)
Да спасибо. Выложу. Про api там все проще чем кажется. coreapi - это библиотека функций, поэтому она и в /sys, а вызывается из /api. Ну она там инклудится ))
<?php define(ROOT, $_SERVER['DOCUMENT_ROOT']); require(ROOT.'/sys/core.php'); require(ROOT.'/sys/coreapi.php');Вот как то так