I have a function in my controller. The problem is I must use two Requests at the same time but only one of them can be used in a controller.
Illuminate\Support\Facades\Request
Illuminate\Http\Request
Code:
public function func(Request $req) {
if (Request::isMethod('post')) {
$this->validate($req, [
'username' => 'required|string'
]);
}
}
What is the solution?
If you wanted to use both of them, you can alias them as below:
use Illuminate\Http\Request as RequestNew;
use Illuminate\Support\Facades\Request as RequestOld;
And then you can reference the alias in your code.
eg: RequestNew::isMethod('post')
Related
I am new to Laravel and I am trying to edit and delete user transactions, but I am stuck with this error:
The update_transaction method is not supported for route POST.
Supported methods: GET, HEAD.
This is my EditTransferController:
namespace App\Http\Controllers;
use App\Models\transfer;
use App\Models\User;
use App\Providers\RouteServiceProvider;
use Illuminate\Auth\Events\Registered;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\Rules;
use Illuminate\Support\Str;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class EditTransferController extends Controller
{
public function update_transaction(Request $request)
{
$id = $request->id;
$transfer = Transfer::find($id);
return view('Transfers_profile', ['transfer' => $transfer]);
}
public function delete_transaction(Request $request)
{
$transfer = $request->id;
Transfer::find($transfer)->delete();
return view('AllTransfers');
}
}
And this is routes/web.php:
Route::get('/update_transaction', function (Request $request) {
$transfer = Transfer::find($request->id);
return view('update_transaction', ['transfer' => $transfer]);
})->name('update_transaction');
Route::PUT('/transaction_profile', [EditTransferController::class, 'update_transaction'])->name('post_transaction_profile');
Route::post('/transaction_delete', [EditTransferController::class, 'delete_transaction'])->name('delete_transaction_profile');
It looks like there are a few issues with the code you've provided:
In the routes/web.php file, the update_transaction route is defined
as a GET request, but the controller method that should handle the
request is expecting a PUT request. To fix this, you should change
the route definition to:
Route::get('/update_transaction/{id}', [EditTransferController::class, 'update_transaction'])->name('update_transaction');
In the EditTransferController, the update_transaction method expects
the id to be passed in the request, but you are not passing it from
the route. To fix this, you should pass the id when calling the
route, like this:
return redirect()->route('update_transaction', ['id' => $id]);
The delete_transaction route is defined as a POST request, but the
controller method that should handle the request is expecting a
DELETE request. To fix this, you should change the route definition
to:
Route::delete('/transaction_delete/{id}', [EditTransferController::class, 'delete_transaction'])->name('delete_transaction_profile');
In the EditTransferController, the delete_transaction method expects
the id to be passed in the request, but you are not passing it from
the route. To fix this, you should pass the id when calling the
route, like this:
return redirect()->route('delete_transaction_profile', ['id' => $id]);
In the update_transaction method, you are using Transfer model but
it is defined as transfer in the use statement. So you should change
the Transfer to transfer
In the delete_transaction method, you are trying to delete a record
by passing $request->id but it should be $request->transfer.
You should change the above mentioned issues in your code, it should work fine.
I am very obviously a noob to Laravel and hope that someone can help me out.
The about screen is accessed through the route
Route::get('/about', array('as' => 'about', function()
{
return View::make('about')->with('title','About Screen')->with('class','about');
}));
The variables $title and $class are accessible in about.blade.php by {{ $title }} and {{ $class }}. If instead, I have a Controller in between,
Route::get('hello/create', array('as' => 'create', 'uses' =>
'HelloController#create', function()
{
return View::make('hello/create')->with('title','Create')->with('class','hello.create');
}));
How do I access $title and $class in the HelloController.php code (so that I can propagate the values to the coming View)?
P.S. I do know about the /hello/create/{name of variable} which is the answer on nearly all questions similar to this, but don't know how to use it to transmit variables NOT keyed onto the Http Request.
$title and $class are the values you are manually giving to the blade. These aren't the values that you are receiving in GET parameters in your route. So, you would do it the same way as you did in the closure.
Your route:
Route::get('hello/create', array('as' => 'create', 'uses' => 'HelloController#create'));
Controller method:
class HelloController{
public function create(){
return View::make('hello/create')->with('title','Create')->with('class','hello.create');
}
}
UPDATE:
From what I understood, you can also call controller's method inside the route's closure and pass parameters to the controller and call the view with these values inside the controller's method.
Your route file:
use App\Http\Controllers\HelloController;
Route::get('hello/create',function(){
$hello_obj = new HelloController();
return $hello_obj->create('create','hello.create');
});
Controller method:
class HelloController{
public function create($title,$class){
return View::make('hello/create')->with('title',$title)->with('class',$class);
}
}
First you need to clear your flow. You are -at the moment- manually setting the variables to be returnet to the view, so your route should look like this:
Route::get('hello/create', 'HelloController#create');
Then, your controller handles the logic:
public function create(Request $request)
{
return view('hello.create')->with('title','Create')->with('class','hello.create');
}
Now, if you need to send parameters from your frontend to your controller, you have two options:
Define route parameters.
Use query params.
Option 1
For the first option, you'll need to define your required/optional parameters in the route itselft:
Route::get('hello/create/{a_variable}', 'HelloController#create');
Then you access this parameter in any of this ways:
public function create(Request $request)
{
return view('hello.create')->with('a_variable', $request->a_variable);
}
or injecting the variable in the method:
public function create(Request $request, $a_variable)
{
return view('hello.create')->with('a_variable', $a_variable);
}
Option 2
For the use of query params, you should include this options when making the request. If your route looks like this:
Route::get('hello/create', 'HelloController#create');
You could specify query params like this:
GET www.my-domain.com/hello/create?first_parameter=value_1&second_parameter=value_2
So in your controller you access this values like this:
public function create(Request $request)
{
$value_1 = $request->get('first_parameter');
$value_2 = $request->get('second_parameter');
return view('hello.create')
->with('value_1', $value_1)
->with('value_2', $value_2);
}
You are alreading sending data to view using with().
Echo it in your view file using $variablename set in with() Example: <?php echo $title; ?>
I saw there are a few other questions in which they asked what the difference was between $this->validate and Validator::make(). They didnt really answer the conceptual question I was wondering though.
Is there a proper use for each of these? Like when to use one versus the other?
How I am currently using it is in my API classes I use a if else with $validator::make() (like below) while in my Web portion of the program I use $this->validate() (also below)
Is this a proper way to use this?
$validator::make:
public function store(Request $request)
{
$validator = Validator::make($request->all(),[
'name' => 'required',
'url' => 'required',
'isPublic' => 'required'
]);
if($validator->fails()){
return response($validator->messages(), 200);
} else {
Helpers::storeServer($request);
return response()->json([
'message'=> ['Server Stored']
]);
}
}
$this->validate:
public function store(Request $request)
{
$this->validate($request, [
'name' => 'required',
'url' => 'required',
'isPublic' => 'required'
]);
Helpers::storeServer($request);
return redirect('dashboard')->with('success', 'Server stored');
}
Nope, they do the same exact thing two different ways. I mean that literally, $this->validate() calls the make() method on the validation class. If you look at ValidatesRequests.php, implemented by Controller.php which your controller extends.
The validate() method calls:
$validator = $this->getValidationFactory()
->make($request->all(), $rules, $messages, $customAttributes);
So it ends up using the make() method eventually. There is a difference in how it is handled, since $this->validate() calls:
if ($validator->fails()) {
$this->throwValidationException($request, $validator);
}
So using Validator::make() will allow you to handle the exception yourself, instead of $this->validate() auto throwing the validation exception for you. This is useful for doing something before your redirect. You show this in your first example, since you check if the validation fails before deciding how to handle it.
In the second example you know that if validation fails it will automatically refuse the request...
if fail any rules on $this->validate, will auto throw an error
$validator::make: you can easy handle the errors and may be you want wrap any data to array() and pass to $validator::make: for Validation
and also if you want to use FormRequest + Route Model Binding
your store() look like this
public function store(YourFormRequestRules $request)
{
Helpers::storeServer($request);
return redirect('dashboard')->with('success', 'Server stored');
}
public function update(YourFormRequestRules $request, Post $post)
{
$post->title = $request->input('title');
$post->save();
return redirect()->route('example.index');
}
thats all
Using $this->validate(): YourController extends a Controller class which uses ValidatesRequests trait and it looks like this:
namespace App\Http\Controllers;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
}
The ValidatesRequests trait itself is made up of several methods that the base Controller gets and then your own controller and which includes:
validateWith($validator, Request $request = null)
...
validate(Request $request, array $rules, array $messages = [], array $customAttributes = [])
...
validateWithBag($errorBag, Request $request, array $rules, array $messages = [], array $customAttributes = [])
... and so on...
These methods helps makes some validation and request errors handling much convenient and in fact considering the mentioned validate() method.
When there's validation error in the request passed, it helps you handle the response without litering your controller with unneeded logic; i.e when it's an ajax call it returns a 422 response with a json body while it returns populates the error bag and fill the $errors variable for use in the blade template for non-ajax.
In summary, this only helps you incase you don't want to do manual validation by creating an instance of Validator, so to keep the developer focus on doing the real work ;)
UPDATE:
$validator = Validator::make() //creates an instance of the validator for further operations
// You can even do after the creating the instance of validator:
$this->validateWith($validator, $request)
//Lets do both steps above i.e the validation and trigger the Validation Exception if there's failure.
$this->validate($request, [...rules...], [...messages..])
Check: https://laravel.com/docs/5.6/validation#quick-writing-the-validation-logic
Validator helper makes me more happy
$validator = validator()->make(request()->all(), [
'type' => 'required|integer'
]);
if ($validator->fails())
{
redirect()->back()->with('error', ['your message here']);
}
Laravel give helper that makes developing more convince.
Can I remove the following line of code
use Illuminate\Http\Request;
form laravel Controller? Is this a good practice?
For example, my HomeController:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class HomeController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
public function index()
{
$totals = [
'customers' => \App\Customer::count(),
'jobs' => \App\Job::count(),
'invoices' => \App\Invoice::count(),
];
$data = [
'page_title' => 'Dashboard',
'totals' => $totals
];
return view('home', $data);
}
}
Here I don't need the "Request", because none of the functions doesn't use that parameter.
To obtain an instance of the current HTTP request via dependency injection, you should type-hint the Illuminate\Http\Request class on your controller method. The incoming request instance will automatically be injected by the service container.
So if you don't want To obtain an instance of the current HTTP request then remove it.
Yes if you are using just select data query you can go ahead and remove this line. It's need where you will use any get or post form in your class function.
Hello I'm trying to create a code generator to invite a user from input email, I want to save on the database the user id who send the invite, the code, and the email who is going to recive the invite, but I can't get the id of my auth user doing $request->user('id') (not working) also I know there is other method to do this easier than using DB::table something like
$request->user()->invites()->create... my controller looks like
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use DB;
use App\Http\Requests;
use App\Http\Controllers\Controller;
class invitacionController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
public function index(Request $request)
{
return view('administrar');
}
public function invitacion(Request $request)
{
$this->validate($request, [
'email' => 'required|email|max:255|unique:invites',
]);
/*$request->user()->invites()->create([
'code' => str_random(40),
]);*/
DB::table('invites')->insert([
['usuId' => $request->user('id'), 'code' => str_random(40), 'email' => $request->input('email')],
]);
return redirect('/administrar');
}
}
If the relationship is properly configured, the first (commented) method should be working.
As for the second method, I think you are adding extra brackets:
DB::table('invites')->insert([
'usuId' => $request->user()->id, // <---
'code' => str_random(40),
'email' => $request->input('email')
]);
That hasMany method can take additional parameters. By default it expects the column to be named user_id, but you called it usuId. The documentation gives this example:
return $this->hasMany('App\Comment', 'foreign_key');
So I think you should do
public function invites()
{
return $this->hasMany(Invite::class, 'usuId');
}