PankovAlxndr
@PankovAlxndr
Fullstack web developer

Как генерировать уникальную строку перед сохранение в БД (D7 bitrix)?

Здравствуйте.
Редакция старт.

Написал свой модуль и лежим в local/modules/my.name/Order/OrderTable.php
Это описанная модель таблицы с заказами.

Те у нас есть таблица, в которой есть поля id, user_id, delivery_id ....
вообщем много полей всяких и одно из эти х полей называется order_num и имеет строковый формат
Как вы уже навреное догадались это номер заказа и он должен быть уникальным (именно номер а не id в базе)
class OrderTable extends Entity\DataManager
{
    public static function getTableName()
    {
        return 'dch_order';
    }


    public static function getMap()
    {
        return array(
            new Entity\IntegerField('ID', array(
                'primary' => true,
                'autocomplete' => true
            )),
            new Entity\StringField('ORDER_NUM', array(
                'required' => false
            )),
.......
    }

Описание модели примерно такое (выше)
У меня стояла задача присваивать номер заказу уникальный
самый простой случай - это брать последний номер и прибавлять 1 - получается новый номер заказа

решил я это через события и в том же файле local/modules/my.name/Order/OrderTable.php добавил
public static function onBeforeAdd(Entity\Event $event)
{
    $result = new Entity\EventResult;
    $data = $event->getParameter("fields");
    if (!$data['ORDER_NUM']) {
        $resOrders = OrderTable::getList([
            'select' => ['ID', 'DATE_CREATE', 'ORDER_NUM'],
            'order' => ['ORDER_NUM' => "DESC"],
            'filter' => ['!ORDER_NUM' => false],
            'limit' => 1
        ]);
        if ($arOrder = $resOrders->fetch()) {
            $newOrderNum = (int)$arOrder['ORDER_NUM'] + 1;
            $result->modifyFields(['ORDER_NUM' => $newOrderNum]);
        }
    }
    return $result;
}

Те у меня где-то далеко в коде есть функция создания заказа, она вообще в другом классе, внутри которой я вызываю
$res = OrderTable:add([...]);
$orderId = res->getId();

Когда запись в БД вот-вот готова и есть все поля (но без поля номер заказа),
далее срабатывает событие onBeforeAdd, которое берет и ищет в таблице с заказ заказ с последним номером
получает его (номер) и присваивает ему +1 - это получается номер для нового заказа
далее уже идет сохранение в базу.

Код работает и давно, но вот недавно стали появляться заказы с одинаковыми номерами (1-2 раза в месяц), посмотрел, а у них дата создания совпадает до секунды, подозреваю, что событие onBeforeAdd когда делает выборку, то работает с одним набором данных, а когда присваивает, то уже с другим, вроде бы это коллизия называется или нарушение консистентности данных. (те заказы создаются в 1 секунду и для нас получается onBeforeAdd 2 раза работает для каждого заказа и получает одинаковый последний номер, тк работает одновременно)

Помогите найти решение, которое бы не создавало мне одинаковых номеров заказов (не сохраняло в базу строки с одинаковым полем)
Заранее благодарен за помощь!
  • Вопрос задан
  • 363 просмотра
Пригласить эксперта
Ответы на вопрос 2
usdglander
@usdglander
Yipee-ki-yay
ищет в таблице с заказ заказ с последним номером
получает его (номер) и присваивает ему +1 - это получается номер для нового заказа

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

В самом простом случае +1 в иных случаях (оптовый заказ, индивидуальная поставка, дальний склад) номера заказов могут принимать вид AA-02-1122, AA-02-1123, AA-02-1124.

А это вообще никак не относится к делу. Совсем. Этот номер генерируется ПОСЛЕ добавления записии из ппрефиксов и ИД: {ТипЗаказ}{ТипДоставки}-{Номерсклада}-ИД
Можете писать его в отдельное поле, которое можете назвать Номер заказа и радоваться.
Ответ написан
Ваш ответ на вопрос

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

Похожие вопросы