phpjqueryajaxphp-luminovaluminova

How to Make PHP Luminova login work with jQuery Ajax?


I am trying to create a login page in PHP Luminova, but doesn't work well with Ajax requests.

How can i update my login class to work with Ajax and redirect to another page after a successful login or show an error message?

The current example doesn't work.

The problem am facing is when i log in, the Ajax doesn't redirect on successful login nor update the error message to the `loginMessage` element.

Also when I check the browser network request tab, while logging in, when an error is encountered, the message shows in the browser preview while the element I added to show the error only shows `undefined`. Same as when login is successful the dashboard is shown in the preview, but if I reload the page after login, it will take me to the dashboard.

Please, i will appreciate any help, i want to show an error message when an error happens and redirect to the dashboard when successful

My login controller class.

use Luminova\Base\BaseController;
use Luminova\Attributes\Prefix;
use Luminova\Attributes\Route;
use Luminova\Security\Crypter;
use App\Models\User;

#[Prefix(pattern: '/api/(:root)', onError: [ViewErrors::class, 'onApiError'])]
class UserController extends BaseController
{
    #[Route('/api/login', methods: ['POST'])]
    public function userLogin(): int 
    {
        if ($this->request->getBody() === []) {
            echo 'Invalid request body';
            return STATUS_ERROR;
        }elseif($this->app->session->online()){
            echo "You are already logged in";
           return $this->view('dashboard');
        }

        $this->validate->rules = [
            'email' => 'required|email',
            'password' => 'required|min(6)',
        ];

        $this->validate->errors = [
            'email' => [
                'required' => 'Email must not be empty',
                'email' => 'Email address must be a valid email.'
            ],
            'password' => [
                'required' => 'Password must not be empty',
                'min' => 'Password must not be less than 6 characters'
            ],
        ];

        if(!$this->validate->validate($this->request->getBody())){
            echo $this->validate->getError();
            return STATUS_ERROR;
        }else{

            $password = $this->request->getPost("password");
            $email = escape($this->request->getPost("email"));
            $user = (new User())->findByEmail($email);
        
            if(!$user){
                echo 'Not matching email found.';
                return STATUS_ERROR;
            }elseif(Crypter::verify($password, $user->user_password_hash)){
                $this->app->session->set('name', $user->name);
                $this->app->session->set('email', $user->email);
                $this->app->session->set('id', $user->id);
                $this->app->session->synchronize(ip_address());

                return $this->view('dashboard');
            }
        }

        echo 'Invalid email or password provided';
        return STATUS_ERROR;
    }
}

Here is my javascript login.

$('#loginAccountForm').on('submit', function (e) {
    e.preventDefault();
    $.ajax({
        url: '<?php echo href(/api/login);?>',
        type: 'POST',
        contentType: 'application/json',
        data: JSON.stringify({
            username: $('#username').val(),
            password: $('#password').val(),
        }),
        success: function (response) {
            if (response.success) {
                window.location.href = '/dashboard';
            } else {
                $('#loginMessage').html('<p style="color: red;">' + response.message + '</p>');
            }
        }
    });
});

Solution

  • Based on documentation here https://luminova.ng/docs/3.0.2/templates/response as @ADyson suggested. Update your controller login method to output json response following your ajax implementation. Use the response function instead of directly echoing the response.

    Below is an optimized example of how your method should look.

    use Luminova\Base\BaseController;
    use Luminova\Attributes\Prefix;
    use Luminova\Attributes\Route;
    use Luminova\Security\Crypter;
    use App\Models\User;
    
    #[Prefix(pattern: '/api/(:root)', onError: [ViewErrors::class, 'onApiError'])]
    class UserController extends BaseController
    {
        #[Route('/api/login', methods: ['POST'])]
        public function userLogin(): int 
        {
            if ($this->request->getBody() === []) {
                return response()->json(['success' => false, 'message' => 'Invalid request body.']);
            }
    
            if($this->app->session->online()){
                return response()->json(['success' => true, 'message' => 'You are already logged in.']);
            }
    
            $this->validate->rules = [
                'email' => 'required|email',
                'password' => 'required|min(6)',
            ];
    
            $this->validate->errors = [
                'email' => [
                    'required' => 'Email must not be empty',
                    'email' => 'Email address must be a valid email.'
                ],
                'password' => [
                    'required' => 'Password must not be empty',
                    'min' => 'Password must not be less than 6 characters'
                ],
            ];
    
            if(!$this->validate->validate($this->request->getBody())){
                return response()->json(['success' => false, 'message' => $this->validate->getError()]);
            }
    
            $password = $this->request->getPost("password");
            $email = escape($this->request->getPost("email"));
            $user = (new User())->findByEmail($email);
        
            if(!$user){
                return response()->json(['success' => false, 'message' => 'Not matching email found.']);
            }
    
            if(Crypter::verify($password, $user->user_password_hash)){
                $this->app->session->set('name', $user->name);
                $this->app->session->set('email', $user->email);
                $this->app->session->set('id', $user->id);
                $this->app->session->synchronize(ip_address());
    
                return response()->json(['success' => true, 'message' => 'Login successful.']);
            }
    
            return response()->json(['success' => false, 'message' => 'Invalid email or password provided.']);
        }
    }