Trying to get property of non-object Laravel Auth - laravel

EDIT : I am testing it now, so weird that sometimes it works and sometimes it gives me that error.
I have an application, I've override the logout function in Laravel so I have this in my AuthController.php
public function getLogout()
{
$userid = Auth::user()->id;
date_default_timezone_set('Asia/Taipei');
$today = date('Y-m-d');
$logHour = new LoginHour();
$checkLogin = $logHour->checkLoginHoursOut(intval($userid), $today);
if($checkLogin != null)
{
$loginhours = '';
$timestamp = date('Y-m-d h:i:s');
$timestamp2 = strtotime($timestamp);
$userLastLogin = $checkLogin[0]->timestamp;
$userLastLogin2 = strtotime($userLastLogin);
// Get difference in hours
$diffHours = round(($timestamp2 - $userLastLogin2) / 3600, 2);
LoginHour::where('date', '=', $today)->
where('user_id', '=', $userid)->
update(['loginhours' => $checkLogin[0]->loginhours + $diffHours, 'status' => 0, 'timestamp' => $timestamp]);
}
Auth::logout();
return redirect(property_exists($this, 'redirectAfterLogout') ? $this->redirectAfterLogout : '/auth/login');
}
But for some reason when I am trying to logout I have this error:
Trying to get property of non-object
Which points me to this line
$userid = Auth::user()->id;
What could be the problem? I believe I could still access the Auth coz I'm not yet calling the Auth::logout(); before that line?

I guess that the problem exists when you visit the logout route, without a logged in user.
So, you should check it at the top.
public function getLogout()
{
if (Auth::guest()) return;
...
}

Related

How with jenssegers/mongodb get last Insert Id?

On Laravel site using jenssegers/mongodb I have store method like :
public function store(ItemRequest $request)
{
$request = request();
try {
$session = DB::getMongoClient()->startSession();
$session->startTransaction();
$insertData = $request->all();
$insertData['published'] = ! empty($insertData['published']);
$item = Item::create([
'title' => $insertData['title'],
'text' => $insertData['text'],
'published' => $insertData['published'],
]);
$session->commitTransaction();
} catch (Exception $e) {
$session->abortTransaction();
return back()->withErrors(['message' => $e->getMessage()]);
}
return redirect(route('admin.items.edit', $item->_id))
->with('message', 'New item was successfully added')
->with('message_type', 'success');
}
But making test for this controller method I did not find how to get ID on new ite, generated on mongodb site :
public function testIsItemEditFormSubmittedWithSuccess()
{
$this->withoutMiddleware();
$item = \App\Models\Item::factory(Item::class)->make();
// Test Action
$response = $this->actingAs(self::$loggedAdmin, 'web')->post(route('admin.items.store'), $item->toArray());
$newItemId = DB::getPdo()->lastInsertId();
// If to uncomment line above I got "Error: Call to a member function lastInsertId() on null"
$response->assertStatus(302); // Redirection status
$response->assertRedirect(route('admin.items.edit', [???])); // HOW can New ID on "store" method above ?
$response->assertSessionHasNoErrors();
}
Any equvalent of lastInsertId for jenssegers/mongodb ?
"jenssegers/mongodb": "^3.9.2",
"laravel/framework": "^9.30.1",
Thanks in advance!
Check this issue.
https://github.com/jenssegers/laravel-mongodb/issues/2451
Your laravel should be 9.31. So downgrade it to 9.30 and wait next release.

error when try to open route without parameter in Laravel 9

I have a problem when trying to access any route without parameter:
When I wrte any route without {uname} parameter like this or any other one:
http://127.0.0.1:8000/login/
show me this error :
and it is in the home in another controller?
These is my routes:
Route::get('/{uname?}', [HomeController::class, 'home'])->name('home');
Route::get('/info/{uname?}', [HomeController::class, 'info'])->name('info.me');
Route::get('/skills/{uname?}', [HomeController::class, 'skills'])->name('skills');
Route::get('/education/{uname?}', [HomeController::class, 'education'])->name('education');
Route::get('/achievements/{uname?}', [HomeController::class, 'achievements'])->name('achievements');
Route::get('/services/{uname?}', [HomeController::class, 'services'])->name('services');
Route::get('/contact/{uname?}', [HomeController::class, 'contact'])->name('contact');
Route::post('/send-email', [HomeController::class, 'sendEmail'])->name('send-email');
Route::get('/dashboard/index', [DashboardController::class, 'index'])->name('dashboard.index');
Route::resource('/dashboard/about', AboutController::class);
Route::resource('/dashboard/skills', SkillsController::class);
Route::resource('/dashboard/education', EducationController::class);
and here is my HomeController:
class HomeController extends Controller
{
function home($uname) {
$user = User::where('name', '=', $uname)->first();
$about = $user->about;
return view('home', compact('user', 'about'));
}
function info($uname) {
$user = User::where('name', '=', $uname)->first();
$about = $user->about;
return view('info', compact(['user', 'about']));
}
function skills($uname) {
$user = User::where('name', '=', $uname)->first();
$about = $user->about;
$skills = $user->skills;
return view('skills', compact(['skills', 'user', 'about']));
}
I have already tried those and nothing changed:
PHP artisan route: cache
PHP artisan cache:clear
Your home route is a catch-all route as you have an optional parameter right after your first dash (/). This will always catch first and stop any other routes from running because it will always match your current url. To solve this you need to put this kind of route as your last route.
As for your error it's because your not finding any user. If ->first() doesn't find a matching row it will return null, and if it's null you will get an error if you're treating it as an object. You either need to check if $user is null and set $about based on that or use firstOrFail and then create a response for that error.
Your error on line 13 of HomeController...
can't find user with your condition and return null and you in line 14 want get about from null....
you have to choose :
1 :
function home($uname) {
$user = User::where('name', '=', $uname)->first();
$about = $user->about ?? null ;
return view('home', compact('user', 'about'));
}
2:
function home($uname) {
$user=$about=null;
if(isset($uname)){
$user = User::where('name', '=', $uname)->first();
$about = $user->about ?? null ;
}
return view('home', compact('user', 'about'));
}
also you can change first() to firstOrFaill() in first method to get 404 page
$uname is an optional parameter. When it's not available no user could be found. You should check if $user is not null and return an error page or something like that, when $user is null.
if ($user !== null) {
$about = $user->about;
return view('home', compact('user', 'about'));
} else {
return view('error');
}

Laravel localization problem: the current language doesn't change

when I want to change the current language for user I'm using:
App::setLocale($requestData['language']);
but when I'm trying to get current language in other functions it always returns the default language and it doesn't change, I'm using to get it:
$lang = App::currentLocale();
where is the problem? did I miss something?
edit: the full code
public function update_profile(Request $request)
{
$user = auth()->user()->details;
$requestData = $request->all();
$details = UserDetail::where('id', $user->id)->update($requestData);
$profile_progress = ListHelper::profile_progress();
App::setLocale($requestData['language']);
return response()->json([
'message' => trans('messages.updated_successfully')
]);
}
and the other function:
public function onboarding()
{
$locale= App::currentLocale();
return $locale;
}

How to pass whole url as params?

I want allow user to scan QR code and go to website. This is search results with params in url address like
http://example.com/qr-code/http://example.org/search/user_id=12&model_id=4&role_id=8
My route is set as
Route::get('qr-code/{data?}/{size?}', 'QrController#qrCode')->name('qr-code');
so i hope my $data will get url:
http://example.org/search/user_id=12&model_id=4&role_id=8
My Controller has
public function qrCode(Request $request, $data = null, $size = 60) {
dd(88);
$data = (empty($data)) ? env('APP_URL') : $data;
return view('qr.code')->with('qr', QrCode::size($size)->generate($data));
}
But i can't even see dd(88) route redirect to main page.
How can i fix that ?
The thing is that Laravel doesn't know that you will provide an entire URL as a parameter. He could interpret everything like that:
http://example.com/qr-code/http:/ /search/user_id=12&model_id=4&role_id=8 . Try encoding the URL diffrently. Your $data will be "http:/" and your size will be 60.
Ok i took i added to helper
function base64url_encode($s) {
return str_replace(array('+', '/'), array('-', '_'), base64_encode($s));
}
function base64url_decode($s) {
return base64_decode(str_replace(array('-', '_'), array('+', '/'), $s));
}
And then i am getting URI from request on view like
Click me
From JS i send params to QrController
public function qrCode(Request $request, $data = null, $type = null, $size = 200) {
$data = (empty($data)) ? env('APP_URL') : $data;
if ($type == 'url') $data = env('APP_URL') . base64url_decode($data);
return view('qr.code')->with('qr', QrCode::size($size)->generate($data));
}
And works fine. Base64 has + or / sometimes so thats why need to replace both - and _ and second is i add base url from env to make whole address.
Thx

Laravel route : any slug takes all the requests

I have a route something like this. The $slug is a variable that is matched to the slugs stored in the database to add the pages dynamically to the website.
#slug variable for different values of page slug....
Route::get('/{slug?}', array(
'as' => 'page',
'uses' => 'AbcController#renderPage'
));
However, now I wish to add an admin side of the website and want routes to be prefixed with media-manager.
My problem is, whenever I make a call to another route in the file, the above mentioned route takes the request call and calls the renderPage method every time, no matter wherever the request is coming from.
This is my middleware where I check for whether request is coming from a URL like 'media-manager/*', if so I don't want to check for the language of the website and redirect it to the media-manager's page.
private $openRoute = ['media-manager/login', 'media-manager/postLogin', 'media-manager/media'];
public function handle($request, Closure $next)
{
foreach ($this->openRoute as $route) {
if ($request->is($route)) {
return $next($request);
}
}
// Make sure current locale exists.
$lang = $request->segment(1);
if(!isValidLang($lang)) {
$lang = getDefaultLang();
$segments = $request->segments();
array_unshift($segments, $lang);
$newUrl = implode('/', $segments);
if (array_key_exists('QUERY_STRING', $_SERVER))
$newUrl .= '?'.$_SERVER['QUERY_STRING'];
return $this->redirector->to($newUrl);
}
setLang($lang);
return $next($request);
}
This is the renderPage method where every time the request is being redirected, no matter what.
public function renderPage($slug = '')
{
if ($slug == 'login') {
return view ('site.login');
}
$page = Page::getBySlug($slug);
if(empty($page)){
return URL::to ('/');
}
if($slug == ''){//home page
$testimonial = DB::table('testimonial')->where('lang','=',$this->lang)->get();
$client_logo = DB::table('client_logo')->get();
return View::make('index', compact('data','page', 'testimonial', 'client_logo'));
}elseif($slug == 'services'){
return View::make('services', compact('page'));
}elseif($slug == 'portfolio'){
$categories = PortfolioCategory::getAll();
$portfolio = Portfolio::getAll();
return View::make('portfolio', compact('page', 'categories', 'portfolio'));
}elseif($slug == 'oshara'){
return View::make('oshara', compact('page'));
}elseif($slug == 'blog'){
$limit = 8;
$pageNum = 1;
$offset = ($pageNum-1)*$limit;
$totalPosts = BlogPost::totalPosts();
$totalPages = ceil($totalPosts/$limit);
$posts = BlogPost::getAll($offset, $limit);
$blog_posts = View::make('partials.blog_posts', compact('posts','pageNum','totalPages'));
return View::make('blog', compact('page', 'blog_posts', 'pageNum', 'totalPages'));
}elseif($slug == 'contact'){
$budgets = Budget::getAll();
return View::make('contact', compact('page', 'budgets'));
}
}
This is postLogin method in the controller that I want to call after user clicks on Login button on login page.
public function postLogin($request) {
# code...
//$request = $this->request;
$this->validate($request, [
'email1' => 'required|email',
'password' => 'required|string'
]);
if($user = User::whereEmail($request->email1)->first() ) {
if(Hash::check($request['password'], $user->getAttributes()['password'])) {
if(!$user->getAttributes()['is_active']) {
return redirect('/media-manager/login')->withErrors('Your Account is not Activated Yet!');
} else if($user->getAttributes()['is_deleted']) {
return redirect('/media-manager/login')->withErrors('Your Account is Banned!');
} else {
# Success
$cookie = Cookie::make('user_id', $user->getAttributes()['id'], 864000);
//echo "hello";
return view('site.media')->with('message', 'You have Successfully Logged In!')->withCookie($cookie);
}
} else {
return redirect('/media-manager/login')->withErrors('Your Login Information is Wrong!');
}
} else {
return redirect('/media-manager/login')->withErrors('Your Login Information is Wrong!');
}
}
Can any one please suggest me some way so that I can disable renderPage method on every call and have my normal routing perform perfectly.
In Laravel the first matching route is used. So I would guess you have your slug route defined above the others (at least above the media-manager ones), right?
So a simple solution would be to just put the slug route definition at the end of your routing file.
Another approach would be utilize conditions for the route. For more information you can read this or leave a comment!
Hope that helps!

Resources