We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Storing a model instance as a service during the session

I want to access to profile of the current user across the application (read/write). The user profile is an in instance of User model. Is it possible to store it on session as a service? If not, what is best practice? Here is my login code. (ajax-based login)

        function loginAction()
            {
                $this->view->disable();
                {
                    $request = (array)$this->request->getJsonRawBody();
                    $user = User::findFirstByUsername($request['username']);

                    if (password_verify($request['password'], $user->password)) {
                        $userModel = User::findFirst('username="'.$request['username'].'"');
                        $this->getDI()['session']->set('auth', $user->id);
                        $this->user = $user;
                        jsonResponse($user->username);
                    } else {
                        http_response_code(401);
                        jsonResponse(['message' => 'invalid']);
                    }
                }
            }


58.4k

Hey man

You just to set seesion after user login, then you can call anywhere here exmpale in my project

    try {
            if ($this->request->isPost()) {
                if (!$form->isValid($this->request->getPost())) {
                    foreach ($form->getMessages() as $message) {
                        $this->flashSession->error($message->getMessage());
                    }
                } else {
                    $object = User::findByEmailOrUsername($this->request->getPost('email'));
                    if ($object && $object->getStatus() == $object::STATUS_ACTIVE) {
                        if (!$this->security->checkHash($this->request->getPost('password'), $object->getPasswd())) {
                            $this->flashSession->error(t('Wrong email/password combination!'));
                        } else {
                            // @TODO : try to make just one query with innerjoin.
                            $role         = $object->getRole();
                            $auth         = $object->toArray();
                            $auth['role'] = $role->toArray();
                            $auth['avatar'] = $object->getAvatar();

                            $this->session->set('auth', $auth);
                            $object->setLastLogin(date('Y-m-d H:i:s'));
                            $object->save();

                            if (!$this->request->getHttpReferer()) {
                                $this->response->redirect();
                            } else {
                                $this->response->redirect($this->request->getHttpReferer());
                            }

                        }
                    } elseif ($object && $object->getStatus() != User::STATUS_ACTIVE) {
                        $this->flashSession->error(
                            t('User status is: ') . $object->getStatusesWithLabels()[$object->getStatus()]
                        );
                    } else {
                        $this->flashSession->error(t('User doesn\'t exist !'));
                    }
                }
            }
        } catch (\Exception $e) {
            $this->flashSession->error($e->getMessage());
        }


22.1k
edited Nov '14

@Thein

Thanks, but I need the user profile as an instanse of Model not as an array. I also tried

                 $this->getDI()->setShared('user',$userModel);

but this does not keep the user's data.



22.1k
edited Nov '14

I also tried the following code, without success:

   $this->getDI()->setShared('user', function () {
                  return User::findFirst($this->session->auth);
                  });
 $this->getDI()->setShared('user', function () {
                return User::findFirst($this->session->auth);
                });

The trouble with that is $this resolution. Inside your function, $this doesn't refer to anything. Try adding a use clause:

$auth_token = $this->session->auth;
$this->getDI()->setShared('user', function () use($auth_token) {
    return User::findFirst($auth_token);
});

_I feel like one should be able to do this: use($this->session->auth as $auth_token), but I've not been able to find any documentation around it - so I may just be inventing stuff in my head._



22.1k
edited Dec '14

@quasipickle

Thanks, however this does not work for me.$this->di["user"] returns a new user (all fields are empty.)

setShared() is supposed to work https://docs.phalcon.io/en/latest/reference/di.html#shared-services

Are you sure $this->di["user"] returns a brand new User object every time? Perhaps the User object is being initialized as an empty object, then that empty object is being returned every time.

Try putting this in the closure:

echo $auth_token;
exit();

And maybe output some values from the expected object before exit()ing - just to make sure the object being retrieved is what you expect.



22.1k
Accepted
answer
edited Dec '14

@quasipickle

Ah, I had placed the code in the login action. I put the following code in services.php and now it works like a charm.

       $di->setShared('user', function () use ($di) {
      if (isset($di['session']['auth']))
          return User::findFirst($di['session']->auth);
      else
          return false;
  })


43.9k

Hi all,

nice and elegant solution. Thanks !