How to call controller action in Laravel and run validation request - php

I have a groups table in my database and each group has a slug. I have the following routes defined last in my routes.php file so that if no other URL is matched the app checks whether the slug belongs to a group and shows the group page instead. There is also a form on the group page so the submission of this form needs to be handled as well.
Route::get('{slug}', ['as' => 'dynamic_route', function($slug){
$group = \App\Group::where('slug', $slug)->first();
if(!is_null($group)) {
$app = app();
$controller = $app->make('App\Http\Controllers\GroupsController');
return $controller->callAction('view', ['slug' => $group->slug]);
} else {
abort(404);
}
}]);
Route::post('{slug}', ['as' => 'dynamic_route_submit', function($slug){
$group = \App\Group::where('slug', $slug)->first();
if(!is_null($group)) {
$app = app();
$controller = $app->make('App\Http\Controllers\GroupsController');
return $controller->callAction('handle_register', [$group->slug]);
} else {
abort(404);
}
}]);
Here is my groups controller:
<?php namespace App\Http\Controllers;
use View;
use App\Group;
use App\Lifestyle_question;
use App\Http\Requests\User\RegisterStep1Request;
use App\Http\Requests\User\RegisterStep2Request;
use Breadcrumbs;
class GroupsController extends FrontendController {
public function __construct()
{
parent::__construct();
}
function view($slug)
{
$this->data['group'] = Group::where('slug', '=', $slug)->first();
$this->data['lifestyle_questions'] = Lifestyle_question::all();
Breadcrumbs::setCurrentRoute('dynamic_route', $this->data['group']);
return View::make('groups/view', $this->data);
}
function handle_register(RegisterStep1Request $request1, RegisterStep2Request $request2, $slug)
{
$this->data['group'] = Group::where('slug', '=', $slug)->first();
die("Validation passed");
}
}
The view method works fine however when I submit the form I get the following error message:
ErrorException in GroupsController.php line 27:
Argument 1 passed to App\Http\Controllers\GroupsController::handle_register() must be an instance of App\Http\Requests\User\RegisterStep1Request, string given
I know this has to do with the parameters that are being passed to the controller method from the route definition and so I tried the following in an attempt to sort it:
Route::post('{slug}', ['as' => 'dynamic_route_submit', function($slug){
$group = \App\Group::where('slug', $slug)->first();
if(!is_null($group)) {
$app = app();
$controller = $app->make('App\Http\Controllers\GroupsController');
return $controller->callAction('handle_register', [new \App\Http\Requests\User\RegisterStep1Request, new \App\Http\Requests\User\RegisterStep2Request, $group->slug]);
} else {
abort(404);
}
}]);
This fixed the issue except the requests just didn't get triggered. How can I call this method and ensure that the requests get triggered so that the validation is run?

Never use an anonymous function in the routing if you're going to call a controller inside of it. Declare your route like this:
Route::post('{slug}', ['as' => 'dynamic_route_submit', 'uses' => 'App\Http\Controllers\GroupsController#handle_register']);
Then in the controller handle whatever validation is necessary.

You could try moving your request validations out of the Request classes and into private controller actions:
UserController.php
/**
* Validates a Create User request
*/
protected function validateCreate()
{
$this->validate($this->request, [
'name' => 'required|max:255',
'email' => 'required|unique:users|max:255',
'account_types_id' => 'required|numeric',
]);
}
So do something similar with your code and call these validation methods from within your controller action:
UserController.php
/**
* #return \Illuminate\Http\RedirectResponse
* #throws CreateException
*/
public function create()
{
$this->validateCreate();
As an FYI you can access route parameters by name using request()->route()->getParameter('slug')
$slug = request()->route()->getParameter('slug');
$this->data['group'] = Group::where('slug', '=', $slug)->first();

Related

Laravel redirect()->action not working and show missing parameters

PHP Version:7.2
Laravel Version:6.2
I am doing a simple project by laravel by article.
When I meet with redirect()->action, I am a little confused about that.
I want to pass a variable named id by redirect()->action but it does't work.
Error Message is Missing required parameters for [Route: blog/post.show] [URI: blog/post/{post}].
If I remove the variable name, only pass the variable value and it would work. I read the manual but still could not understand the reason. Could you help me explain the logic. Thank you. Below is the sample code.
Router.php
Route::group(['prefix' => 'blog',
'as' => 'blog/',
'namespace' => 'Blog'],
function(){
Route::resource('/post',"PostController");
});
PostController.php
Create new blog post ( wrong )
Couldn't understant why this does't work ? Variable name($id) is the same.
public function store(Request $request)
{
$post = new BlogPost;
$post->title = $title;
$post->content = $content;
$post->save();
return redirect()->action(
'Blog\PostController#show', ['id' => $post->id]
);
}
Create new blog post ( correct )
public function store(Request $request)
{
$post = new BlogPost;
$post->title = $title;
$post->content = $content;
$post->save();
return redirect()->action(
'Blog\PostController#show', [$post->id]
);
//Or 'Blog\PostController#show', $post->id
}
Show the new blog post
public function show($id)
{
$post = BlogPost::find($id);
if(! $post) {
abort(404);
}
$content = $post->content;
return view("blog.post", [
"title" => $post->title,
"content" => $content,
]);
}
Thank you
Here is code :
return redirect()->route('routename', ['id' => 1]);
You got the error message because you are using the Resource Route and it will automatic bind the Model with Route
For More Info please refer: https://laravel.com/docs/6.x/routing#route-model-binding
I encountered this error myself when trying to use a redirect()->action. Here's a simple example that will fail in just the same way.
class SimpleController extends Controller {
public function index() {
return redirect()->action([static::class, 'show'], ['id' => 7]);
}
public function show($id) {
// ... code goes here ...
}
}
And in the routes somewhere:
Route::resource('somethingsimpler', SimpleController);
The reason this fails is because default stub used by Route::resource for show is the same as the resource name. Have a read here: https://laravel.com/docs/9.x/controllers#actions-handled-by-resource-controller
Solution 1
We could change our original example to using 'somethingsimpler' instead of 'id'.
class SimpleController extends Controller {
public function index() {
return redirect()->action([static::class, 'show'], ['somethingsimpler' => 7]);
}
public function show($id) {
// ... code goes here ...
}
}
And in the routes somewhere:
Route::resource('somethingsimpler', SimpleController);
However, this seems to negate the whole purpose of using redirect()->action.
Solution 2
Reading further in the same document linked above, it seems you can set the resource name https://laravel.com/docs/9.x/controllers#restful-naming-resource-route-parameters.
class SimpleController extends Controller {
public function index() {
return redirect()->action([static::class, 'show'], ['id' => 7]);
}
public function show($id) {
// ... code goes here ...
}
}
And in the routes somewhere:
Route::resource('somethingsimpler', SimpleController)->parameters([
'somethingsimpler' => 'id'
]);
Solution 3 - Recommended
Reading the rest of the document, it becomes obvious that you can probably get away with not even naming the parameter.
class SimpleController extends Controller {
public function index() {
return redirect()->action([static::class, 'show'], [7]);
}
public function show($id) {
// ... code goes here ...
}
}
And in the routes somewhere:
Route::resource('somethingsimpler', SimpleController);

How do I capture a protected page's url in query string?

Beware with me for a second as I try to lay the background to my issue.
So I having using the python web framework Flask close to a year now and it has a wonderful extension called Flask-Login that helps provide user session management kind of like this in laravel.
Having said all that, there is a certain feature in Flask-Login that provides the functionality that when a user is not logged or signed in and tries to access that a page that requires one to be authenticated for example /create_post, they will be redirected back to the login page with that page encoded in the query string like /login?next=%2Fcreate_post.
Am trying to implement the same feature in a laravel project that am working on so I can redirect the user to the page they probably wanted to go to in the first place or to a different route in case that query string doesn't exist and I cannot seem to find where to put my code to do just that and I don't want to mess with anything in the vendor directory(because of the obvious issues that come with that), and I have tried manipulating the file app/Http/Middleware/RedirectIfAuthenticated.php by doing what is below but with no success.
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
return redirect('/');
}
$previous_url = url()->previous(); // how do I insert this in query string
return $next($request);
}
Will I have to create my own middleware or is there another way of implementing this kind of feature in laravel?
NOTE: I am not using the default laravel authentication system. I have created my own controller SessionsController to handle logins which contains the below code.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;
class SessionsController extends Controller
{
public function __construct()
{
$this->middleware('auth')->except(['create', 'login']);
}
public function create()
{
$data = [
'title' => 'Login',
'body_class' => 'hold-transition login-page',
];
return view('auth.login', $data);
}
public function login(Request $request)
{
$this->validate($request, [
'username' => 'required',
'password' => 'required',
]);
$user = User::checkCredentials($request->username, $request->password);
if (!$user) {
return back()->with([
'class' => 'alert-danger',
'message' => 'Please check your credentials',
]);
}
// set session active flag to true
$user->session_active = true;
$user->save();
auth()->login($user);
return redirect()->route('dashboard');
}
public function destroy()
{
$user = auth()->user();
$user->last_login = date('Y-m-d H:i:s');
$user->session_active = false;
$user->save();
auth()->logout();
return redirect()->route('login')->with([
'class' => 'alert-success',
'message' => 'You logged out successfully',
]);
}
}
Thank you.
I managed to somewhat solve my issue even though I didn't use query strings as I had wanted.
I create a helper function get_previous_url as shown below
/**
* Gets the previous url
*
* #return null|string
*/
function get_previous_url()
{
$host = $_SERVER['HTTP_HOST'];
$previous_url = url()->previous();
// check if previous url is from the same host
if (!str_contains($previous_url, $host)) {
return null;
}
// get the previous url route
list(, $route) = explode($host, $previous_url);
// make sure the route is not the index, login or logout route
if (in_array(substr($route, 1), ['', 'login', 'logout'])) {
$route = '';
}
return $route;
}
And then I called the same function in my SessionsController class in the create method by doing this
public function create()
{
$previous_url = get_previous_url();
if ($previous_url) {
session(['previous_url' => $previous_url]);
}
...
}
And then I changed my login method to
public function login(Request $request)
{
...
$redirect = redirect()->route('dashboard'); // '/'
if (session()->has('previous_url')) {
$redirect = redirect(session()->pull('previous_url'));
}
return $redirect;
}

How to get all user details from laravel5.3

How i get all users in laravel 5.3 . i am using barryvdh for cors
this is my RegisterController which is in Auth folder
public function index(){
return Users::all();
}
above code gives all the user data if in route below we do not use middleware
and if we use middleware then i got error unauthenticated . so i want to get all user data using middleware in route . How can i get
Route::get('/users','Auth\RegisterController#index')->middleware('auth');
I think you can try this :
public function index(){
$users = Users::get();
return $users;
}
Hope this work for you!
So if you want to get all data of your user table you simple have to do following:
# Middleware group if user is logged in
Route::group(['middleware' => 'auth'], function ()
{
Route::get('home', ['as' => 'home', 'uses' => 'HomeController#index']);
Route::group(['prefix' => 'user'], function ()
{
Route::get('get', ['as' => 'getUser', 'uses' => 'UserController#getUser']);
});
});
And in your controller you can do something like this:
class UserController extends Controller
{
public function getUser(Request $request)
{
$users = DB::table('users')->get();
return $users;
}
}
If you want add something to that return you probably have to create a relation between your models, and call them in your method and return them.
If you still have any questions or if I understood something wrong feel free to comment on this answer.
Edit:
If you want to return all user with an api route you can do following in your api routes:
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
Try this
public function index()
{
$userDetail = Users::get();
dd($userDetails);
}

Inputting to a Controllers closure in laravel 5.2

So i have a 'TicketController' which holds my functions for manipulating 'tickets' in a system.
I am looking to work out the best way to send my new route that will take a route parameter of {id} to my TicketController to view a ticket.
Here is my route set
Route::group(['middleware' => 'auth', 'prefix' => 'tickets'], function(){
Route::get('/', 'TicketController#userGetTicketsIndex');
Route::get('/new', function(){
return view('tickets.new');
});
Route::post('/new/post', 'TicketController#addNewTicket');
Route::get('/new/post', function(){
return view('tickets.new');
});
Route::get('/view/{id}', function($id){
// I would like to ideally call my TicketController here
});
});
Here is my ticket controller
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Ticket;
use App\User;
class TicketController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
/**
* Returns active tickets for the currently logged in user
* #return \Illuminate\Http\Response
*/
public function userGetTicketsIndex()
{
$currentuser = \Auth::id();
$tickets = Ticket::where('user_id', $currentuser)
->orderBy('updated_at', 'desc')
->paginate(10);
return view('tickets.index')->with('tickets', $tickets);
}
public function userGetTicketActiveAmount()
{
$currentuser = \Auth::id();
}
public function addNewTicket(Request $request)
{
$this->validate($request,[
'Subject' => 'required|max:255',
'Message' => 'required|max:1000',
]);
$currentuser = \Auth::id();
$ticket = new Ticket;
$ticket->user_id = $currentuser;
$ticket->subject = $request->Subject;
$ticket->comment = $request->Message;
$ticket->status = '1';
$ticket->save();
}
public function viewTicketDetails()
{
//retrieve ticket details here
{
}
You don't need to use closure here. Just call an action:
Route::get('/view/{id}', 'TicketController#showTicket');
And in TicketController you'll get ID:
public function showTicket($id)
{
dd($id);
}
More about this here.
You should use type-hint in laravel. Its awesome
In route
Route::get('/view/{ticket}', 'TicketController#viewTicketDetails');
In controller
public function viewTicketDetails(Ticket $ticket)
{
//$ticket is instance of Ticket Model with given ID
//And you don't need to $ticket = Ticket::find($id) anymore
{

Passing multiple parameters to controller in Laravel 5

In my application, a user has the ability to remind another user about an event invitation. To do that, I need to pass both the IDs of the event, and of the user to be invited.
In my route file, I have:
Route::get('events/{id}/remind', [
'as' => 'remindHelper', 'uses' => 'EventsController#remindHelper']);
In my view, I have:
{!!link_to_route('remindHelper', 'Remind User', $parameters = array($eventid = $event->id, $userid = $invitee->id) )!!}
In my controller, I have:
public function remindHelper($eventid, $userid)
{
$event = Events::findOrFail($eventid);
$user = User::findOrFail($userid);
$invitees = $this->user->friendsOfMine;
$invited = $event->helpers;
$groups = $this->user->groupOwner()->get();
return view('events.invite_groups', compact('event', 'invitees', 'invited', 'groups'));
}
However, when I hit that route, I receive the following error:
Missing argument 2 for App\Http\Controllers\EventsController::remindHelper()
I'm sure I have a formatting error in my view, but I've been unable to diagnose it. Is there a more efficient way to pass multiple arguments to a controller?
When you define this route:
Route::get('events/{id}/remind', [
'as' => 'remindHelper', 'uses' => 'EventsController#remindHelper']);
You are saying that a single URI argument will be passed to the method.
Try passing the two arguments, like:
Route::get('events/{event}/remind/{user}', [
'as' => 'remindHelper', 'uses' => 'EventsController#remindHelper']);
View:
route('remindHelper',['event'=>$eventId,'user'=>$userId]);
Route :
Route::get('warden/building/{buildingId}/employee/{employeeId}',[
'uses'=>'WardenController#deleteWarden',
'as'=>'delete-warden'
]);
View :
Controller:
public function deleteWarden($buildingId,$employeeId){
$building = Building::find($buildingId);
$building->employees()->detach($employeeId);
return redirect('warden/assign/'.$buildingId)->with('message','Warden Detached successfully');
}
This is how you do it:
Click Here
Go to your controller and write code like following:
public function passData()
{
$comboCoder=['Bappy','Sanjid','Rana','Tuhin'];
$ffi=['Faisal','Sanjid','Babul','Quiyum','Tusar','Fahim'];
$classRoom=['Sanjid','Tamanna','Liza'];
return view('hyper.passData',compact('comboCoder','ffi','classRoom'));
}
/*
Again, in View part use:
(passData.blade.php)
*/
<u>Combocoder:</u>
#foreach($comboCoder as $c)
{{$c}}<br>
#endforeach
<u>FFI</u>
#foreach($ffi as $f)
{{$f}}<br>
#endforeach
<u>Class Room </u>
#foreach($classRoom as $cr)
{{$cr}}<br>
#endforeach
Route::get('/details/{id}/{id1}/{id2}', 'HomeController#SearchDetails');
//pass data like the below code
<a href="{{url("/details/{$orga_list->dcode}/{$orga_list->dname}/{$GroupHead}")}}"
target="_blank" > Details </a>
//controller write like the below code
public function SearchDetails($id, $searchtext,$grp_searchtext)
{
// get data like the below code
$data['searchtext'] = $searchtext;
$data['grp_searchtext'] = $grp_searchtext;
$data['id_is'] = $id;
}
routes/web.php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\BookController;
Route::controller(BookController::class)->group(function () {
Route::get('author/{author_name}/book/{title}', 'show')
->name('book.show');
});
Now update the controller like:
app/Http/Controllers/BookController.php
namespace App\Http\Controllers;
use App\Models\Book;
use App\Models\Author;
use Illuminate\Http\Request;
class BookController extends Controller
{
public function show(Request $request, Author $author, Book $book)
{
return view('show',[
'book' => $book->show($request)
]);
}
}
Now update the book model:
app\Models\Book.php
namespace App\Models;
use App\Common\HasPdf;
use App\Common\HasImage;
use Illuminate\Contracts\Database\Eloquent\Builder;
use Illuminate\Support\Facades\URL;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Factories\HasFactory;
class Book extends Model
{
use HasFactory;
protected $guarded = [];
public function author() : BelongsTo
{
return $this->belongsTo(Author::class);
}
public function url()
{
return URL::route('book.show', [
'author_name' => $this->author->author_name,
'title' => $this->title,
]);
}
}
<h3>{{ $item->title }}</h3>
Hope it can help you.

Categories