@targeting24

Пожалуйста, проведите код ревью, норм, не норм?

Задача построение дерева рефералов сетки партнера по следующим критериям:
посчитать суммарный объем volume * coeff_h * coeff_cr по всем уровням реферральной системы за период времени
посчитать прибыльность (сумма profit) за определенный период времени
посчитать количество прямых рефералов и количество всех рефералов клиента
<?php


namespace app\commands;


use app\models\Users;
use yii\console\Controller;
use \yii\helpers\BaseConsole;
use yii\helpers\Console;

/**
 * Class ReferralController
 * @package app\commands
 */
class ReferralController extends Controller
{
    /**
     * Метод для построения дерева и вывода общего количества рефералов
     */
    public function actionTree(){
        //Вводим uid полльзователя
        $client_uid = BaseConsole::input("Введите uid пользователя: ");
        $this->checkValidUid($client_uid);

        //Получаем всех пользователей
        $users = Users::find()
            ->select(['client_uid', 'partner_id'])
            ->asArray()
            ->all();

        /**
         * Функция прохода по всем пользователя и поиск рефералов (используется рекурсивный метод)
         *
         * @param $users //массив пользователей
         * @param $client_uid //uid клиента
         * @param int $level // уровень, то есть вложенность рефералов меняется если находим у реферала реферала
         */
        function printBuildTree($users, $client_uid, $level = 0) {
            foreach ($users as $arr) {
                if ($arr['partner_id'] == $client_uid) {
                    if ($level == 0){
                        //Печать дерева
                        echo "|" . "    |-- " . $arr['client_uid']  ."\n";
                    }
                    else{
                        //Печать дерева
                        echo "|" . str_repeat("    |-- ", $level + 1) . $arr['client_uid'] . "\n";
                    }
                    //Сама рекурсия, то есть находим реферала и для него ищем реферала
                    printBuildTree($users, $arr['client_uid'], $level + 1);
                }
            }
        }

        /**
         * Функция подсчета прямых рефералов
         *
         * @param $users
         * @param $client_uid
         * @param int $level
         * @param int $i
         * @return int
         */
        function getDirectReferral($users, $client_uid, $level = 0, $i = 0) {
            foreach ($users as $arr) {
                if ($arr['partner_id'] == $client_uid) {
                    if ($level == 0){
                        $i++;
                        $i += getDirectReferral($users, $arr['client_uid'], $level + 1);
                    }
                }
            }
            return $i;
        }

        /**
         * Функция подсчета всех рефералов
         *
         * @param $users
         * @param $client_uid
         * @param int $level
         * @param int $i
         * @return int
         */
        function getAllReferral($users, $client_uid, $level = 0, $i = 0) {
            foreach ($users as $arr) {
                if ($arr['partner_id'] == $client_uid) {
                    $i++;
                    $i += getAllReferral($users, $arr['client_uid'], $level + 1);
                }
            }
            return $i;
        }
        echo "|-- " . $client_uid . "\n";

        $result = printBuildTree($users, $client_uid);
        echo $result;
        echo "Всего прямых рефералов: " . getDirectReferral($users, $client_uid) . "\n";
        echo "Всего всех рефералов: " . getAllReferral($users, $client_uid) . "\n";
        //82824897
    }

    /**
     * Метод получения Прибыльности и Суммарного объема
     */
    public function actionTotalVolume(){
        //Вводим uid полльзователя
        $client_uid = BaseConsole::input("Введите uid пользователя: ");
        //Вводим дату ОТ
        $date_from = BaseConsole::input("Введите дату ОТ в формате ГОД-Месяц-День ЧАСЫ:МИНУТЫ:СЕКУНДЫ ");
        //Вводим дату ДО
        $date_to = BaseConsole::input("Введите дату ДО в формате ГОД-Месяц-День ЧАСЫ:МИНУТЫ:СЕКУНДЫ ");
        $this->checkValidUid($client_uid);

        //Проверяем если ввели дату то делаем условие
        if (!empty($date_from)){
            $date_from_condition = ['>=', 't.close_time',
                $date_from];
        }
        else{
            $date_from_condition = [];
        }

        //Проверяем если ввели дату то делаем условие
        if (!empty($date_to)){
            $date_to_condition = ['<=', 't.close_time',
                $date_to];
        }
        else{
            $date_to_condition = [];
        }

        //Получаем всех пользователей
        $users = (new \yii\db\Query())
            ->select(['volume', 'coeff_h', 'coeff_cr', 'a.client_uid', 'profit', 'partner_id'])
            ->from(['u' => 'users'])
            ->leftJoin(['a' => 'accounts'], 'a.client_uid = u.client_uid')
            ->leftJoin(['t' => 'trades'], 't.login = a.login')
            ->where(['u.client_uid' => $client_uid])
            ->andWhere($date_from_condition)
            ->andWhere($date_to_condition)
            ->all();
        $total_volume = 0;
        $sum_profit = 0;
        foreach ($users as $arr) {
            $total_volume += $arr['volume'] * $arr['coeff_h'] * $arr['coeff_cr'];
            $sum_profit += $arr['profit'];
        }

        echo "Прибыльность: " . $sum_profit . "\n";
        echo "Суммарный объем: " . $total_volume . "\n";
    }

    /**
     * Функция проверки на пустоту и валидность uid
     *
     * @param $client_uid
     */
    protected function checkValidUid($client_uid){
        if (empty($client_uid) || !is_numeric($client_uid)){
            $this->stdout("uid не может быть пустым и должен содержать число \n", Console::FG_RED);
            exit();
        }
    }
}
  • Вопрос задан
  • 204 просмотра
Решения вопроса 1
maksim92
@maksim92 Куратор тега Yii
Нашёл решение — пометь вопрос ответом!
Если кратко — главное чтобы работало, в вашем случае.

Если чуть развёрнуто:
  1. Функция в функции плохо. Выносите.
  2. Весь код в контроллере тоже плохо. Выносите в калькуляторы, сервисы, репозитории.
  3. Используйте camelCase в переменных.
  4. Посмотрите в документации как правильно получать через консоль пользовательские данные (input)
  5. Некоторые комментарии излишние и некоторые названия не логичны. Уберите лишние комментарии и поработайте над неймингом.

Это основные моменты. Тут стоит опираться не на код, а на Ваши знания. Вам не хватает знаний и стоит погрузиться в тему рефакторинга, ООП, чистый код и т.д.

Ваш код — результат Ваших знаний.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
slashinin
@slashinin
Задачи для PHP https://justcoding.ru
Соглашусь с Максимом и от себя добавлю, что при сложных выборках с использованием агрегирующих функций типа суммирования и т.п. стоит рассмотреть вариант с денормализацией данных для ускорения и упрощения подсчетов. Т.е. создать копию данных со структурой при которой подсчет будет проще и быстрее.

Описание метода денормализации данных
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы