Когда следует очищать переменную сеанса? - PullRequest
1 голос
/ 27 марта 2011

Спецификация для моего приложения гласит, что два пользователя должны иметь возможность работать с одной и той же записью веб-приложения одновременно, не забивая друг друга данными (если, конечно, каждый из них не изменяет одно и то же поле, это будет последний спасает победы.) Это медицинская система, и вполне возможно, что люди, занимающиеся выставлением счетов, могут работать над записью, пока технический специалист обновляет другой раздел записи.

Таким образом, когда пользователь сохраняет форму, система должна изменять только те значения в базе данных, которые пользователь фактически изменил. Поскольку я использую CakePHP, я пытаюсь разобраться с этим на стороне PHP, а не делаю это с JavaScript перед отправкой данных формы.

Моей первой мыслью было проверить значения в базе данных непосредственно перед сохранением и изменить только те значения, которые не совпадают. Но если пользователь A сохраняет форму после того, как ее открыл пользователь B, а затем пользователь B сохраняет форму, то изменения пользователя A будут заменены старыми данными в форме пользователя B.

Моей следующей мыслью было сохранение значений формы в сеансе пользователя. Таким образом, когда он открывает форму, данные сохраняются в сеансе, и только значения, которые изменились по сравнению с тем, что было в его сеансе, будут обновлены в базе данных. Таким образом, сессия сериализовала бы в нее $ old_data.

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

И это подводит меня к последней проблеме. Я могу сбросить данные из сеанса, когда пользователь сохранит форму (и затем сразу же восстановить ее, если они снова отобразят ту же запись). Но это не относится к ситуации, когда пользователь не сохраняет форму. Если они откроют форму и прочитают ее, а затем уйдут, постепенно их сессия будет полна мусора.

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

Ответы [ 4 ]

1 голос
/ 29 марта 2011

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

Полученный компонент SaveDiff не использовался в производстве, поэтому потребуется некоторое тестирование. (Не стесняйтесь вносить изменения в GitHub, если вы обнаружите какие-либо ошибки.)

<?php
class ModelsController extends AppController {

    public $components = array(
        'SaveDiff' => array( # include the component
            'actions' => array('edit'), # tell it which actions to work with
        ),
    );

    public function edit($id) {
        $record = $this->read(null, $id)
        # not found
        if (!$record) {
            $this->cakeError('error404');
        }
        # populate form
        if (!$this->data) {
            $this->data = $record;
            return;
        }
        # save form
        $saved = $this->Model->save($this->data);
        if (!$saved) {
            $this->Session->setFlash('Failed validation');
            return;
        }
        # success
        $this->Session->setFlash('Saved changed fields');
        $this->redirect(array('action' => 'index'));
    }
}

Во время действия контроллера (ModelsController::edit() в приведенном выше примере) заполните форму, используя $this->data. Компонент сработает после рендеринга действия контроллера и сохранит $this->data в сеансе. Ну, если проверка не удалась, потому что мы, вероятно, имеем дело с данными, предоставленными пользователями на этом этапе.

Когда новые запросы поступают в компонент, он снова запускается перед действием контроллера и очищает любые неизмененные данные из $this->data (сравнивая их с сеансом), что означает, что он должен соответствовать вашим требованиям (только измененные поля) и является готов сохранить.

Примечание: я заметил, что мой SaveDiffComponent::extractChanges() метод работает не совсем правильно, но я оставлю это для вас. Обязательно используйте DebugKit при тестировании (вкладки «Сессия» и «Переменные») и помните, что вам нужно дважды обновить данные нового сеанса (потому что PHP не может читать новые данные сеанса до следующего запроса ... или что-то в этом роде).

0 голосов
/ 27 марта 2011

Спасибо за описание вашего мыслительного процесса.

Моей следующей мыслью было сохранение значений формы в сеансе пользователя. Так, когда он открывает форму, данные получают хранится в сеансе, и только значения, которые изменились с того, что было в своей сессии будет обновляться в база данных. Итак, сессия будет иметь в нем сериализовано $ old_data.

Я думаю, что это лучший способ сделать это.

И это приводит меня к финалу проблема. Я могу сбросить данные из сеанс, когда пользователь сохраняет форму (а затем повторно получить его немедленно, если они воспроизводят ту же запись снова). Но это не касается ситуация, когда пользователь не сохраняет форма. Если они открывают форму и прочитайте это и затем уходите, постепенно их сессия будет полна мусор.

Имейте в виду, что сессия в конце концов истечет. В это время старые данные сеанса будут удалены. Если это слишком долго для вас, вы можете добавить дату и время к данным сеанса, а когда страница загружена, пройтись по данным сеанса, чтобы удалить устаревшую информацию.

Частота этой уборки зависит от вас. Я бы установил для него любое значение, которое вы считаете максимальным количеством времени, которое потребуется человеку для работы над конкретной формой + 1 минута.

Надеюсь, это поможет!

0 голосов
/ 27 марта 2011

Я не уверен насчет дизайна вашей системы, но, как вы упомянули, что это медицинская система, есть ли какой-нибудь идентификатор ревизии в форме? Если это так, то у вас может быть скрытое поле, которое отслеживает начальную точку для обоих пользователей, но вы все равно можете сравнить с тем, что изменилось, не тратя так много времени на объект сеанса.

0 голосов
/ 27 марта 2011

Вы можете поместить каждый элемент в данные сеанса, причем каждая запись является собственным массивом.aka $_SESSION["client1"] будет информацией для первого клиента, тогда как $_SESSION["client2"] будет информацией для второго клиента.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...