Как убрать дублирование кода?

weldp

Новичок
Есть "приложение работы со складом". Есть различные сущности: Пользователи и привилегии; Склады; Товары; Описания товаров, категории, номенклатура; Логи действий...
Тут нет никакой замысловатой бизнес логики и все храниться в базе данных.

PHP:
<?php
/*
Пришел GET-запрос: В зависимости от того по какому адресу(routing) - отображаем в темплейте результат выборки из базы.
Пришел POST-запрос: routing - Проверяем что есть права на действие, проверяем что все правильно, выполняем {update || remove || insert }  1-2 запроса к базе данных
*/

//slim framework взят просто для наглядности.
require 'Slim/Slim.php';
require 'Views/TwigView.php';


try { 
  $DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass); 
 
} 
catch(PDOException $e) { 
    echo $e->getMessage(); 
}

// www.slimframework.com - PHP micro framework
$app = new \Slim\Slim();

// выполняем функцию при get-запросе /api/get/user/ид
$app->get('/api/get/user/(:id)', function ($id,$DBH) use ($app) {

    try {  $STH = $DBH->prepare("SELECT FROM  `user` WHERE .....");  } 
    catch(PDOException $e) { 
      echo $e->getMessage(); 
    }
......................
    return $app->render('get_user_id.html', array(
        'action_name'    =>    'View',
        'action_url'    =>    '/api/get/user/' . $id,
        ......................
    ));
});

// выполняем функцию при post-запросе /api/get/user/ид
$app->post('/api/get/user/(:id)', function ($id,$DBH) use ($app) {
  if (validate(request()->post('name'))==true) ){   
            $STH = $DBH->prepare("INSERT INTO `user` ( name ) values ( 'Cathy' )"); 
    }
................
    return $app->render('get_user_id.html', array(
        'action_name'    =>    'Edit',
        'action_url'    =>    '/api/get/user/' . $id,
        ......................
    ));


});
$app->run();

?>
Итак вся эта реализация связана с дублированием кода. Дело в том, что "Сохранение Товара" отличается от "Сохранения Пользователя" - конечным SQL, и валидацией перед сохранением
 

Вурдалак

Продвинутый новичок
А где именно дублирование?

И почему при $app->post() рендится страница? Логичнее вернуть new RedirectResponse('/api/get/user/'.$id).
 

Фанат

oncle terrible
Команда форума
Как минимум убрать дублирование бессмысленного кода

PHP:
<?php
require 'Slim/Slim.php';
require 'Views/TwigView.php';

$DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);

// www.slimframework.com - PHP micro framework
$app = new \Slim\Slim();

// выполняем функцию при get-запросе /api/get/user/ид
$app->get('/api/get/user/(:id)', function ($id,$DBH) use ($app) {
$STH = $DBH->prepare("SELECT FROM  `user` WHERE .....");
......................
return $app->render('get_user_id.html', array(
        'action_name'    =>    'View',
        'action_url'    =>    '/api/get/user/' . $id,
        ......................
    ));
});
Код сразу значительно сокращается.
 

weldp

Новичок
$app->get и $app->post - функции обьекта-роутера

А где именно дублирование?
.
Имеем разные результаты из базы данных, но одинаковый алгоритм обработки

PHP:
/*************
     GET
***************/

$app->get('/api/get/user/(:id)', function ($id) use ($app,$DBH) {
  /*
  1.Проверка Правильности GET-запроса
  2.Выполнение запроса к Базе данных
 
  ......................
  */
  return $app->render('.... РЕНДЕРИНГ СТРАНИЦЫ..................' ));
});
$app->get('/api/get/warehouse/(:id)', function ($id) use ($app,$DBH) {
  /*
  1.Проверка Правильности GET-запроса
  2.Выполнение запроса к Базе данных
 
  ......................
  */
  return $app->render('.... РЕНДЕРИНГ СТРАНИЦЫ..................' ));
});
$app->get('/api/get/acl/(:id)', function ($id) use ($app,$DBH) {
  /*
  1.Проверка Правильности GET-запроса
  2.Выполнение запроса к Базе данных
 
  ......................
  */
  return $app->render('.... РЕНДЕРИНГ СТРАНИЦЫ..................' ));
});
$app->get('/api/get/log/(:id)', function ($id) use ($app,$DBH) {
  /*
  1.Проверка Правильности GET-запроса
  2.Выполнение запроса к Базе данных
 
  ......................
  */
  return $app->render('.... РЕНДЕРИНГ СТРАНИЦЫ..................' ));
});
$app->get('/api/get//(:id)', function ($id) use ($app,$DBH) {
  /*
  1.Проверка Правильности GET-запроса
  2.Выполнение запроса к Базе данных
 
  ......................
  */
 
  return $app->render('.... РЕНДЕРИНГ СТРАНИЦЫ..................' ));
});


/*************
      POST
***************/


$app->post('/api/post/user/(:id)', function ($id) use ($app,$DBH) {
  /*
  1.Проверка Правильности POST-запроса
  2.В зависимости от того: ОБНОВЛЕНИЕ/СОЗДАНИЕ/УДАЛЕНИЕ - Выполнение различный запрос к Базе данных
  ......................
  */
  $app->redirect('/api/post/user/');
});
$app->post('/api/post/warehouse/(:id)', function ($id) use ($app,$DBH) {
  /*
  1.Проверка Правильности POST-запроса
  2.Выполнение запроса к Базе данных
  ......................
  */
  $app->redirect('/api/post/warehouse/');
});
$app->post('/api/post/acl/(:id)', function ($id) use ($app,$DBH) {
  /*
  1.Проверка Правильности POST-запроса
  2.Выполнение запроса к Базе данных
  ......................
  */

  $app->redirect('/api/post/acl/');
});
$app->post('/api/post/log/(:id)', function ($id) use ($app,$DBH) {
  /*
  1.Проверка Правильности POST-запроса
  2.Выполнение запроса к Базе данных
  ......................
  */
  $app->redirect('/api/post/log/');
});
Блин ошибся и роутинг неправильно в пост методе прописал
И почему при $app->post() рендится страница? Логичнее вернуть new RedirectResponse('/api/get/user/'.$id).
.
Спасибо, буду использовать для ПОСТа - редирект ;)
 
Последнее редактирование:

Вурдалак

Продвинутый новичок
weldp, использовать другой фреймворк? Другие уровни абстракции? Некоторые современные фреймворки позволяют сократить код до
PHP:
class UserController {
    /**
     * @Template
     */
    public function getUserAction(User $user) {
        return $user;
    }

    /**
     * @Template
     */
    public function postUserAction(Request $request) {
        $user = new User;
        $form = $this->createFormBuilder($user)->getForm();
        $form->handleRequest($request);

        if ($form->isValid()) {
            $this->userRepository->save($user);

            return $this->redirect($this->generateUrl('user', ['id' => $user->getId()]));
        }

        return ['form' => $form->createView()];
    }
}
 

weldp

Новичок
weldp, использовать другой фреймворк? Другие уровни абстракции?
так я и хочу =)
По сути у меня есть Классы: Пользователь, Склад, Товар и т.д. у которых различные реализации функций тех же функций. XClassName - переменное название класса. Но это то, как я это сейчас вижу

PHP:
$app->get('/api/get/XClassName/(:id)', function ($id) use ($app,$DBH) {

  $XClassName->get_permition_for_operation();
  $XClassName->validate_input_get_array( $some_input_param);
  $_params_array=$XClassName->get_value_to_rend();

   return $app->render('template_get_XclassName.tml', $_params_array ));
});


$app->post('/api/post/XClassName/(:id)', function ($id) use ($app,$DBH) {
 $XClassName->get_permition_for_operation();
 
 $_post_array=array('XparamName'=> $app->request->post('paramName'), 'Yparam'=> $app->request->post('paramY'),...);
 $XClassName->validate_post_input($_post_array);
 $XClassName->save_to_storage();


   return $app->redirect('/api/post/XClassName/');
});
Я думал может неким хитрым образом сделать
 

Вурдалак

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

weldp

Новичок
Это намного хуже, чем написать явно, пусть и с дублированием. Нет класса — нет интерфейса. Это тухлая абстракция.
...и я о том же =) Нужно решить это, во смотрю на шаблоны проектирования, но не могу понять что подойдет?

С этим кодом несколько проблем - например при написании не был во всех случаях (а их 6-ть) написан вызов для: $XClassName->validate_input_get_array( $some_input_param) - Таким образом можно в одном из сценариев не авторизированым пользователям позволить манипулировать/или непроверенные данные записать или еще что-то.

Смотрю на шаблоны проектирования, есть мысли, но не могу написать ;)
 

Фанат

oncle terrible
Команда форума
Как я уже писал выше, надо убирать мусорный код.
как только он уберется, останутся только те самые "конечный SQL и валидацией перед сохранением" плюс пара управляющих структур.

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