И снова ООП - как хранить и задействовать настройки для каждого свойства?

Timol

Новичок
Не так давно изучаю ООП и столкнулся с проблемой - как хранить и задействовать настройки для каждого свойства?
В Гугле ответ на свой вопрос я не нашел - возможно просто не о том спрашивал?
Для того, чтобы было понятно, о чем идет речь, ниже я вкратце опишу то, что я пытаюсь сделать сейчас для того, чтобы разобраться в ООП - cвой lite велосипед/framework.

Основная задача framework`a - перегонять данные из одного источника в другой, например, можно взять простые случаи: GET-данные, полученные в форме, нужно передать в БД или вытянуть данные из БД и отобразить в виде HTML.
Для того, чтобы не было проблем с получаемыми данными - все данные строго типизированы. Для примера я буду рассматривать случай, когда GET-данные, полученные в форме, нужно передать в БД. Есть несколько полей формы и соответствующие им колонки в БД: user_name, datetime. Для каждого вида данных я создаю отдельный массив - получается жуткая вложенность, но пока что без знаний ООП, работает все именно так. Ниже пример описания свойств - 2 полей формы, кода хоть и много, но разобраться в нем, я думаю, не составит труда:

PHP:
$cnf['user_name']['name'] = 'Имя пользователя';
$cnf['user_name']['data']['internal']['type'] = 'string';
$cnf['user_name']['data']['internal']['string']['min'] = 2;
$cnf['user_name']['data']['internal']['string']['max'] = 50;
$cnf['user_name']['data']['internal']['string']['pattern'] = '|^[a-z]$|ui';
$cnf['user_name']['data']['internal']['string']['empty'] = false;
$cnf['user_name']['data']['db']['type'] = 'string';
$cnf['user_name']['data']['db']['column'] = 'user_name';
//...

$cnf['datetime']['name'] = 'Дата пользователя';
$cnf['datetime']['data']['internal']['type'] = 'string';
$cnf['datetime']['data']['internal']['string']['min'] = 19;
$cnf['datetime']['data']['internal']['string']['max'] = 19;
$cnf['datetime']['data']['internal']['string']['pattern'] = 'регулярка на соответствие даты такому формату: 2016-12-27 10:20:31';
$cnf['datetime']['data']['internal']['string']['empty'] = true;
$cnf['datetime']['data']['db']['type'] = 'datetime';
$cnf['datetime']['data']['db']['datetime']['timezone'] = $_SESSION['user_timezone'];
$cnf['datetime']['data']['db']['column'] = 'user_date';
//...
На самом деле настроек для каждого свойства намного больше, чем я привел выше, но для того, чтобы объяснить суть моего вопроса - вполне достаточно.
Все эти данные нужны чтобы запустить 2 класса: GetData($cnf) - получить, проверить на ошибки и преобразовать в случае необходимости полученные данные и выдать $data и SetData($cnf, $data) - подготовить данные к записи в БД (escapeslach, etc) и записать.

Как эту "простыню" кода разбить по объектам? Т.е. приблизительно, я это себе представляю так: создаются классы для каждого типа данных (Data/Internal/String, Data/Db/String, Data/Db/Datetime, ...), потом классы (Name, Data)?
Подозреваю, что строгая типизация, наподобие того, что я привел в виде массива, уже кем-то придумана и где-то используется в виде ООП?
 

fixxxer

К.О.
Партнер клуба
Примеры из Доктрины могут навеять неверные мысли о том, что анемичные модели имеют отношение к ООП.

Если все, что от бэкенда требуется, это валидация данных и хранение их в базе данных, а какая-либо бизнес-логика отсутствует вообще, можно взять готовое решение типа Parse/StrongLoop и ничего не программировать вообще, только конфиги написать.
 

WMix

герр M:)ller
Партнер клуба
А почему бы просто не использовать эти сущности? Ну те. Доктрина заполнила обьект, и на этом ее задачи окончились. Осталось только крови налить
 

fixxxer

К.О.
Партнер клуба
Ну, если есть чем.

У него задача "перегонять данные из одного источника в другой", для этого никакого ООП и не надо
 

Timol

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

AnrDaemon

Продвинутый новичок
Ты разницу между "форматом" и "источником" вообще не ощущаешь?
 

fixxxer

К.О.
Партнер клуба
конвертацией данных из одного формата в другой занимаются практически все приложения
Вот если говорить о разработке таковых (data mapper какой-нибудь) - тогда уже можно предметно рассуждать.

Ты показал кусок конфигурации, для определения конфигурации не нужен никакой ООП, для этого нужен файл с конфигурацией (капитан, да). Можно в php-массивах писать (кстати, если ты запишешь в нормальном виде, а не по одной строчке с присваиваниями, сразу станет намного удобнее), можно в каком-нибудь yaml или xml-конфиге, это вообще не имеет значения абсолютно никакого.

Кстати, ты зря смешиваешь валидацию ввода и маппинг в одном конфиге.
 

Timol

Новичок
... для определения конфигурации не нужен никакой ООП, для этого нужен файл с конфигурацией (капитан, да). Можно в php-массивах писать, можно в каком-нибудь yaml или xml-конфиге
Да, конфиг можно записать хоть в JSON, но как потом с ним работать, ведь все равно его будет нужно один раз загнать в массив или объект, не перечитывать же его каждый раз для каждого параметра/настройки? Потом нужно проверить всю конфигурацию на ошибки, например чтобы ['string'] содержал, как минимум 2 параметра: min и max и не содержал чего-то лишнего, и так для всех параметров. В конфиге могут встречаться свойства с одинаковыми параметрами. Например first_name и last_name имеют идентичные настройки ['min'], ['max'], ['pattern'] - как-то нужно предусмотреть механизм, чтобы раз задав настройки для Name, они бы автоматически применялись к first_name и last_name?

Есть базовая (default) конфигурация, в которой описаны все свойства, например, товара. И есть конфигурация для каждого случая, например, добавление товара, где из базовой конфигурации выбираются только те свойства, которые нужны для выполнения действия по добавлению товара (конвертация данных из POST в БД) и каждому свойству добавляются новые параметры: source, destination, etc для инструктирования скриптов - что делать с данными (откуда брать, куда записывать).

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

Sufir

Я не волшебник, я только учусь
пример "нормального ввода"
PHP:
$config = [
    'user_name' => [
        'name' => 'Имя пользователя',
        'data' => [
            'internal' => [
                'type' => 'string',
                'string' => [
                    'min' => 2,
                    'max' => 50,
                    'pattern' => '|^b64a-z]$|ui',
                    'empty' => false,
                ],
            ],
            'db' => [
                'type' => 'string',
                'column' => 'user_name',
            ],
        ],
    ],
    'datetime' => [
        'name' => 'Дата пользователя',
        'data' => [
            'internal' => [
                'type' => 'string',
                'string' => [
                    'min' => 19,
                    'max' => 19,
                    'pattern' => 'регулярка на соответствие даты такому формату: 2016-12-27 10:20:31',
                    'empty' => true,
                ],
            ],
            'db' => [
                'type' => 'datetime',
                'datetime' => [
                    'timezone' => 'user_timezone',
                ],
                'column' => 'user_date',
            ],
        ],
    ],
];
 
Последнее редактирование:

fixxxer

К.О.
Партнер клуба
но как потом с ним работать
При разработке ничего страшного, если парсить каждый раз, на продакшене - кэшировать результат парсинга.
Например first_name и last_name имеют идентичные настройки ['min'], ['max'], ['pattern'] - как-то нужно предусмотреть механизм, чтобы раз задав настройки для Name, они бы автоматически применялись к first_name и last_name?
Не вижу ничего страшного в копипасте в конфигах, но если так уж напрягает, можно написать что-то вида
PHP:
$nameParams = ['min' => 20,...];
...
$cfg = [
    'first_name' => $nameParams,
    'last_name' => $nameParams + ['other_option' => 100],
];
Ну или использовать yaml, там есть ссылки.

В общем какие-то у тебя детские проблемы :)
 

Timol

Новичок
Пример нормального ввода:
Попробую воспользоваться, но пока что, мой вариант записи массива мне нравится больше. В стандарте PSR, к сожалению, подходящего примера я не нашел.

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

можно написать что-то вида...
Ну или использовать yaml, там есть ссылки.
Вот именно так оно сейчас и написано, я думал ты предложишь что-то получше :) А по поводу ссылок в yaml - спасибо, пойду смотреть документацию.
 

fixxxer

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

AnrDaemon

Продвинутый новичок
@Timol, слушай дядю… я как раз сейчас с таким проектом [цензура]…
Попросили добавить к цене способ указания… всё, структура сайта уже в конфиг не влезает.
 

Timol

Новичок
На самом деле многие описанные тобой проблемы уже решены. Массив $cnf['user_name'] лежит в другом массиве, назовем его, $megacnf['property'], в котором собрано все то, что нужно обработать за раз. В $megacnf['conf_all'] хранятся общие параметры. Каждому свойству $cnf прописывается, откуда его взять и куда вставить, между этими двумя действиями можно выполнить любую обработку данных. У каждого свойства прописываются параметры, например какой запрос БД использовать при чтении или записи, поэтому user_name можно записать в одну таблицу, а user_phone - в другую. Если, например, пользователь за раз может добавить несколько телефонов - пожалуйста, создаем отдельную модель ($megacnf) только для телефонов. Проблема в другом - код должен быть максимально понятным, чего я и пытаюсь достичь средствами ООП.
 

fixxxer

К.О.
Партнер клуба
А если для добавления телефона нужно сделать подтверждение владением этим номером путем отправки и сверки одноразового кода смской, это в твоей схеме как будет выглядеть?
 

AnrDaemon

Продвинутый новичок
@Timol, вот прямо сейчас здесь - ты запутываешь свой код, а не делаешь его понятнее.
 

Timol

Новичок
А если для добавления телефона нужно сделать подтверждение владением этим номером путем отправки и сверки одноразового кода смской, это в твоей схеме как будет выглядеть?
Запись телефона: одна модель, отображение формы для ввода СМС-ки - другая, обработка СМСки на корректность - третья. Логика отправки СМС-ки запускается после обработки формы с номером (если не возникло ошибок). Да, еще забыл, что самая первая модель - это форма для ввода данных о телефоне.

P.S. Оставлять всякий спам, типа ": popcorn: :)" и "@Timol, вот прямо сейчас здесь - ты запутываешь свой код, а не делаешь его понятнее." - это приветствуется на этом форуме? Помоему, посты которые мало того, что не по теме, так еще и не несут никакой полезной смысловой нагрузки на форме о ПХП, нужно нещадно прибивать :) Ведь ветку читают не только те, кто участвует в обсуждении, но и много других, ни в чем не повинных, пользователей.
 

Adelf

Administrator
Команда форума
@Timol, а это не спам. Я смотрю когда же fixxer наберет критическую массу аргументов, чтобы убедить тебя :) И смотрю как интересный фильм :) Поэтому и попкорн. Ты пытаешься соптимизировать то, что не поддается оптимизации(точнее CRUD - уже давным давно исследованная тема, и есть куча способов это решать и твой точно не в лучших). Итогом будет гораздо более сложная структура кода+конфига, чем могла бы быть.

обработка СМСки на корректность - третья.
И она тоже пойдет в табличку базы?
 
Сверху