[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Задача на корректную обработку данных
Winston
Решил и я потренироваться с ООП и понять как практически применяется шаблон MVC.
В качестве задания решил взять вот эту задачку twin'a. Она не сложная и на ее примере у меня получилось лучше понять как применяется MVC на практике.
Надеюсь, что у меня получилось хоть какое-то подобие этого шаблона :) (Хотелось бы от других получить подтверждение этого :))
Получилось всего 12 файлов. Всех выкладывать не буду, а только основные. А остальные можно взять в приаттаченом архиве.
И так:
.htaccess


php_flag magic_quotes_gpc On
php_flag magic_quotes_runtime On

Options -Indexes

<Files ~ "\.tpl$|\.ini$">
Order allow,deny
Deny from all
</Files>


index.php


<?php
header('Content-Type: text/html; charset=utf-8');

define('MODE', 'developing'); // Режим разработчика или продакшн
// define('MODE', 'production'); // Режим продакшн


switch(MODE)
{
case 'developing' : error_reporting(E_ALL); break;
case 'production' : error_reporting(0); break;
default : error_reporting(0); break;
}

define('EXEC' , true); // Флаг который предотвращает прямой доступ к файлам
define('DS' , str_replace(DIRECTORY_SEPARATOR, '/', DIRECTORY_SEPARATOR)); // Разделитель
define('PHIS_PATH', str_replace('\\', '/', dirname(__FILE__)) . DS); // Абсолютный путь
define('WEB_PATH' , 'http://' . $_SERVER['HTTP_HOST'] . DS); // WEB адрес

include_once PHIS_PATH . 'config.php'; // Конфигурационный файл
include_once PHIS_PATH . 'core' . DS . 'Controller.php'; // Главный контроллер

Controller :: loadConfig('main'); // Загружаем ini-файл конфигурации

include_once PHIS_PATH . 'core' . DS . C_PREF . 'Base.php'; // Базовый контроллер
include_once PHIS_PATH . 'controllers' . DS . C_PREF . 'Index.php'; // Контроллер главной страницы


$class = C_PREF . 'Index';
$controller = new $class;


echo $controller -> Request(); // Метод который вызывает виртуальный обработчик и метод формирующий страницу



config.php


<?php
defined('EXEC') or die('Restricted Access !');

define('V_EXT', '.tpl'); // Расширение файла шаблона
define('VIEW_DIR', 'view' . DS); // Каталог с шаблонами

define('M_PREF', 'M_'); // Префикс для файлов модели
define('V_PREF', 'V_'); // Префикс для файлов вида
define('C_PREF', 'C_'); // Префикс для файлов контроллера



Дальше контроллеры:
Главный контроллер
Controller.php


<?php
defined('EXEC') or die('Restricted Access !');

// Главный контроллер
abstract class Controller
{
public static $config = Array(); // Настройки БД

/**
* Метод который вызывает виртуальный обработчик
* и метод который возвращает сформированную страницу
*/

public function Request()
{
// Убиваем магические кавычки
self :: killQuotes($_GET);
self :: killQuotes($_POST);
self :: killQuotes($_COOKIE);

$this -> Input(); // Виртуальный обработчик
return $this -> Output(); // Возвращаем сформированную страницу
}

abstract protected function Input(); // Виртуальный обработчик данных
abstract protected function Output(); // Метод который возвращает сформированную страницу

/**
* Метод формирующий страницу
* $template - имя шаблона
* $vars - массив переменных
*/

protected static function View($template, $vars = Array())
{
$template = PHIS_PATH . 'view' . DS . $template . V_EXT; // Формируем путь к шаблону

if(file_exists($template))
{
self :: proccessingInputData($vars); // Обрабатываем многомерный массив ф-ей htmlspecialchars
self :: killQuotes($vars); // Убиваем кавычки в данных из БД
self :: htmlChars($_GET); // Обработка данных из GET
extract($vars, EXTR_SKIP); // Распаковываем переменные

ob_start();
include $template;
$page = ob_get_contents();
ob_end_clean();

return $page; // Возвращаем сформированную страницу
}
else
return
false;
}

/**
* Обработка многомерного массива ф-ей htmlspecialchars
*/

private function proccessingInputData(&$data)
{
foreach($data AS $k => &$v)
{
if(is_array($data[$k]))
$data[$k] = self :: htmlCharsDeep($data[$k]);
else
$data[$k] = self :: htmlChars($data[$k]);
}

return $data;
}

/**
* Убийца магических кавычек
*/

private static function killQuotes(&$VAR)
{
if (get_magic_quotes_gpc())
{
if (is_array($VAR))
$VAR = array_map(array(__CLASS__, __METHOD__), $VAR);
else
$VAR = stripslashes($VAR);
}

return $VAR;
}

/**
* Обработчик массива ф-ей htmlspecialchars
*/

public static function htmlChars(&$data)
{
if(is_array($data))
return $data = array_map('htmlspecialchars', $data);
else
return
$data = stripslashes($data);

return false;
}

/**
* Обработчик двумерного массива ф-ей htmlspecialchars
*/

protected static function htmlCharsDeep(&$data)
{
if(is_array($data))
{
$data = array_map(create_function('$item',
'
if(is_array($item))
return array_map("htmlspecialchars", $item);
else
return htmlspecialchars($item);
'
),
$data);
return $data;
}
else
return
false;
}

/**
* Загрузчик файла конфигурации
*/

public static function loadConfig($config)
{
$file = PHIS_PATH . 'config' . DS . $config . '.ini';

if(file_exists($file))
self :: $config = parse_ini_file($file, true);
else
return
false;
}

/**
* Форматтер даты
* Возвращает дату в формате: ДД-MM-ГГГГ ЧЧ-ММ-СС
*/

public static function formatDate($dateStr)
{
$date = explode(' ', $dateStr);
$time = $date[1];

$date = explode('-', $date[0]);
$date = $date[2] . '-' . $date[1] . '-' . $date[0];

return $date . ' ' . $time;
}
}



Методу proccessingInputData
self :: proccessingInputData($vars);
передается массив такого вида:
Свернутый текст


Array
(
[title] => Задача на корректную обработку данных
[userList] => Array
(
[0] => Array
(
[id] => 12
[date] => 2011-08-28 17:21:48
[name] => <script>alert('test');</script>
)

[1] => Array
(
[id] => 11
[date] => 2011-08-28 17:21:18
[name] => O"Relly
)

[2] => Array
(
[id] => 10
[date] => 2011-08-28 17:18:49
[name] => O'Relly
)

[3] => Array
(
[id] => 9
[date] => 2011-08-28 17:18:40
[name] => Mc''donalds
)

[4] => Array
(
[id] => 8
[date] => 2011-08-28 17:18:32
[name] => volt&
)

[5] => Array
(
[id] => 7
[date] => 2011-08-28 17:18:22
[name] => I 100% know
)

[6] => Array
(
[id] => 6
[date] => 2011-08-28 17:18:13
[name] => Guest004
)

[7] => Array
(
[id] => 5
[date] => 2011-08-28 17:18:03
[name] => <Jensen & partners>
)

[8] => Array
(
[id] => 4
[date] => 2011-08-28 17:17:55
[name] => 2*2=5?
)

[9] => Array
(
[id] => 3
[date] => 2011-08-28 17:17:27
[name] => \ bacslashes \
)

[10] => Array
(
[id] => 2
[date] => 2011-08-28 17:17:02
[name] => -=++++
)

[11] => Array
(
[id] => 1
[date] => 2011-08-28 17:16:42
[name] => %%%%
)

)

[userInfo] => Array
(
)

[listUserSearch] => Array
(
[0] => Array
(
[id] => 4
[date] => 2011-08-28 17:17:55
[name] => 2*2=5?
)

)

[countSearch] => 1
[countRegUsers] => 12
[errorSearch] =>
)



Контроллер по умолчанию
C_Base.php


<?php
defined('EXEC') or die('Restricted Access !');

// Контроллер по умолчанию
abstract class C_Base extends Controller
{
protected $title; // Тайтл страницы

protected function Input()
{
$this -> title = 'Главная страница';
}

protected function Output()
{
// Устанавливаем настройки по умолчанию
$vars = Array('title' => $this -> title);

// Передаем имя шаблона для отображения и переменную
return parent :: View('default', $vars);
}
}




Модель
MySql.php


<?php
defined('EXEC') or die('Restricted Access !');

// Драйвер для работы с БД
class MySql
{
const NO_SELECTDB = 'Невозможно выбрать БД !';
const NO_CONNECTHOST = 'Невозможно соединиться с БД !';

private static $instance; // Объект класса
private static $connectLink = NULL; // Идентификатор соединения

private function __construct(){} // Запрещаем создание экземпляра

/**
* Singleton - Получаем единственный экземпляр объекта
*/

public static function getInstance()
{
if(is_null(self :: $instance))
{
self :: connectDB();
self :: $instance = new MySql;
}

return self :: $instance;
}

/**
* Соединение с БД
*/

private static function connectDB()
{
try
{
if(false === ($result = @mysql_connect( Controller :: $config['DB']['HOST'],
Controller :: $config['DB']['USER'],
Controller :: $config['DB']['PASS'])))
throw new Exception(self :: NO_CONNECTHOST);

self :: $connectLink = $result;
mysql_query('SET NAMES utf8', self :: $connectLink);

if(false === ($result = @mysql_select_db(Controller :: $config['DB']['DB'], self :: $connectLink)))
throw new Exception(self :: NO_SELECTDB);
}
catch(Exception $e)
{
die($e -> getMessage());
}
}


/**
* Оболочка для mysql_query
*/

public function setQuery($sql)
{
if(!is_resource($sql))
return mysql_query($sql);
else
return
$sql;
}

/**
* Метод возвращает 1 элемент из запроса
*/

public function getAssocRow($resource)
{
if(is_resource($resource))
return mysql_fetch_assoc($resource);
else
return
$resource;
}

/**
* Метод возвращает ассоциативный массив
*/

public function getAssocArray($resource)
{
$data = Array();
if(is_resource($resource))
{
while($row = mysql_fetch_assoc($resource))
$data[] = $row;

return $data;
}
else
return
$resource;
}

/**
* Метод экранирования спецсимволов в запросе
*/

public function RES($string)
{
return mysql_real_escape_string($string);
}
}




Контроллер главной страницы
C_Index.php


<?php
defined('EXEC') or die('Restricted Access !');

include_once PHIS_PATH . 'model' . DS . 'MySql.php'; // Подключаем модель

// Контроллер гланой страницы

class C_Index extends C_Base
{
private $mysql; // Объект класса для работы с БД
private $userList = Array(); // Список всеъ пользователей
private $userInfo = Array(); // Информация о определенном пользователе
private $listUserSearch = Array(); // Список пользователей которые были найдены
private $countRegUsers; // Количество зарегистрированных пользователей
private $countSearch; // Количество найденных пользователей

private $errorSearch;

function __construct()
{
$this -> mysql = MySql :: getInstance(); // Получаем объект для рабооты с БД
}

protected function Input()
{
parent :: Input();

$this -> title = 'Задача на корректную обработку данных'; // Устанавливаем тайтл страницы
$this -> getUsers(); // Получаем всех пользователей

// Если есть кнопка и существует элемент regName массива POST
// И обрезанная перменная regName не равна NULL то добавляем пользователя

if(isset($_POST['regBtn']) && isset($_POST['regName'])
&&
trim($_POST['regName']) != NULL)
$this -> addUser();

// Если существует ID пользователя, то получаем информацию о нем
if(isset($_GET['id']))
$this -> getUserInfo();

// Ищем пользователя
if(isset($_GET['search']))
$this -> searchUsers();
}

/**
* Метод получает всех зарегистрированных пользователей
*/

private function getUsers()
{
$sql = "SELECT *
FROM `"
. Controller :: $config['DB']['TABLE'] . "`
ORDER BY `"
. Controller :: $config['ROWS']['id'] . "` DESC";

$this -> userList = $this -> mysql -> setQuery($sql); // Запускаем запрос
$this -> userList = $this -> mysql -> getAssocArray($this -> userList); // Получаем ассоциативный масив пользователей
$this -> countRegUsers = self :: countItems($this -> userList); // Получаем количество зарегистрированных пользователей
}

/**
* Метод добавления пользователей
*/

private function addUser()
{
$sql = "INSERT INTO `" . Controller :: $config['DB']['TABLE'] . "`
(`"
. Controller :: $config['ROWS']['name'] . "`)
VALUES ('"
. $this -> mysql -> RES($_POST['regName']) . "')";

if($this -> mysql -> setQuery($sql))
{
header('Location: ' . $_SERVER['PHP_SELF']);
exit;
}
else
return
false;
}

/**
* Метод получения информации о пользователе
*/

private function getUserInfo()
{
$userId = (int)$_GET['id'];

$sql = "SELECT *
FROM `"
. Controller :: $config['DB']['TABLE'] . "`
WHERE `"
. Controller :: $config['ROWS']['id'] . "` = " . $userId;

if($this -> userInfo = $this -> mysql -> setQuery($sql))
{
$this -> userInfo = $this -> mysql -> getAssocRow($this -> userInfo); // Получаем информацию о пользователе
$this -> userInfo['date'] = !empty($this -> userInfo) ?
Controller :: formatDate($this -> userInfo['date']) : ''; // Форматируем дату регистрации в удобный вид

$this -> title = isset($this -> userInfo['name']) ?
'Пользователь: ' . $this -> userInfo['name'] :
$this -> title; // Устанавливаем заголовком страницы имя выбранного пользователя
}
else
return
false;
}

/**
* Метод поиска пользователя
*/

private function searchUsers()
{
$search = isset($_GET['search']) ? $_GET['search'] : NULL;

if($_SERVER['REQUEST_METHOD'] == 'GET' && $search != NULL)
{
$sql = "SELECT *
FROM `"
. Controller :: $config['DB']['TABLE'] . "`
WHERE `"
. Controller :: $config['ROWS']['name'] . "`
LIKE '%"
. addcslashes($this -> mysql -> RES($search), '%_\\\'') . "%'
ORDER BY `"
. Controller :: $config['ROWS']['date'] . "` DESC";

$this -> listUserSearch = $this -> mysql -> setQuery($sql); // Запускаем запрос
$this -> listUserSearch = $this -> mysql -> getAssocArray($this -> listUserSearch); // Получаем список зарегистрированных пользователей
$this -> countSearch = self :: countItems($this -> listUserSearch); // Количество найденых записей
}
else
return
$this -> errorSearch = 'Критерии поиска не зыданы !';
}

/**
* Метод возвращает количество записей
*/

private static function countItems($array)
{
return sizeof($array);
}

/**
* Метод формирования страницы
*/

protected function Output()
{
// Собираем все переменные в массив
$vars = Array(
'title' => $this -> title, 'userList' => $this -> userList,
'userInfo' => $this -> userInfo, 'listUserSearch' => $this -> listUserSearch,
'countSearch' => $this -> countSearch, 'countRegUsers' => $this -> countRegUsers,
'errorSearch' => $this -> errorSearch
);

// Указываем шаблон для отображения
// И передаем все переменные в метод который формирует страницу

return $this -> View('default', $vars);
}
}




Ну и шаблон, у меня он только один
default.tpl


<?php include_once PHIS_PATH . VIEW_DIR . 'baseTpl' . DS . 'top' . V_EXT; // Head страницы ?>

<?php if(isset($userInfo) && !empty($userInfo['date'])) : ?>
<div class="userInfo" id="userInfo">
<
span id="user">Пользователь:</span> <b><?php echo $userInfo['name']; ?></b>
<
a href="#" OnClick="document.location.href='index.php'">X</a><br/>
<
span id="regDate">Зарегистрирован:</span> <b><?php echo $userInfo['date']; ?></b>
</
div>
<?php endif; ?>

<?php

if(!empty($listUserSearch)) : ?>
<div class="searchUserList">
<
span class="countSearch">По запросу: <u><?php echo ($_GET['search']); ?></u><br/>
Найденно: <?php echo $countSearch; ?> совпадения</span><br/>
<
ul>
<?php foreach($listUserSearch AS $key => $val) : ?>
<li><a href="?search=<?php echo ($_GET['search']); ?>&id=<?php echo $val['id']; ?>"><?php echo $val['name']; ?></a></li>
<?php endforeach; ?>
</ul><br/><br/>
</
div>
<?php elseif(isset($_GET['search']) && $_GET['search'] == NULL) : ?>
<span class="notFound">Критерии поиска не заданы !</span>

<?php elseif($_SERVER['REQUEST_METHOD'] == 'GET' && isset($_GET['search'])) : ?>
<span class="notFound">По запросу: <u><?php echo isset($_GET['search']) ? ($_GET['search']): ''; ?></u><br/>
Ничего не найденно !</span><br/>
<?php endif; ?>

<?php
if(!empty($userList)) : ?>
<div class="countReg">
Зарегистрировано: <?php echo $countRegUsers; ?> пользователей
</div>
<
div class="userList">
<
ul>
<?php foreach($userList AS $key => $val) : ?>
<li><a href="?id=<?php echo $val['id']; ?>"><?php echo $val['name']; ?></a></li>
<?php endforeach; ?>
</ul>
</
div>

<?php else : ?>
<h2>Не зарегистрировано не одного пользователя !</h2>
<?php endif; ?>

<br/><br/>
<
form name="registration" action="" method="POST">
<
b>Введите имя:</b><br/>
<
input type="text" name="regName" value="<?php echo isset($_POST['regName']) ? $_POST['regName'] : ''; ?>"><br/>
<
input type="submit" name="regBtn" value="Зарегистрировать">
</
form>

<
form name="searchUser" action="" method="GET">
<
b>Поиск:</b><br/>
<
input type="text" name="search" value="<?php echo isset($_GET['search']) ? ($_GET['search']) : ''; ?>"><br/>
<
input type="submit" value="Искать">
</
form>

<?php include_once PHIS_PATH . VIEW_DIR . 'baseTpl' . DS . 'footer' . V_EXT; // Footer страницы ?>



Обкатать можно Здесь - Т.к. хост бесплатный и стоит лимит трафика и работает буферизация. Я это к тому, что если выдается белеберда то обновите страницу :)
Мое первое решение Здесь
Обкат первого решения Здесь
Благодарю за критику и уделенное внимание :)



Спустя 31 минута, 21 секунда (28.08.2011 - 17:08) inpost написал(а):
Winston
А где mysqli ? smile.gif

Спустя 1 минута, 40 секунд (28.08.2011 - 17:09) Winston написал(а):
Цитата (inpost @ 28.08.2011 - 17:08)
А где mysqli ?

С ней не работал. Потому и нету. А дописать не составить труда smile.gif

Спустя 6 минут, 53 секунды (28.08.2011 - 17:16) inpost написал(а):
Winston
А ты возьми и допиши. Тебя не смущает, что пишут: "начиная с php5.3 заканчивают поддержку обычной библиотеки mysql", а ей на смену пришла mysqli?
Зачем магические кавычки включил? Зачем register_globals? На современных серверах они автоматически выключаются, и на многих заблокирована возможность их включить.

Спустя 5 минут, 35 секунд (28.08.2011 - 17:22) Winston написал(а):
Цитата (inpost @ 28.08.2011 - 17:16)
Зачем магические кавычки включил

Ну это, чтобы подчеркнуть то, что скрипт не зависит от magic_quotes, это в условии было
Цитата
Требования.
...
5. Скрипт не должен зависеть от настройки magic_quotes.

Цитата (inpost @ 28.08.2011 - 17:16)
Зачем register_globals

Упс... протупил... Поправил.

Спустя 31 минута, 27 секунд (28.08.2011 - 17:53) twin написал(а):
Цитата (inpost @ 28.08.2011 - 14:16)
Зачем магические кавычки включил? Зачем register_globals? На современных серверах они автоматически выключаются, и на многих заблокирована возможность их включить.

А вот и нет. Агава допутим держит их включенными, а это далеко не последний хостер.

Спустя 1 минута, 52 секунды (28.08.2011 - 17:55) twin написал(а):
А вообще лично я не понимаю, зачем этот огород весь. Особенно с базой данных.
Совершенно лишняя работа, только людей позапутать. smile.gif

Спустя 5 минут, 40 секунд (28.08.2011 - 18:01) inpost написал(а):
twin
Первая мысль моя, когда увидел работу: "Сейчас тигрёнок придет, вот недоволен будет! Зачем городить огород..." smile.gif

Спустя 15 секунд (28.08.2011 - 18:01) Winston написал(а):
А где код для работы с базой писать? huh.gif
Цитата (twin @ 28.08.2011 - 17:55)
А вообще лично я не понимаю, зачем этот огород весь. Особенно с базой данных.

Ну а если будет использоваться другая БД ?



Спустя 27 секунд Winston написал(а):
Цитата (inpost @ 28.08.2011 - 18:01)
Первая мысль моя, когда увидел работу: "Сейчас тигрёнок придет, вот недоволен будет! Зачем городить огород..."

smile.gif

Спустя 5 часов, 41 минута (28.08.2011 - 23:42) neadekvat написал(а):
Цитата (twin @ 28.08.2011 - 18:53)
Агава допутим держит их включенными, а это далеко не последний хостер.

А у меня в htaccess прописано отключение, я и не парюсь.
А с виндовскими хостингами не работаю, о чем и предупреждаю заказчиков - хрен знает, какие там камни при работе с IIS.

Спустя 8 часов, 55 минут, 6 секунд (29.08.2011 - 08:37) twin написал(а):
Можно и htaccess конечно, но так надежнее. Особенно если скрипт не сам обслуживаешь. Пойдет по рукам, htaccess отстанет где-нибудь. Я на это попадался.

Да и в условиях задачи это было. А вот то, что он не будет работать в 5.3 ветке, ссылка все портит, печально.

И вот этот демарш мне вообще не ясен...
    /**
* Обработчик массива ф-ей htmlspecialchars
*/

public static function htmlChars(&$data)
{
if(is_array($data))
return $data = array_map('htmlspecialchars', $data);
else
return
$data = stripslashes($data);

return false;
}

/**
* Обработчик двумерного массива ф-ей htmlspecialchars
*/

protected static function htmlCharsDeep(&$data)
{
if(is_array($data))
{
$data = array_map(create_function('$item',
'
if(is_array($item))
return array_map("htmlspecialchars", $item);
else
return htmlspecialchars($item);
'
),
$data);
return $data;
}
else
return
false;
}


Причем тут stripslashes()? И вообще достаточно первый метод запустить рекурсивно и он обработает массивы любой вложенности, не только двумерные.

    /**
* Обработчик массива ф-ей htmlspecialchars
*/

public static function htmlChars($data)
{
if(is_array($data))
return $data = array_map(array(__CLASS__, __METHOD__), $data);
else
return
$data = htmlspecialchars($data);

}

Вообще вся это мишура ... ну если только потренироваться. Впечатление такое, что работа не ради результата, а ради процесса. Столько всего лишнего, просто ужос. Особенно БД.
Цитата
Ну а если будет использоваться другая БД ?
Не будет. Это миф, придуманный махровыми ООПэшниками, дабы оправдать наличие такого класса. Ибо:

1. Никогда коней на переправе не меняют. И базы данных тоже. Те крайне редкие исключеня, которые случаются по одному на десять жизней программиста, только подтверждают правило.
2. Если даже это случится, все равно придется переписывать запросы.
3. Такой класс путает синтаксис, а значит усложняет обслуживание.
4. Увеличивает накладные расходы.
5. Напрочь убивает диагностику. Так как раньше можно было ошибку найти в логах, а теперь нигде. У тебя же проверка на ресурс. Ошибка в запросе теперь ответит тишиной и придется дооолго греть голову, что да как.

Вобщем это все сделано исключительно для "красоты" и форса. Пользы от него никакой, так это бы и ладно. Но налицо вред. А это уже плохо.


Так то в целом по идее неплохо, но рационального зерна нет. Награмождение.

Спустя 1 час, 59 минут, 22 секунды (29.08.2011 - 10:36) alex12060 написал(а):
include_once PHIS_PATH . 'core'        . DS . 'Controller.php';                  // Главный контроллер


я бы посоветовал использовать require_once

Спустя 2 часа, 1 минута, 11 секунд (29.08.2011 - 12:38) Winston написал(а):
Цитата (twin @ 29.08.2011 - 08:37)
Причем тут stripslashes()?

Протупил малек... huh.gif
Цитата (twin @ 29.08.2011 - 08:37)
Так то в целом по идее неплохо, но рационального зерна нет. Награмождение

У меня один вопрос: Это похоже на MVC? rolleyes.gif



Спустя 22 минуты, 52 секунды Winston написал(а):
Цитата (twin @ 29.08.2011 - 08:37)
И вообще достаточно первый метод запустить рекурсивно и он обработает массивы любой вложенности, не только двумерные

Вот блин... Метод killQuotes по такому же принципу работает, а с этим протупил... ohmy.gif

Спустя 31 минута, 17 секунд (29.08.2011 - 13:09) killer8080 написал(а):
А это что? :blink:
define('DS'       , str_replace(DIRECTORY_SEPARATOR, '/', DIRECTORY_SEPARATOR)); 

Спустя 5 минут, 7 секунд (29.08.2011 - 13:14) Winston написал(а):
Цитата (killer8080 @ 29.08.2011 - 13:09)
А это что? blink.gif

smile.gif
Как знаешь, в винде разделители такие \ в линах такие /
Здесь любые разделители заменяются на /

Спустя 15 минут, 4 секунды (29.08.2011 - 13:29) killer8080 написал(а):
Цитата (Winston @ 29.08.2011 - 13:14)
Здесь любые разделители заменяются на /

а зачем str_replace, если результат всегда один и тот же? Не проще так ;)
define('DS', '/'); 

хотя если везде нужен прямой слеш, смысл вообще заводить константу? Так и пиши /.

Спустя 35 секунд (29.08.2011 - 13:30) inpost написал(а):
Winston
А почему бы сразу не написать "/" ?

Спустя 13 минут, 44 секунды (29.08.2011 - 13:43) Игорь_Vasinsky написал(а):
зачем вообще для одного симола заводить константу??? что круто смотрелось?

Спустя 8 минут, 6 секунд (29.08.2011 - 13:51) Greg1978 написал(а):
Цитата (Игорь_Vasinsky @ 29.08.2011 - 10:43)
зачем вообще для одного симола заводить константу??? что круто смотрелось?

кроссплатформенное решение, чем меньше хардкода тем гибче

Спустя 5 минут, 23 секунды (29.08.2011 - 13:57) Игорь_Vasinsky написал(а):
ну тут слеш вставляется в URL - чем его можно, нужно будет заменить? помоему ничем.

Спустя 1 минута, 13 секунд (29.08.2011 - 13:58) twin написал(а):
Ну запутался немного человек.

DS ставят для того, чтобы было короче писать. Слишком длинно называется предустновленная.

define('DS', DIRECTORY_SEPARATOR); 

А делается это как раз для того, чтобы юзать прямые или обратные слэши, в зависимости от оси. Только это анахронизм, PHP сейчас спокойно работает с обоими слэшами и вполне нормально скушает даже такое:

home/site\www/core\file.php

А посему прав inpost, константа эта вообще не нужна.

Спустя 1 минута, 23 секунды (29.08.2011 - 13:59) killer8080 написал(а):
Цитата (Greg1978 @ 29.08.2011 - 13:51)
кроссплатформенное решение, чем меньше хардкода тем гибче

в чём? Объявить константу в которой всегда прямой слеш?

Спустя 50 секунд (29.08.2011 - 14:00) Игорь_Vasinsky написал(а):
Цитата
А делается это как раз для того, чтобы юзать прямые или обратные слэши, в зависимости от оси

упс... как то это мне в голову не приходило.

Спустя 4 минуты, 53 секунды (29.08.2011 - 14:05) killer8080 написал(а):
Цитата (twin @ 29.08.2011 - 13:58)
А делается это как раз для того, чтобы юзать прямые или обратные слэши, в зависимости от оси. Только это анахронизм, PHP сейчас спокойно работает с обоими слэшами и вполне нормально скушает даже такое:

это было актуально для PHP4, а сейчас действительно анахронизм. И нужно было только для работы с файловой системой, в урл такое пихать нельзя. Ну да ладно, не буду придираться smile.gif

Спустя 16 минут, 35 секунд (29.08.2011 - 14:22) Winston написал(а):
Во зацепились то :D
Цитата (twin @ 29.08.2011 - 13:58)
нормально скушает даже такое:
home/site\www/core\file.php

Насчет этого не знал... Но так красивее то выглядит
home/site/www/core/file.php

Насчет того, что так
Цитата (killer8080 @ 29.08.2011 - 13:29)
define('DS', '/');
лучше... согласен.
А по поводу того, чтобы заводить константу...
До пустим в коде вручную понатыкивать / а потом может понадобились \ то, что вручную все исправлять? (... не мне об этом вам рассказывать :))
Потому ИМХО константа здесь кстати...

Спустя 1 минута, 2 секунды (29.08.2011 - 14:23) T1grOK написал(а):
Цитата (inpost @ 28.08.2011 - 15:01)
twin
Первая мысль моя, когда увидел работу: "Сейчас тигрёнок придет, вот недоволен будет! Зачем городить огород..." smile.gif

Я пришел! И я возмущен! mad.gif biggrin.gif

Спустя 1 минута, 54 секунды (29.08.2011 - 14:25) inpost написал(а):
Winston
ни разу не видел необходимости, чтобы она нужна была, обратный слеш, всмысле.

Спустя 4 минуты, 28 секунд (29.08.2011 - 14:29) Winston написал(а):
Цитата (inpost @ 29.08.2011 - 14:25)
ни разу не видел необходимости, чтобы она нужна была, обратный слеш, всмысле

Ну тогда чтобы
Цитата (Игорь_Vasinsky @ 29.08.2011 - 13:43)
круто смотрелось

biggrin.gif



Спустя 8 часов, 25 минут, 11 секунд Winston написал(а):
И все таки я хочу услышать ответ на вопрос: Это нагромождение кода которое я создал, похоже на MVC или это индусская MVC или вообще не MVC? smile.gif



Спустя 1 день, 29 минут, 34 секунды Winston написал(а):
Никто не знает ? huh.gif

Спустя 1 день, 1 час, 6 минут, 21 секунда (30.08.2011 - 15:35) twin написал(а):
Похожа, похожа smile.gif
Тебе даже тот, кто придумал эту аббривеатуру толком не скажет, как именно должен выглядеть скрипт, чтобы быть похожим. Главное, чтобы тебе было удобно.

Спустя 7 минут, 19 секунд (30.08.2011 - 15:43) Winston написал(а):
Успокоил smile.gif

Спустя 2 часа, 34 минуты, 8 секунд (30.08.2011 - 18:17) Winston написал(а):
Цитата (twin @ 29.08.2011 - 08:37)
А вот то, что он не будет работать в 5.3 ветке, ссылка все портит, печально

Из-за ссылки не будет работать? huh.gif
У меня 5.3.3 и все отлично работает smile.gif

Спустя 19 часов, 21 минута, 11 секунд (31.08.2011 - 13:38) Игорь_Vasinsky написал(а):
так я не понял с какой версии PHP забивает на сепаратор????

Спустя 1 час, 26 минут, 13 секунд (31.08.2011 - 15:04) killer8080 написал(а):
Цитата (Игорь_Vasinsky @ 31.08.2011 - 13:38)
так я не понял с какой версии PHP забивает на сепаратор????

точно не скажу с какой, но 5.2.4 под виндой однозначно работает с файловыми путями с /.

Спустя 8 часов, 58 минут, 33 секунды (2.09.2011 - 00:03) neadekvat написал(а):
Цитата (Игорь_Vasinsky @ 31.08.2011 - 14:38)
так я не понял с какой версии PHP забивает на сепаратор????

Вот ду ю спик эбаут? Это вообще относится к ОС, а не к PHP. А Винде, как известно, глубоко плевать, какой слэш. А никсами не плевать. Так почему бы не использовать / ? (не думаю, что кто-то ставит сервера на маках).

Спустя 38 минут, 30 секунд (2.09.2011 - 00:41) moskitos80 написал(а):
Что то ты с MVC всё перепутал...

MySql.php - это у тебя не модель, а уровень доступа к данным.

Методам: getUsers(), addUser(), getUserInfo(), searchUsers() - в контроллере не место. Выдели их в отдельный класс User, создай для него модель и в модель убери весь функционал по общению с БД. Статичному методу View в "ГЛАВНОМ" контроллере тоже не место... господи, почитай "Объекты, шаблоны и методики программирования" Мэта Зандстры. Шаблоны: Front Controller, Application Controller, Command, Factory.

Для MySql и User создай классы фабрик, что бы была возможность предварительной их конфигурации, можно так же сделать их "одиночками" ... в общем учись, "дорогу осилит идущий". smile.gif

PS
countItems($array) - вообще убил.
А вот код ты хорошо оформляешь. smile.gif

Спустя 8 часов, 21 минута, 3 секунды (2.09.2011 - 09:02) twin написал(а):
А позвольте полюбопытствовать, почему именно так? Почему нужно всех под одну гребенку? И именно под эту?

Зандстра конечно же молодец, кто спорит, но он не Бог. И слепо следовать его канонам - религиозный фанатизм.

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

Быть может Winston изобрел свой шаблон и быть может он лучше всех других. По крйней мере пока и для него.

Учиться конечно нужно, ни кто не спорит. Но вот такие советы меня лично повергают в ступор:
Цитата
Методам: getUsers(), addUser(), getUserInfo(), searchUsers() - в контроллере не место. Выдели их в отдельный класс User, создай для него модель и в модель убери весь функционал по общению с БД. Статичному методу View в "ГЛАВНОМ" контроллере тоже не место...


Да с чего ради? На каком основании делаются такие выводы? Где аргументация?
Может быть совсем наоборот, если идею развить дальше. Зачем это рубить крылья человеку, который наслаждается свободным полетом программирования, загонять его в золотую клетку шаблонов, да еще и под конкретную личность?

Весьма вероятно он скоро сам напишет кучу шаблонов.

Этим и отличаются программисты от кодеров. Программист разрабатывает код, кодер его использует.

Спустя 1 час, 8 минут, 19 секунд (2.09.2011 - 10:11) moskitos80 написал(а):
Зандстру - привёл как пример, если человек интересуется данной темой - это одна из книг на которую не жаль потраченного времени. Следовать его советам, или нет - личное дело каждого. Умный человек сам поймет чего ему нужно.

Winston изначально спросил:
Цитата
...как практически применяется шаблон MVC...

Цитата
... Надеюсь, что у меня получилось хоть какое-то подобие этого шаблона...

Он не написал: "Я изобрёл свой шаблон - зацените" - Человек учиться, и я не собирался ни кому рубить крылья, а просто хотел дать совет и указать на неточности. Или за это уже "дёгтем и в перья"?

По поводу методов тоже не указание, а совет. А ваше:
Цитата
На каком основании делаются такие выводы? Где аргументация?

На основании того же шаблона MVC. Ведь, если не ошибаюсь, его то как раз Winston и хочет понять.
Уважаемый Winston и вы twin, если Вам интересно: посмотрите пункт "Наиболее частые ошибки" :MVC Wiki
И вообще: почему бы новичкам не указывать на их ошибки, чтобы они учитывали их в будущем?

PS
А по поводу "кодера" - я не принял это на свой счет - я знаю какой код Я пишу, как он работает, расширяется и поддерживается в итоге, а так же как используется повторно. Поэтому не считаю нужным кому либо что то доказывать.

Спустя 43 минуты, 15 секунд (2.09.2011 - 10:54) twin написал(а):
Цитата
просто хотел дать совет и указать на неточности.
Это нужно обозначать. Неточности в чем? В шаблоне, который предлагаете и используете Вы? Или в шаблоне, который используется в ZEND-фреймворке, описанный как частный случай в википедии и с какого то перепуга воспринимаемый всеми как единственно правильный? Или шаблоне, предлагаемым тем же Зандстрой?

Что значит неточности? Судя из совета, предлагаются конкретные действия:
Цитата
Методам: getUsers(), addUser(), getUserInfo(), searchUsers() - в контроллере не место. Выдели их в отдельный класс User, создай для него модель и в модель убери весь функционал по общению с БД. Статичному методу View в "ГЛАВНОМ" контроллере тоже не место...
Второй раз спрошу, да почему не место то? Зачем убирать? Где обоснование того, что у него сделано неверно? И чем это может грозить?

Просто так сказать - все неверно, это не MVC - нельзя. Ибо MVC, это шаблон, который позволяет разделить бизнесс-логику с логикой представления. А то, что у Winston - вполне подпадает под это определение. Все остальное - частности.

Цитата
Уважаемый Winston и вы twin, если Вам интересно: посмотрите пункт "Наиболее частые ошибки" :MVC Wiki
И вообще: почему бы новичкам не указывать на их ошибки, чтобы они учитывали их в будущем?

Да, действительно, нужно указывать на ошибки. Допустим одна из самых распространенных - безпеляционно верить всему, что написано в википедии. Повторю - никакого отношения пункт "Наиболее частые ошибки" к паттерну MVC не имеет. Потому что описывает реализацию паттерна в конкретном продукте. А реализация уже есть суть не шаблон.

Цитата
А по поводу "кодера" - я не принял это на свой счет
Никого лично я и не имел ввиду... Просто предостерег от того, что копипаст из учебников не всегда полезен для программистов.

Спустя 1 час, 33 минуты, 26 секунд (2.09.2011 - 12:27) moskitos80 написал(а):
Как то Вы уважаемый twin все буквально воспринимаете. На википедию я сослался без какого либо умысла. MVC можно трактовать и реализовывать по-разному, и толстыми контроллерами, и тонкими, да хоть маринованными... Спорить по этому поводу можно долго - не вижу смысла. Каждый в итоге делает как ему удобнее и понятнее, а правильно ли он сделал или нет он узнает позже.

Вы правы: паттерны это всего лишь идея, удачная реализация какого то круга, или одной задачи - не важно. Важно что это всего лишь идея, о том как сделать в данной ситуации лучше. А за идею у нас в стране революцию сделали biggrin.gif . Тем более, что паттерны не лишены недостатков, о них тоже, кстати написано.

Так что вступать в спор с вами я не стану.

Но только поясню по поводу методов из за которых сыр-бор: ведь удобнее поместить их в собственный класс. И позже, если понадобится рефакторинг или оптимизация кода, то сохраняя внешний интерфейс класса, сам класс можно переделывать как душе угодно, при этом не трогая код остального приложения - удобно. При расширении функционала можно либо добавлять методы в уже существующую модель, либо создать новую, и подключать её при необходимости. А что касается методов, относящихся к работе с данными пользователя, то выделив и их в отдельный класс мы получаем те же преимущества.

По сути, шаблоны то нам дают лишь удобные возможности для работы и расширения функционала, уберегают от дублирования кода, и выхода его из под контроля, когда сам автор уже не понимает что к чему, позволяют писать классы, которые мы используем в дальнейшем и которые не зависят от окружающего контекста . Можно ж начхать на "все MVC" и писать вообще всё в одном файле, а потом застрелиться, если что то нужно будет добавить или переделать.

Спустя 23 часа, 28 минут, 22 секунды (3.09.2011 - 11:56) Гость_Greg1978 написал(а):
Цитата (twin @ 2.09.2011 - 06:02)
Учиться конечно нужно, ни кто не спорит. Но вот такие советы меня лично повергают в ступор:
Цитата
Методам: getUsers(), addUser(), getUserInfo(), searchUsers() - в контроллере не место. Выдели их в отдельный класс User, создай для него модель и в модель убери весь функционал по общению с БД. Статичному методу View в "ГЛАВНОМ" контроллере тоже не место...


Да с чего ради? На каком основании делаются такие выводы? Где аргументация?
Может быть совсем наоборот, если идею развить дальше. Зачем это рубить крылья человеку, который наслаждается свободным полетом программирования, загонять его в золотую клетку шаблонов, да еще и под конкретную личность?

Весьма вероятно он скоро сам напишет кучу шаблонов.

Этим и отличаются программисты от кодеров. Программист разрабатывает код, кодер его использует.

На основании разделения знаний и абстракций. Сами интерфейсы уже "кричат" юзер - юзер smile.gif
Уже лезет абстракция User.
А контроллер всего лишь управляющая абстракция а не как не хранящая данные и параметры.
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.