Правила     Закладки     Карма    Календарь    Журналы    Помощь    Поиск    PDA    Чат   
        СМС-ки
   
Пейджер выключен!
Страницы: (2) [1] 2  ( Перейти к первому непрочитанному сообщению )  
Фильтр авторов:    показать 
  скрыть
  Ответ в темуСоздание новой темыСоздание опроса

> Помогите проверить и допилить!), примитивный MVC роутер
CoopeR  
 ۩  [x]    Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Пользователь
**

Профиль
Группа: Форумчанин
Завсегдатай форума
Сообщений: 59
Пользователь №: 38317
На форуме: 3 года, 2 месяца, 24 дня
Карма: 3




Предупреждаю сразу, я ученик и я только учусь. Хочу сделать что то типо примитивного MVC роутера
классами, PDO и тд не пользуюсь, так как ещё не умею, поэтому процедурный стиль...(код немного сокращен для наглядности)
Вопрос: можно ли так?, безопасно ли так? и вообще что убрать что добавить

Файл .htaccess - перенаправляет все запросы на index.php (только если не существует такого файла)
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ [NC,L]
RewriteRule ^.*$ index.php [NC,L]


Файл index.php -
<?php define('_TEST',true);
mb_internal_encoding("UTF-8");
error_reporting(E_ALL);
ini_set('display_errors', 1);
if (version_compare(phpversion(), '5.1.0', '<') == true) { die ('PHP5.1 Only'); }
require_once ('router.php'); //ссылка на роутер
?>



Файл router.php - наш роутер
<?php defined('_TEST') or die();
if ($_SERVER['REQUEST_URI'] == '/') { // если главная страница то

require_once('controller/index.php');
} else { // если не главная то
$parse = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); // Парсим урл с GET и POST запросами
$url = explode('/', trim($parse, ' /')); // Разбиваем урл по символу "/"
if (count($url) > 3) { die('error')} // eсkи больше 3 директорий - ошибка

$controller = empty($url[0]) ? strtolower($url[0]) : 'index';
$model = empty($url[1]) ? strtolower($url[1]) : 'index'; // проверили существование
$view = empty($url[2]) ? strtolower($url[2]) : 'index';

$dir_controller = 'controller/' . $controller . '.php';
$dir_model = 'model/' . $controller . '.php'; //определяем поддиректории
$dir_view = 'view/' . $controller . '.php';

if (file_exists($dir_controller)){
require_once($dir_controller); //проверим и подключим контроллер
} else echo'eror load controller';
if (file_exists($dir_model)){
require_once($dir_model); //проверим и подключим модель
} else echo'eror load model';
if (file_exists($dir_view)){
require_once($dir_view); //проверим и подключим вид
} else echo'eror load view';
}
model($model); //запуск функции
view($action); //запуск функции
?>


--------------------
Нажимаю "Мой компьютер"... не моет, сукоо...
Познакомлюсь с девушкой, можно крякнутая версия...
PMПисьмо на e-mail пользователюСайт пользователя
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
Игорь_Vasinsky  
Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Лысый и злой
******

Профиль
Журнал
Группа: ★ЛжеЭксперт★
Завсегдатай форума
Сообщений: 26041
Пользователь №: 21350
На форуме: 6 лет, 10 месяцев, 5 дней
Карма: 726

Не курю:
1 год, 3 месяца, 21 день


Цитата
'5.1.0', '<') == true)

типы разве так сравнивают типы?


Цитата
} else echo'eror load controller';

если уж какой то компонент не доступен - то может грохнуть весь дальнейший ход скрипта через exit() ???

Цитата
// eсkи больше 3 директорий - ошибка

пфф.. а чё так?

не проще написать функцию, которая будет разбирать GET и собирать в нужный вид?

Цитата
dir_controller = 'controller/'

пути может всё же полные указывать?


--------------------
Халявные ответы кончились.
Если нужен готовый код - готовьтесь заплатить.
Райкин тоже был артист

Возле дома был сарай
А когда всё хорошо
Можно просто покурить

user posted image
http://ufa102.xyz/
PMПисьмо на e-mail пользователю
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
xlebosol  
Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Знатный быдлокодер
******

Профиль
Группа: Форумчанин
Завсегдатай форума
Сообщений: 337
Пользователь №: 32761
На форуме: 4 года, 6 месяцев, 29 дней
Карма: 19




if (file_exists($dir_controller)){
require_once($dir_controller); //проверим и подключим контроллер
} else echo'eror load controller';

Первый (else) сразу сработает, нужно (else if).
PMПисьмо на e-mail пользователюICQ
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
Игорь_Vasinsky  
Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Лысый и злой
******

Профиль
Журнал
Группа: ★ЛжеЭксперт★
Завсегдатай форума
Сообщений: 26041
Пользователь №: 21350
На форуме: 6 лет, 10 месяцев, 5 дней
Карма: 726

Не курю:
1 год, 3 месяца, 21 день


если там exit() поставить - то всё что далее - нам пофиг - скрипт остоновится


--------------------
Халявные ответы кончились.
Если нужен готовый код - готовьтесь заплатить.
Райкин тоже был артист

Возле дома был сарай
А когда всё хорошо
Можно просто покурить

user posted image
http://ufa102.xyz/
PMПисьмо на e-mail пользователю
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
CoopeR  
 ۩  Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Пользователь
**

Профиль
Группа: Форумчанин
Завсегдатай форума
Сообщений: 59
Пользователь №: 38317
На форуме: 3 года, 2 месяца, 24 дня
Карма: 3




Подправил вот так
	define( "DIR", dirname( __FILE__ ) ."/" );						//определяем директорию сайта
$dir_controller = DIR . 'controller/' . $controller . '.php';
$dir_model = DIR . 'model/' . $controller . '.php'; //определяем поддиректории
$dir_view = DIR . 'view/' . $controller . '.php';


а с exit() если так?
	if (file_exists($dir_controller)){
require_once($dir_controller); //проверим и подключим контроллер
} else {echo 'eror load view'; exit();}


--------------------
Нажимаю "Мой компьютер"... не моет, сукоо...
Познакомлюсь с девушкой, можно крякнутая версия...
PMПисьмо на e-mail пользователюСайт пользователя
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
Игорь_Vasinsky  
Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Лысый и злой
******

Профиль
Журнал
Группа: ★ЛжеЭксперт★
Завсегдатай форума
Сообщений: 26041
Пользователь №: 21350
На форуме: 6 лет, 10 месяцев, 5 дней
Карма: 726

Не курю:
1 год, 3 месяца, 21 день


Цитата
define( "DIR", dirname( __FILE__ ) ."/" ); 

а чё не $_SERVER['DOCUMENT_ROOT'] ???
Цитата

а с exit() если так?

логичней уж так или редирект на 404
if (file_exists($dir_controller)){
require_once($dir_controller); //проверим и подключим контроллер
}
else {
exit('eror load view');

}


--------------------
Халявные ответы кончились.
Если нужен готовый код - готовьтесь заплатить.
Райкин тоже был артист

Возле дома был сарай
А когда всё хорошо
Можно просто покурить

user posted image
http://ufa102.xyz/
PMПисьмо на e-mail пользователю
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
bestxp  
Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



орангутанг
******

Профиль
Группа: Форумчанин
Завсегдатай форума
Сообщений: 2018
Пользователь №: 36605
На форуме: 3 года, 11 месяцев, 3 дня
Карма: 112




ну твой роутер немного не правильно работает если это у тебя MVC

первое что он должен найти это контроллер, и сказать ему запусти такое-то действие

получается нашли контроллер
потом контроллер->runAction(найденое дествие)

а view уже определяется под конец работы контроллера, то есть, его необходимость, ведь порой оно и не нужно в виде html, например какое-то аякс действие, и ты уже отдаешь не html а просто echo json_encode($responce) как пример


--------------------
PMПисьмо на e-mail пользователюСайт пользователяICQ
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
kaww  
Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Здесь живет
******

Профиль
Группа: Форумчанин
Завсегдатай форума
Сообщений: 1769
Пользователь №: 20757
На форуме: 6 лет, 11 месяцев, 17 дней
Карма: 185




CoopeR, крайне не настраиваемая структура адресов получится, если можно так выразиться. Чем обусловлен такой странный подход ; http://site.ru/controller/model/view ?
Помимо того, что код попахивает, имхо, первое что бросается в глаза (не считая качества кода, конечно же), так это, то что "роутер" не считает разными страницы http://site.ru/controller/model/view и http://site.ru/controller/model/view/
PMПисьмо на e-mail пользователю
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
CoopeR  
 ۩  [x] Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Пользователь
**

Профиль
Группа: Форумчанин
Завсегдатай форума
Сообщений: 59
Пользователь №: 38317
На форуме: 3 года, 2 месяца, 24 дня
Карма: 3




Спасибо за критику! пошел дальше учить...((
Предлагаю посмотреть на этот код: (может, хоть раньше я что то правильно делал)
<?php define('_TEST',true);
mb_internal_encoding("UTF-8");
error_reporting(E_ALL);
ini_set('display_errors', 1);
$go = isset($_GET['go']) ? $_GET['go'] : '';
switch ($go) {
case ('post'):
if (isset($_GET['id'])){
$id = max(1, intval($_GET['page']));
include('func/post.php');
post($id);
} else die('no id');
break;
case ('cat'):
if (isset($_GET['catid'])){
$page = isset($_GET['page']) ? max(1, intval($_GET['page'])) : 1;
$catid = intval($_GET['catid']);
$pages = 10;
include('func/cat.php');
cat($catid,$page,$pages);
} else die('no catid');
break;
case ('addcomm'):
if(isset($_POST['id']))$id = intval($_POST['id']);
if(isset($_POST['name']))$name = $_POST['name'];
if(isset($_POST['message']))$message = $_POST['message'];
if(isset($id) & isset($message) & isset($name)){
$message = substr($_POST["message"],0,1024);
$message = nl2br(htmlspecialchars(stripslashes($message)));
$name = substr($_POST["name"],0,32);
$name = htmlspecialchars(stripslashes($name));
include('func/addcomm.php');
addcomm($id,$name,$message);}
break;
default:
$page = isset($_GET['page']) ? max(1, intval($_GET['page'])) : 1;
$pages = 10;
include('func/all.php');
all($page,$pages);
break;
}
?>


--------------------
Нажимаю "Мой компьютер"... не моет, сукоо...
Познакомлюсь с девушкой, можно крякнутая версия...
PMПисьмо на e-mail пользователюСайт пользователя
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
Игорь_Vasinsky  
Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Лысый и злой
******

Профиль
Журнал
Группа: ★ЛжеЭксперт★
Завсегдатай форума
Сообщений: 26041
Пользователь №: 21350
На форуме: 6 лет, 10 месяцев, 5 дней
Карма: 726

Не курю:
1 год, 3 месяца, 21 день


Цитата
. Чем обусловлен такой странный подход ; http://site.ru/controller/model/view ?

кстати, на CI такое вижу


для ТС
-------------------
ты знаешь что такое тернарный оператор
$go = isset($_GET['go']) ? $_GET['go'] : '';


но далее чёрти чё
Цитата
if(isset($_POST['id']))$id = intval($_POST['id']);
  if(isset($_POST['name']))$name = $_POST['name'];
  if(isset($_POST['message']))$message = $_POST['message'];
  if(isset($id) & isset($message) & isset($name)){


(int)$var работает быстрее intval($var)

Цитата
$name = htmlspecialchars(stripslashes($name));

чего боимся?

Цитата
$message = substr($_POST["message"],0,1024);

ты то в юникоде работаешь
1.mb_substr
2. нехило - так взял и рубанул пользовательский текст - не жестоко?


а код похож на кашу и логика только с прищуренного глаза еле понятна


--------------------
Халявные ответы кончились.
Если нужен готовый код - готовьтесь заплатить.
Райкин тоже был артист

Возле дома был сарай
А когда всё хорошо
Можно просто покурить

user posted image
http://ufa102.xyz/
PMПисьмо на e-mail пользователю
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
CoopeR  
 ۩  [x] Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Пользователь
**

Профиль
Группа: Форумчанин
Завсегдатай форума
Сообщений: 59
Пользователь №: 38317
На форуме: 3 года, 2 месяца, 24 дня
Карма: 3




немного переделал, можете глянуть есть ли ошибки?
index.php
<?php define('_TEST',true);													
mb_internal_encoding("UTF-8");
error_reporting(E_ALL);
ini_set('display_errors', 1);
$go = isset($_GET['go']) ? $_GET['go'] : 'all';
switch ($go) {
case ('all'):
$page = isset($_GET['page']) ? max(1, int($_GET['page'])) : 1;
$pages = 10;
require_once(__DIR__ . '/func/all.php'); //этот файл есть ниже
all($page, $pages);
break;
case ('post'):
$id=(int)$_GET['id'];
if ($id){
require_once(__DIR__ . '/func/post.php');
post($id);
} else eror404();
break;
case ('cat'):
$catid=(int)$_GET['catid'];
if ($catid){
$page = isset($_GET['page']) ? max(1, intval($_GET['page'])) : 1;
$pages = 10;
require_once(__DIR__ . '/func/cat.php');
cat($catid,$page,$pages);
} else eror404();
break;
case ('addcomm'):
if(isset($_POST['id']))$id = int($_POST['id']);
if(isset($_POST['name']))$name = $_POST['name'];
if(isset($_POST['message']))$message = $_POST['message'];
if(isset($id) & isset($message) & isset($name)){
$message = mb_substr($_POST["message"],0,1024);
$message = nl2br(mysqli_real_escape_string($message));
$name = substr($_POST["name"],0,32);
$name = mysqli_real_escape_string($name);
require_once(__DIR__ . '/func/addcomm.php');
addcomm($id,$name,$message);}
break;
default:
eror404();
break;
}
function eror404() {
header('HTTP/1.1 404 Not Found');
header('Status: 404 Not Found');
exit;
}


Для примера all.php (файл открывающийся на 10 строчке в предыдущем примере)
<?php defined('TEST') or die();
function all($page,$pages){
require("adm/connect.php");
$sql_page = "SELECT COUNT(*) AS cnt FROM post";
$sel_page = mysqli_query($db, $sql_page);
$row_page = mysqli_fetch_row($sel_page);
$num_page = ceil($row_page['cnt']/$pages);
$str_page = intval(($page - 1) * $pages);
$array_all = array();
$sql_all = "SELECT post.*, COUNT(comm.id) AS comments
FROM post LEFT JOIN comm ON post.id = comm.post_id
GROUP BY post.id ORDER BY date DESC LIMIT
$str_page, $pages";
$sel_all = mysqli_query($db, $sql_all); if (!$sel_all) die("нет статей в базе данных");
while( $all = mysqli_fetch_assoc($sel_all) ){
if (mb_strlen($all['content']) > 500) {
$all['content'] = mb_substr(strip_tags($all['content']), 0, 497) . '...';}
$all['day'] = date('d', $all['date']);
switch (date('m', $all['date'])){
case '1': $all['month'] = 'янв'; break;
case '2': $all['month'] = 'фев'; break;
case '3': $all['month'] = 'мар'; break;
case '4': $all['month'] = 'апр'; break;
case '5': $all['month'] = 'май'; break;
case '6': $all['month'] = 'июн'; break;
case '7': $all['month'] = 'июл'; break;
case '8': $all['month'] = 'авг'; break;
case '9': $all['month'] = 'сен'; break;
case '10': $all['month'] = 'окт'; break;
case '11': $all['month'] = 'ноя'; break;
case '12': $all['month'] = 'дек'; break;}
$all['year'] = date('Y', $all['date']);
$all['content'] = nl2br($all['content']);
$array_all[] = $all;}
require('template/all.php');
}
?>


Далее в template/all.php
<?php foreach ($array_all as $all):
здесь то что нужно в шаблоне
endforeach; ?>


--------------------
Нажимаю "Мой компьютер"... не моет, сукоо...
Познакомлюсь с девушкой, можно крякнутая версия...
PMПисьмо на e-mail пользователюСайт пользователя
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
EvilDev  
Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Здесь живет
******

Профиль
Группа: Форумчанин
Завсегдатай форума
Сообщений: 484
Пользователь №: 16303
На форуме: 8 лет, 1 месяц, 5 дней
Карма: 7




Жестко..
Когда то писал свой велосипед, посмотри и внимательно с документацией изучи:
$rQuery = $this->request->getQuery('r');
if (isset($rQuery)) {
$r = explode('/', $rQuery);
$num = count($r);
if ($num == 1 || $num == 2) {
// Контроллер
if (preg_match('/^[a-zA-Z]{1,32}$/', $r[0])) {
$this->_controller = $r[0];

// Теперь действие, если есть
if (isset($r[1])) {
if (preg_match('/^[a-zA-Z]{1,32}$/', $r[1]))
$this->_action = $r[1];
}
}
}
}

// Если есть такой контроллер, то выполним его
if (file_exists($this->basePath . '/controllers/' . ucfirst($this->_controller) . 'Controller.php')) {
$_controller = ucfirst($this->_controller) . 'Controller';
$_action = 'action' . ucfirst($this->_action);

// Есть ли такой класс?
if (!class_exists($_controller) || !is_subclass_of($_controller, 'Controller'))
throw new Exception('Error load controller!');

$controller = new $_controller();

// Если такого действия нет
if (!is_callable(array($controller, $_action)))
throw new Exception('Action "' . $this->_action . '" not found!');

// Выполним действие
$ref = new ReflectionMethod($_controller, $_action);
$refParams = $ref->getParameters();
$funcParams = array();

// Получим параметры
// TODO: Постестить на уязвимость надо
foreach ($refParams as $item) {
$funcParams[ $item->name ] = Kernel::app()->request->getQuery($item->name);
//if ($funcParams[ $item->name ] == null)
// throw new Exception('Error data');
}

// Вызываем функцию с набором параметров
call_user_func_array(array($controller, $_action), $funcParams);
} else
throw new Exception('Controller "' . $this->_controller . '" not found!');


Это application class в котором производится роутинг на нужные контроллеры. Заметь, тут мы выдергиваем параметр r=controller/action. Controller - нужный класс, action - его функция.


--------------------
HTML5, CSS3, jQuery, Node.js, PHP, Yii, Joomla, MySQL, MongoDb, GIMP
PMПисьмо на e-mail пользователюСайт пользователя
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
bestxp  
Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



орангутанг
******

Профиль
Группа: Форумчанин
Завсегдатай форума
Сообщений: 2018
Пользователь №: 36605
На форуме: 3 года, 11 месяцев, 3 дня
Карма: 112




EvilDev
очень сильно напоминает Yii твой роутер


--------------------
PMПисьмо на e-mail пользователюСайт пользователяICQ
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
EvilDev  
Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Здесь живет
******

Профиль
Группа: Форумчанин
Завсегдатай форума
Сообщений: 484
Пользователь №: 16303
На форуме: 8 лет, 1 месяц, 5 дней
Карма: 7




Цитата (bestxp @ 13.11.2013 - 09:32)
EvilDev
очень сильно напоминает Yii твой роутер

Есть немного)


--------------------
HTML5, CSS3, jQuery, Node.js, PHP, Yii, Joomla, MySQL, MongoDb, GIMP
PMПисьмо на e-mail пользователюСайт пользователя
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
Игорь_Vasinsky  
Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Лысый и злой
******

Профиль
Журнал
Группа: ★ЛжеЭксперт★
Завсегдатай форума
Сообщений: 26041
Пользователь №: 21350
На форуме: 6 лет, 10 месяцев, 5 дней
Карма: 726

Не курю:
1 год, 3 месяца, 21 день


Цитата
case '1': $all['month'] = 'янв'; break;
  case '2': $all['month'] = 'фев'; break;
  case '3': $all['month'] = 'мар'; break;
  case '4': $all['month'] = 'апр'; break;
  case '5': $all['month'] = 'май'; break;
  case '6': $all['month'] = 'июн'; break;
  case '7': $all['month'] = 'июл'; break;
  case '8': $all['month'] = 'авг'; break;
  case '9': $all['month'] = 'сен'; break;
  case '10': $all['month'] = 'окт'; break;
  case '11': $all['month'] = 'ноя'; break;
  case '12': $all['month'] = 'дек'; break;}


яб массив создал. зачем для этого логику прикручивать.


--------------------
Халявные ответы кончились.
Если нужен готовый код - готовьтесь заплатить.
Райкин тоже был артист

Возле дома был сарай
А когда всё хорошо
Можно просто покурить

user posted image
http://ufa102.xyz/
PMПисьмо на e-mail пользователю
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
  Быстрый ответ
Информация о Госте
Введите Ваше имя
Кнопки кодов
Для вставки цитаты, выделите нужный текст и
НАЖМИТЕ СЮДА
Введите сообщение
Смайлики
:huh:  :o  ;) 
:P  :D  :lol: 
B)  :rolleyes:  <_< 
:)  :angry:  :( 
:unsure:  :blink:  :ph34r: 
     
Показать всё

Опции сообщения  Включить смайлики?
 Включить подпись?
 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:

Опции темыСтраницы: (2) [1] 2  Ответ в темуСоздание новой темыСоздание опроса