CSRF on Yajra Datatable Laravel not working - laravel

I have this code in laravel and used YAJRA as my datatable and upon submitting it says that the CSRF token is error, attached here is my code in Controller before rending in View/Blade.
Here is my code:
$return = '<form method="post" action="/procurement/add-product">
'.{{ csrf_token() }}.'
<input type="hidden" name= "product_id" value=".$row->id.">
<input type="text" name="product_qty" class="form-control">
<button type="submit" class="btn btn-primary btn-block">Add Item</button>
</form>';
return $return;

I found an answer via documentation, https://laravel.com/docs/master/csrf
I just put the URI of the said form
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier;
class VerifyCsrfToken extends BaseVerifier
{
/**
* The URIs that should be excluded from CSRF verification.
*
* #var array
*/
protected $except = [
//
'procurement/*',
];
}

Return the form to another blade like view/products/datatables.blade.php
Example: The controller should looks like:-
public function getproducts()
{
$product = Product::all(); //Product is Model name
return Datatables::of($product)
->addColumn('action', function($product)
{
return view('product.datatables', compact('product'))->render();
})->make(true);
}
And the view should look as below:
Edit
<form action="/product/{{ $product->id }}" method="post" id="deleteForm">
{{ method_field('DELETE') }}
{{ csrf_field() }}
<button class="btn btn-danger btn-sm" type="submit">Delete</button>
</form>
It will work just fine. Because the mustache {{}} can't be read in the controller. We redirect the things to the blade

Related

How do I deal with form in laravel?

I was dealing with forms in laravel, I have written the code but once i click on the button to submit the form it's just reset the page
Here is my view create.blade.php
#extends('layouts.app')
#section('content')
<div class="container">
<form action="/p" enctype="multipart/form-data" method="post">
#csrf
<div class="row">
<div class="col-8 offset-2">
<div class="row">
<h1>Add New Post</h1>
</div>
<div class="form-group row">
<label for="caption" class="col-md-4 col-form-label">Post Caption</label>
<input id="caption"
type="text"
class="form-control{{ $errors->has('caption') ? ' is-invalid' : '' }}"
name="caption"
value="{{ old('caption') }}"
autocomplete="caption" autofocus>
#if ($errors->has('caption'))
<span class="invalid-feedback" role="alert">
<strong>{{ $errors->first('caption') }}</strong>
</span>
#endif
</div>
<div class="row">
<label for="image" class="col-md-4 col-form-label">Post Image</label>
<input type="file" class="form-control-file" id="image" name="image">
#if ($errors->has('image'))
<strong>{{ $errors->first('image') }}</strong>
#endif
</div>
<div class="row pt-4">
<button class="btn btn-primary">Add New Post</button>
</div>
</div>
</div>
</form>
</div>
#endsection
And my PostsController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class PostsController extends Controller
{
public function create(){
return view('posts.create');
}
public function store(){
$data = request()->validate([
'caption' => 'required',
'image' => ['required', 'image'],
]);
Post::create($data);
dd(request()->all());
}
}
my routes web.php
<?php
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('/', function () {
return view('welcome');
});
Auth::routes();
Route::get('/p/create', 'PostsController#create');
Route::post('/p', 'PostsController#create');
Route::get('/profile/{user}', 'ProfilesController#index')->name('profile.show');
The validation is not working and every time I click on the button, it resets everything. Kidly Help me sort this out
Post model
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreatePostsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('user_id');
$table->string('caption');
$table->string('image');
$table->timestamps();
$table->index('user_id');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('posts');
}
}
Change this line in your web.php file, from
Route::post('/p', 'PostsController#create');
to
Route::post('/p/store', 'PostsController#store')->name('p.store');
As you can see in the modification above, you were pointing to the wrong Controller method.
Additionally, it is best practice to use named route.
With the above named route, you can now use the route helper without worrying about the url like this in your form:
<form action="{{ route('p.store') }}" enctype="multipart/form-data" method="post">
</form>
UPDATE 1:
I didn't catch this earlier. Your Controller method must have at least the Request object as parameter in the definition for POST requests. Also update your validation logic.
Update your store() method to this
public function store(Request $request){
$request->validate([
'caption' => 'required',
'image' => 'required|image|mimes:jpeg,png,jpg,gif,svg',
]);
Post::create($request->input());
dd($request->all());
}
Observe that you were using the global request helper request() previously. You don't need to do that anymore because the Request object is now passed in as a parameter. Also note that you don't need to pass any actual arguments when you use the route. The argument is automatically passed in by Laravel.
UPDATE 2:
Also, update your Post model with $fillable array
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model {
protected $fillable = ['caption', 'image'];
public function user(){
return $this->belongsTo(User::class);
}
}
The $fillable array indicate fields in the database that can be assigned using an HTTP request (e.g. from an HTML form).
From the Laravel documentation:
you will need to specify either a fillable or guarded attribute on the model, as all Eloquent models protect against mass-assignment by default.
The problem is in your route. Both your get and post route are going to the controller's create method. Post route will be like
Route::post('/p', 'PostsController#store');

Undefined variable: posts when passing parameter from controller to view

I'm trying to create a search function in Laravel and its returning me with "undefined variable: posts" when I do foreach on my view.
My code:
Post Model
class Post extends Model {
protected $fillable = [
'creator',
'post_url',
'books',
'likes',
'created_at'
];
public function user() { return $this->belongsTo(User::class); }
}
Homeview:
<form action="{{ url('/search') }}" method="get">
<input type="text" class="search-text form-control form-control-lg" name="q" placeholder="Search" required>
</form>
Controller:
public function search($keyword)
{
$result = Post::where('books', 'LIKE', "'%' . $keyword . '%'")->get();
return view('/search', ['posts' => $result]);
}
Route:
Route::get('/search/{keyword}', 'SearchController#search');
Searchview:
#foreach($posts as $post)
<div class="post">{{ $post->id }}</div>
#endforeach
What am I doing wrong here?
This might help you out.
Homeview.blade.php
<form action="/search" method="POST">
#csrf // include your csrf token
<input type="text" class="search-text form-control form-control-lg" id="q" name="q" placeholder="Search" required>
</form>
Searchview.blade.php
<!-- or did you return a collection? -->
#if( $posts->count() > 1 )
<!-- then loop through the posts -->
#foreach( $posts as $post )
<div class="post"> {{ $post->id }} </div>
#endforeach
#else
#if( !empty($posts) )
<div class="post"> {{ $post->id }} </div>
#endif
#endif
Routes/web.php
Route::post('/search', 'PostsController#show')->name('posts.show');
PostsController
use App\Post;
public function show( Request $request )
{
$result = Post::where("books", "LIKE", "%{$request->input('q')}%")->get();
// Uncomment the following line to see if you are returning any data
// dd($result);
// Did you return any results?
return view('searchview', ['posts' => $result]);
}
The reason it wasn't working,
Route::get('/search/{keyword}', 'SearchController#search');
In your route file you were looking for a {keyword} that was never passed by the form. Your form action is action="{{ url('/search') }}". A get variable will not be picked up by a route and if it was you called the input 'q' anyway.
So then in your controller you were looking for the keyword being passed that is never passed in.
public function search($keyword)
Instead the correct thing to do is pass in the Request object like so
public function search(Request $request)
Then use $request->input('q') to retrieve the passed value through your form.
In your example $keyword would always have been blank.
Corrected code
Homeview:
<form action="{{ url('/search') }}" method="get">
<input type="text" class="search-text form-control form-control-lg" name="q" placeholder="Search" required>
</form>
Controller:
public function search(Request $request)
{
$result = Post::where('books', 'LIKE', "%{$request->input('q')}%")->get();
return view('/search', ['posts' => $result]);
}
Route:
Route::get('/search', 'SearchController#search');
Searchview:
#foreach($posts as $post)
<div class="post">{{ $post->id }}</div>
#endforeach
try:
return view('/search')->with('posts', $result);
Or even better with dinamic vars.
return view('/search')->withPosts($result);

Can't update Laravel database (Model, View, Controller)

I'm currently working with Laravel. I'm a novice and still trying to get used to the platform. I want to update my database based on form input but it's not working. I've tried updating models, views, and controllers and can't seem to get the database to update with input values.
My view:
<div class="form-group row">
<label class="col-xs-2 col-form-label">Expiration Date</label>
<div class="col-xs-10">
<input class="form-control" type="date" value="{{ $Document->expires_at }}" name="expires_at" placeholder="Expiration Date">
</div>
</div></form>
<embed src="{{ asset('storage/'.$Document->url) }}" width="100%" height="100%" />
<div class="row">
<div class="col-xs-6">
<form action="{{ route('admin.provider.document.update', [$Document->provider->id, $Document->id]) }}" method="POST">
{{ csrf_field() }}
{{ method_field('PUT') }}
<button class="btn btn-block btn-primary" type="submit">Approve</button>
</form>
</div></form>
My model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class ProviderDocument extends Model
{
protected $table = 'provider_documents';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'provider_id',
'document_id',
'url',
'unique_id',
'status',
'expires_at',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
];
/**
* The services that belong to the user.
*/
public function provider()
{
return $this->belongsTo('App\Provider');
}
/**
* The services that belong to the user.
*/
public function document()
{
return $this->belongsTo('App\Document');
}
}
My controller:
public function update(Request $request, $provider, $id)
{
if(Setting::get('demo_mode', 0) == 1) {
return back()->with('flash_error', 'Disabled for demo purposes! Please contact us at info#appoets.com');
}
try {
$Document = ProviderDocument::where('provider_id', $provider)
->where('id', $id)
->firstOrFail();
$Document->update(['status' => 'ACTIVE']);
$Document->expires_at = $request['expires_at'];
$Document->save();
return redirect()->route('admin.provider.document.index', $provider)->with('flash_success', 'Provider document has been approved.');
}
catch (ModelNotFoundException $e) {
return redirect()->route('admin.provider.document.index', $provider)->with('flash_error', 'Provider not found!');
}
}
The database stays blank with no errors. If I manually put it in the database directly, then go to the form and update, it's deleted. Please help.
Thanks to the input of ##LimKeanPhang above, below is the end result. I didn't have to change the model or controller. Just the view. Worked like a charm.
<form class="form-horizontal" action="{{ route('admin.provider.document.update', [$Document->provider->id, $Document->id]) }}" method="POST">{{csrf_field()}}
<input type="hidden" name="_method" value="PATCH">
<div class="form-group row">
<label class="col-xs-2 col-form-label">Expiration Date</label>
<div class="col-xs-10">
<input class="form-control" type="date" value="{{ $Document->expires_at }}" name="expires_at" placeholder="Expiration Date">
</div>
</div>
<embed src="{{ asset('storage/'.$Document->url) }}" width="100%" height="100%" />
<div class="row">
<div class="col-xs-6">
<button class="btn btn-block btn-primary" type="submit">Approve</button>
</div>
</div>
</form>
Why don't you get the get the document by id only as follows ? Please try the following code. It should work.
The controller update function.
public function update(Request $request, $provider, $id)
{
if (Setting::get('demo_mode', 0) == 1) {
return back()->with('flash_error', 'Disabled for demo purposes! Please contact us at info#appoets.com');
}
try {
$Document = ProviderDocument::find($id);
$Document->status = 'ACTIVE';
$Document->expires_at = $request['expires_at'];
$Document->save();
return redirect()->route('admin.provider.document.index', $provider)->with('flash_success',
'Provider document has been approved.');
} catch (ModelNotFoundException $e) {
return redirect()->route('admin.provider.document.index', $provider)->with('flash_error',
'Provider not found!');
}
}

"No message" error laravel - trying to update user account information

I'm receiving the error "MethodNotAllowedHttpException
No message" on submit of my user's form, which is meant to update the user's table. I have two post forms on the same page and two post routes, would that have something to do with it?
I will include all the routes and another form that might be conflicting with it.
web.php
Route::get('profile','userController#profile');
Route::post('profile', 'userController#update_avatar');
Route::post('profile-update', 'userController#update_account'); //this ones not working
userController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;
use Auth;
use Image;
class UserController extends Controller
{
//
public function profile()
{
return view('profile', array('user' => Auth::user()) );
}
public function update_avatar(Request $request)
{
if($request->hasFile('avatar')){
$avatar = $request->file('avatar');
$filename = time() . '.' . $avatar->getClientOriginalExtension();
Image::make($avatar)->resize(300,300)->save( public_path('/uploads/avatars/' . $filename) );
$user = Auth::user();
$user->avatar = $filename;
$user->save();
}
return view('profile', array('user' => Auth::user()) );
}
public function update_account(Request $request, $id) //the function with the error
{
User::update([
'id' => Auth::user()->id,
'name' => $request->name,
'email' => $request->email
]);
return redirect('/profile');
}
}
profile.blade.php
<img src="/uploads/avatars/{{ $user->avatar }}" style="width:150px;height:150px;float:left;border-radius:50%;margin-right:25px">
<h2>{{ $user->name }}'s Profile</h2>
<form enctype="multipart/form-data" action="/profile" method="post">
<label>Update Profile Image</label>
<input type="file" name="avatar">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<input type="submit" class=" btn btn-sm btn-light" style="color:#2b2b2b;" value="Update Image">
</form>
<form method="post" action="/profile-update"> <!-- The form with the error -->
{{ method_field('put') }}
{{ csrf_field() }}
<input type="hidden" name="_method" value="PUT" />
<label>Username</label>
<input type="text" name="name" class="form-control" value="{{ $user->name }}">
<label>Email</label>
<input type="email" name="email" class="form-control" value="{{ $user->email }}">
<input type="submit" id="update-account" class="btn btn-success" value="Update">
</form>
try this method:
public function update_account(Request $request, $id)
{
$user = User::find($id)
$user->name = $request->name;
$user->email = $request->email;
$user->update();
return redirect('/profile');
}
You don't have any route which can handle the PUT request for "profile-update". In your form you have defined the following function.
{{ method_field('put') }}
This helper function generate an hidden input field which will be used by Laravel to process the current request only as PUT.
To make this work, you either have to make your make your request POST by removing the above helper function or change your route method to PUT.
Route::put('profile-update', 'userController#update_account');
For those that might need the same answer, to fix this I had to play about with it for quite some time and used bits from the suggested answers to solve the issue completely.
I changed the route method to put in web.php.
Replaced my update_account function with #TonzFale answer but replaced $user = User::find($id)with $user = User::find(Auth::user()->id);.

Issue updating user account with avatar laravel

So I was able to submit the form to allow an avatar to be uploaded and changed which worked. Now I am trying to allow all the user details to be updated too.
If I just try to change the username or email and submit, the page is reloaded with the original content. When I upload a new avatar and then try to submit I get the error "Non-static method Illuminate\Http\Request::input() should not be called statically".
*edited*** I've just realised Im saying if the user uploads an image then update the form. Whereas I want the form to submit whether or not an image has been uploaded. How could I change my update_avatar function for this to work?
web.php
Route::get('profile','userController#profile');
Route::post('profile', 'userController#update_avatar');
userController
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Auth;
use Image;
class UserController extends Controller
{
//
public function profile()
{
return view('profile', array('user' => Auth::user()) );
}
public function update_avatar(Request $request)
{
if($request->hasFile('avatar')){
$avatar = $request->file('avatar');
$filename = time() . '.' . $avatar->getClientOriginalExtension();
Image::make($avatar)->resize(300,300)->save( public_path('/uploads/avatars/' . $filename) );
$user = Auth::user();
$user->avatar = $filename;
$user->name = Request::input('username');
$user->email = Request::input('email');
$user->save();
}
return view('profile', array('user' => Auth::user()) );
}
}
profile.blade.php
<img src="/uploads/avatars/{{ $user->avatar }}" style="width:150px;height:150px;float:left;border-radius:50%;margin-right:25px">
<h2>{{ $user->name }}'s Profile</h2>
<form enctype="multipart/form-data" action="/profile" method="post">
<label>Update Profile Image</label>
<input type="file" name="avatar">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<label>Username</label>
<input type="text" name="username" class="form-control" value="{{ $user->name }}">
<label>Email</label>
<input type="email" name="email" class="form-control" value="{{ $user->email }}">
<input type="submit" class=" btn btn-sm btn-light" style="color:#2b2b2b;">
</form>
change the code
$user->name = $request->input('username');
$user->email = $request->input('email');
Please see the docs for more information:
http://laravel.com/docs/5.0/controllers#dependency-injection-and-controllers
in top of the namespace declaration in your controller ,
replace the following
use Illuminate\Http\Request;
to
use Request;

Resources