Laravel route : any slug takes all the requests - laravel

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!

Related

How to redirect excluding some slug in laravel routing?

I would like to exclude the {user} in slug route
I want to make:
from example.com/user/someslugs
to exclude the {user} in slug route example.com/someslugs
// This my Verify Controller
class VerifyController extends Controller{
public function redirect($user, $slug){
// Get verify
$verify = Verify::slug($slug)->first();
// Check if verify exists
if (!$verify) {
abort(404);
}
// Redirect to url
return redirect($verify->url);
}
}
Function
// MyFunc
if (!function_exists('verify')) {
function verify($uri, $user){
$model = new \App\Models\Verify;
if (!validate_url($uri)) {
return false;
}
$createVerify = function($url) use ($model){
$slug = \Str::random(6);
$new = $model;
$new->url = $url;
$new->slug = $slug;
$new->save();
return $slug;
};
$route = function($slug, $user){
return route('verify', ['user' => $user, 'slug' => $slug]);
};
if (!$verify = $model->url($uri)->first()) {
$slug = $createVerify($uri);
return $route($slug, $user);
}
return $route($verify->slug, $user);
}
}
Route web.php
// MyRouteVerify
Route::get('{user}/{slug}', 'VerifyController#redirect')->name('verify');
The main problem when I remove {user} from route and wrong controller is called.
How can I achieve this? to get the full URL exclude the {user}, (example.com/someslugs)?
Any suggestion? And I would really appreciate some good and relative answer. Thanks!
in case you guarantee that your slug will never match your route, you can put your user route at the end of the web.php file
Example
// route list here
Route::get('/someroute', 'SomeController#somemethod');
// the last route in your web.php file
Route::get('/{slug}', 'VerifyController#redirect')->name('verify');
I hope it's useful

Auth::user() Returns Null in API Controller

I'm using Laravel 7 and my problem is to get null from Auth::user();
auth()->user and Auth::id() return null as well.
BTW, in balde template Auth::user() works.
It returns null when I try to use it in controller.
What I'm trying to do is to create a comment page in backend (Vuejs) and I want to build up a filter logic. In order to do that, I want to add a new property named repliedBy into each comment in controller. If a comment isn't replied by the current user, repliedBy will be notByMe. So I don't event try to return user id to Vuejs. I can't get id even in the controller. BTW, login, registration etc work normal way.
Here is my CommentsController:
public function index()
{
$comments = Comment::join("site_languages", "language_id", "=", "site_languages.id")
->select("content_comments.*", "site_languages.shorthand as lang_shorthand")
->with(["replies", "post", "user"])
->orderBy('id', 'desc')
->get()
->groupBy("commentable_type");
$grouppedComments = [];
foreach ($comments as $type => $typeSet) {
$newType = strtolower(explode("\\", $type)[1]);
$grouppedByLanguage = $typeSet->groupBy("lang_shorthand");
$langSet = [];
foreach ($grouppedByLanguage as $lang => $commentSet) {
$grouppedBycontent = [];
foreach ($commentSet as $comments) {
$content = $newType . "_" . $comments->commentable_id;
if (array_key_exists($content, $grouppedBycontent)) {
array_push($grouppedBycontent[$content], $comments);
} else {
$grouppedBycontent[$content] = [$comments];
}
}
$groupAfterOrganized = [];
foreach ($grouppedBycontent as $content => $comments) {
$order = 1;
$commentAndReplies = [];
foreach ($comments as $comment) {
if ($comment->parent_id === null) {
if (isset($comment->order) === false || $comment->order > $order) {
$comment->order = $order;
}
array_push($commentAndReplies, $comment);
} else {
foreach ($comments as $parentComment) {
if ($parentComment->id === $comment->parent_id) {
$parent = $parentComment;
break;
}
}
foreach ($parent->replies as $replyInParent) {
if ($replyInParent->id === $comment->id) {
$reply = $replyInParent;
break;
}
}
if (isset($comment->order) === false) {
$comment->order = $order;
$order++;
}
if (isset($parent->order) === false || $parent->order > $comment->order) {
$parent->order = $comment->order;
}
$reply->order = $comment->order;
$reply->replies = $comment->replies;
$reply[$newType] = $comment[$newType];
$basePower = 6;
if ($comment->user_id !== null) {
if ($comment->user_id === Auth::id()) {
$reply->replyFrom = "me";
} else if ($comment->user->role->power >= $basePower) {
$reply->replyFrom = "staff";
} else {
$reply->replyFrom = "user";
}
} else {
$reply->replyFrom = "visitor";
}
$iReplied = false;
$staffReplied = false;
foreach ($reply->replies as $replyOfReply) {
if ($replyOfReply->user_id !== null) {
$power = $replyOfReply->user->role->power;
if ($power >= $basePower) {
$staffReplied = true;
}
}
if ($replyOfReply->user_id === Auth::id()) {
$iReplied = true;
}
}
if ($staffReplied === false) {
if ($reply->replyFrom === "user" && $reply->replyFrom === "visitor") {
$reply->replied = "notReplied";
} else {
$reply->replied = "lastWords";
}
} else if ($staffReplied && $iReplied === false) {
$reply->replied = "notByMe";
} else if ($staffReplied) {
$reply->replied = "replied";
}
}
}
$groupAfterOrganized[$content] = $commentAndReplies;
}
$langSet[$lang] = $groupAfterOrganized;
}
$grouppedComments[$newType] = $langSet;
}
return $grouppedComments;
}
api.php
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
Route::apiResources([
'languages' => 'API\LanguagesController',
'users' => 'API\UsersController',
'roles' => 'API\RolesController',
'tags' => 'API\TagsController',
'categories' => 'API\CategoryController',
'pictures' => 'API\PicturesController',
'posts' => 'API\PostsController',
'comments' => 'API\CommentsController'
]);
EDIT
I'm using the code down below in RedirectIfAuthenticated.php and when I try with
dd(Auth::user());
it returns null as well. BTW obviosly, redirect to backend doesn't work.
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
if (Auth::user()->role->power > 5) {
return redirect('backend');
}
return redirect(RouteServiceProvider::HOME);
}
return $next($request);
}
The solution to this problem is fairly simple . because you are using api request laravel default auth can not understand the user so here the passport comes :
https://laravel.com/docs/7.x/passport
as written in documenation you should go 3 steps :
composer require laravel/passport
php artisan migrate
php artisan passport:install
after that you can generate token for logged in users and use that token in api authentication to use for your api which is the only and more reliable way that laravel default auth .
this link can be helpful to you too :
https://laravel.io/forum/laravel-passport-vue-check-user-authentication
this way if you intent to use you api in mobile or any other application you can simply authenticate your user in that :)
hope this helps
EDIT
according To your comment now you must generate token for your vue api to use so this would be like below :
$token = $user->createToken(config('app.name'))->accessToken;
if ($this->isApiType()) {
$token = $user->createToken(config('app.name'))->accessToken;
} else {
Auth::login($user);
$redirect = $this->getRedirectTo($user);
}
this must be added in the end of your login method so if the request comes from api it generates a JWT token for you which can be used in vue for login
yes for getting the authencated user detail your API must under the auth:API middleware.
Route::group(['middleware' => 'auth:api'], function () {
}
As you are using Resource those are not under the Api middleware just put that into that and Auth::user will return the result set.
Route::group(['middleware' => 'auth:api'], function () {
Route::apiResources([
'comments' => 'API\CommentsController'
]);
}
will fix the issue.

how to pass session variable into view using laravel4

I want to pass logged in id into my view page.i got the id in the function of user_login_submits.
Actually i want to get the id in one more function in the same controller.
how to get the session id in controller..
Normally session put its enough i did like that.
Here is my code anyone can check and tel me what need to change here
Controller
public function user_login_submits()
{
$inputs = Input::all();
$uname = Input::get('username');
$password = Input::get('password');
$logincheck=Userlogin::login_checks($uname,$password);
if($logincheck == 1)
{
$id=Session::get('customer_id');
return Redirect::to('businessprio/create_news?p=1');
}
else if($logincheck == 0)
{
//echo "fail";
return Redirect::to('businessprio/create');
}
}
Model
public static function login_checks($uname,$password)
{
$check = DB::table('customer_login')
->where('username','=',$uname)
->where('password','=',$password)->get();
if($check)
{
//Session::put(['customer_id'=>'value']);
Session::put('customer_id', $check[0]->customer_id);
Session::put('username', $check[0]->username);
return 1;
}
else
{
return 0;
}
}
I won't pass it to model, instead i would do it in controller itself,
public function user_login_submits()
{
$uname = Input::get('username');
$password = Input::get('password');
$check = DB::table('customer_login')
->where('username','=',$uname)
->where('password','=',$password)->count();
if($check==1)
{
$id=Session::get('customer_id');
return Redirect::to('businessprio/create_news?p=1');
}
else
{
return Redirect::to('businessprio/create');
}
}
Recommendation :
But i would strongly recommend you to do it by Auth::attempt i.e., to follow the clean one
public function user_login_submits()
{
if (Auth::attempt(['email' => $userEmail, 'password' => $userPassword])) {
return Redirect::to('businessprio/create_news?p=1');
}
else
{
return Redirect::to('businessprio/create');
}
}
If you do so, then you can access the Default checking for authenticated user
Auth::check()
Get the Logged in user details by
Auth::user()->id
Auth::user()->username
Note : To use default Auth::attempt you should use the User Model too.

Laravel 5 redirect to previous root after filters

I ran into simple problem but I still can't solve it. At the moment i got middleware which checks user status, if it's 0 middleware redirects user to choose status root. So how do i redirect user to route, after successfully picking status, where he got cought by middleware?
My status check middleware:
if (Auth::user()->status == '0') {
return new RedirectResponse(url('/user/user-status'));
}
return $next($request);
I'm using laravel 5.
Thanks in advance!
Lets look into the option of using Redirect::intended() and Redirect::guest()
The code behind Redirect::intended() is:
public function intended($default, $status = 302, $headers = array(), $secure = null)
{
$path = $this->session->get('url.intended', $default);
$this->session->forget('url.intended');
return $this->to($path, $status, $headers, $secure);
}
The one for Redirect::guest() is :
public function guest($path, $status = 302, $headers = array(), $secure = null)
{
$this->session->put('url.intended', $this->generator->full());
return $this->to($path, $status, $headers, $secure);
}
So basically, this means you can do this:
if (!Auth::user()->status) {
return redirect()->guest('/user/user-status');
}
return $next($request);
Then once the process of setting status is completed, you simply run:
return redirect()->intended();
You have to use the redirect provider. Into this function, Laravel memories the intended path.
if (Auth::user()->status == '0') {
{
\Session::flash('flash_message','Please choose a status.');
return redirect()->guest('/user/user-status');
}
return $next($request);
You can try this:
if (Auth::user()->status == '0') {
return redirect()->guest('/user/user-status');
}
return $next($request);
According to code documentation, redirect()->guest() does this: "Create a new redirect response, while putting the current URL in the session.". Then, in your "user status" page, you can get your intended URL in session with Session::get('url.intended') or return redirect()->intended('default-route-if-not-set');

laravel auth and session not persisting

The laravel session and auth I use have some problem in server, but working really fine in localhost . I will show.
Route
Route::get('/signin', 'PageController#signin');
Route::get('/signup', 'PageController#signup');
Route::get('/terms', 'PageController#terms');
Route::resource('/', 'PageController');
Route::controller('user', 'UserController');
PageController
public function index() {
if (Auth::check()) {
return View::make('user.index');
} else {
return View::make('landing');
}
}
UserController
public function postLogin() {
$data = array();
$secured = ['user_email' => $_POST['email'], 'password' => $_POST['password']];
if (Auth::attempt($secured, isset($_POST['remember']))) {
if (Auth::user()->user_status == 1 ) {
return Redirect::to('/');
} else {
$data['success'] = false;
}
} else {
$data['success'] = false;
}
return $data;
}
Auth::check() fails in pagecontoller even after login succeds. But if I change the code to
UserController
public function postLogin() {
$data = array();
$secured = ['user_email' => $_POST['email'], 'password' => $_POST['password']];
if (Auth::attempt($secured, isset($_POST['remember']))) {
if (Auth::user()->user_status == 1 ) {
return Return View::make(user.index);
} else {
$data['success'] = false;
}
} else {
$data['success'] = false;
}
return $data;
}
I get the index page and if I click the link of the home I get the landing page not the index page.
I guess I clarify my problem, I have gone through may solution replied earlier in same manner question nothing working.
I don't think its the server problem because another laravel application is working fine in same server.
Please help.
Your query seems to be incomplete, from what i understand you are able to get the index page after passing the authentication check only once, and that is by using this method:
public function postLogin() {
$data = array();
$secured = ['user_email' => $_POST['email'], 'password' => $_POST['password']];
if (Auth::attempt($secured, isset($_POST['remember']))) {
if (Auth::user()->user_status == 1 ) {
return Return View::make(user.index);
}
else {
$data['success'] = false;
}
}
else {
$data['success'] = false;
}
return $data;
}
try using a different browser to make sure there is no cookie storage restrictions in the client side and check the app/config/session.php file and see if you have configured the HTTPS Only Cookies according to your needs.
and just on an additional note this line "return Return View::make(user.index);" looks vague.

Resources