sails.js Используйте сессионный параметр в модели

Это продолжение этого вопроса.

В моих моделях для каждой требуется, чтобы при создании был задан companyId, а для каждой модели требуется фильтрация по одному и тому же сеансу, проведенному companyid.

С sails.js я прочитал и понял, что сеанс недоступен в модели, если я не внедряю его с помощью контроллера, однако это потребует от меня кодирования всех моих контроллеров / действий с чем-то очень, очень повторяющимся. Несчастная.

Мне нравится sails.js, и я хочу сделать это, но кто-нибудь может описать мне лучший способ? Я надеюсь, что только что что-то пропустил.

3 ответа

Решение

Итак, если я вас правильно понимаю, вы хотите избежать большого количества кода, подобного этому, в ваших контроллерах:

SomeModel.create({companyId: req.session.companyId, ...})
SomeModel.find({companyId: req.session.companyId, ...})

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

SomeModel.doCreate(req, ...);
SomeModel.doFind(req, ...);

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

Если вы работаете с неузловым фоном, это может вызвать царапины на голове. "Почему вы не можете просто сделать сеанс доступным везде?" Вы можете спросить. "Как они делают в PHP!"

Причина в том, что PHP не имеет состояния - каждый входящий запрос получает, по сути, свежую копию приложения, при этом в памяти ничего не распределяется между запросами. Это означает, что любые глобальные переменные будут действительны только в течение одного запроса. Это замечательно $_SESSION хэш принадлежит вам и только вам, и после обработки запроса он исчезает.

Сравните это с приложениями Node, которые по сути работают в одном процессе. Любые глобальные переменные, которые вы устанавливаете, будут совместно использоваться каждым входящим запросом, и, поскольку запросы обрабатываются асинхронно, нет гарантии, что один запрос завершится до того, как начнется другой. Таким образом, такой сценарий может легко произойти:

  1. Запрос А приходит.
  2. Sails получает сеанс для запроса A и сохраняет его в глобальном $_SESSION объект.
  3. Запрос звонков SomeModel.find(), который обращается к базе данных асинхронно
  4. В то время как база данных делает свое волшебство, Запрос A отказывается от своего контроля над потоком Узла
  5. Запрос B приходит.
  6. Sails получает сеанс для запроса B и сохраняет его в глобальном $_SESSION объект.
  7. Запрос B сдает контроль над потоком для выполнения другого асинхронного вызова.
  8. Запрос A возвращается с результатом своего вызова базы данных и читает что-то из $_SESSION объект.

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

Я предпочитаю делать политику, которая добавляет companyId внутри body.param, вот так:

    // Needs to be Logged
    module.exports = function(req, res, next) {
        sails.log.verbose('[Policy.insertCompanyId() called] ' + __filename);

        if (req.session) {
            req.body.user = req.session.companyId; 
                 //or something like AuthService.getCompanyId(req.session);
            return next();
        }

        var err = 'Missing companyId'; 
        //log ...
        return res.redirect(307, '/');
    };

Лучший вариант, который я могу придумать, - воспользоваться JS и создать некоторые глобально доступные функции.

Но у него будет запах кода:(

Другие вопросы по тегам