Reputation: 563
I am working on a management-style application using Laravel 5, which has a login/logout feature and a facility for users to create their own posts (in this example they are called 'bookings'). I want each user to be able to create their own bookings that are unique to them - i.e. only visible when they are logged in with their username and password. In order to achieve this I have created a column in the 'bookings' table (which stores all the bookings) for user_id. When a logged in user creates a booking, I want his/her own user id to be stored in the user_id column. So at the moment I am passing the user_id (ascertained using auth()->user()) into the 'bookings.store' function as an additional parameter in the route (url). However, I keep on receiving the message: "No query results for model [App\Booking]" when submitting the form, instead of being redirected back to the bookings page with the new booking saved as expected.
Here is some of my code: // BookingsController.php:
<?php
namespace App\Http\Controllers;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Http\Request;
use View;
use App\Model;
use App\User;
use App\Booking;
use App\BookingItem;
use App\Http\Controllers\Validator;
use Input;
class BookingsController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
$bookings = \App\Booking::all();
return View::make('bookings.index')->with('bookings', $bookings);
// $user = auth()->user()->id;
// $bookings = auth()->user()->bookings()->get();
// return view('bookings.index')->with('bookings', $bookings);
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
$user = auth()->user();
return View::make('bookings.create')->with('user', $user);
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request, $user_id)
{
// define rules
$rules = [
'name' => 'between:2,255',
];
$this->validate($request, [
'name' => 'required|unique:bookings|max:255',
]);
$name = $request->get('name');
$description = $request->get('description');
$booking->name = $name;
$booking->user_id = $user_id;
$booking->description = $description;
$booking->save();
return Redirect::route('bookings.index')->withMessage('Booking Was Created');
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
$booking = \App\Booking::findorFail($id);
$items = $booking->BookingItems()->get();
return View::make('bookings.show')
->withBooking($booking) // will allow us to see our bookings, by id.
->withItems($items);
}
}
?>
// Create.blade.php
@extends('layouts.main')
@section('content')
<div class="container">
<div class="row">
<div class="small-6 columns">
<div class="panel panel-default">
<div class="panel-heading"><h2>Add a new booking</h2></div>
<div class="panel-body">
{{ var_dump($user->id) }}
<form class="form-horizontal" role="form" method="POST" action="{{ route('bookings.store', $user->id) }}">
<input name="_method" type="hidden" value="PUT">
{!! csrf_field() !!}
@include('bookings.partials._form');
<div class="form-group">
<div class="col-md-6 col-md-offset-4">
<button type="submit" class="btn btn-primary">
<i class="fa fa-btn fa-briefcase"></i>Add Booking
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@stop
// web.php (my routes)
Route::get('/', 'BookingsController@index');
Route::resource('bookings', 'BookingsController');
Route::resource('bookings.items', 'BookingItemController', ['except' => ['index', 'show']]);
Route::resource('agents', 'UsersController');
Route::get('/bookings/{bookings}/items/{items}/complete', ['as' => 'bookings.items.complete', 'uses' => 'BookingItemController@complete']);
Auth::routes();
Route::get('/home', 'HomeController@index');
Route::get('/logout', function(){
Auth::logout();
return Redirect::route('bookings.index')->withErrors('You Are Logged Out!');
});
Route::post('/bookings/{id}', ['uses' => 'BookingsController@store', 'as' => 'bookings.store']);
My bookings table contains the following columns:
id (pk) user_id (fk) name description created_at updated_at
If anyone has any advice or could help, that would be great. At the moment, I think it might be defaulting to the show route.
Regards,
Robert London, Uk
Current routes:
+--------+-----------+--------------------------------------------+-------------------------+------------------------------------------------------------------------+--------------+
| Domain | Method | URI | Name | Action | Middleware |
+--------+-----------+--------------------------------------------+-------------------------+------------------------------------------------------------------------+--------------+
| | GET|HEAD | / | | App\Http\Controllers\BookingsController@index | web |
| | GET|HEAD | agents | agents.index | App\Http\Controllers\UsersController@index | web |
| | POST | agents | agents.store | App\Http\Controllers\UsersController@store | web |
| | GET|HEAD | agents/create | agents.create | App\Http\Controllers\UsersController@create | web |
| | GET|HEAD | agents/{agent} | agents.show | App\Http\Controllers\UsersController@show | web |
| | DELETE | agents/{agent} | agents.destroy | App\Http\Controllers\UsersController@destroy | web |
| | PUT|PATCH | agents/{agent} | agents.update | App\Http\Controllers\UsersController@update | web |
| | GET|HEAD | agents/{agent}/edit | agents.edit | App\Http\Controllers\UsersController@edit | web |
| | GET|HEAD | api/user | | Closure | api,auth:api |
| | POST | bookings | bookings.store | App\Http\Controllers\BookingsController@store | web |
| | GET|HEAD | bookings | bookings.index | App\Http\Controllers\BookingsController@index | web |
| | GET|HEAD | bookings/create | bookings.create | App\Http\Controllers\BookingsController@create | web |
| | GET|HEAD | bookings/{bookings}/items/{items}/complete | bookings.items.complete | App\Http\Controllers\BookingItemController@complete | web |
| | DELETE | bookings/{booking} | bookings.destroy | App\Http\Controllers\BookingsController@destroy | web |
| | PUT|PATCH | bookings/{booking} | bookings.update | App\Http\Controllers\BookingsController@update | web |
| | GET|HEAD | bookings/{booking} | bookings.show | App\Http\Controllers\BookingsController@show | web |
| | GET|HEAD | bookings/{booking}/edit | bookings.edit | App\Http\Controllers\BookingsController@edit | web |
| | POST | bookings/{booking}/items | bookings.items.store | App\Http\Controllers\BookingItemController@store | web |
| | GET|HEAD | bookings/{booking}/items/create | bookings.items.create | App\Http\Controllers\BookingItemController@create | web |
| | DELETE | bookings/{booking}/items/{item} | bookings.items.destroy | App\Http\Controllers\BookingItemController@destroy | web |
| | PUT|PATCH | bookings/{booking}/items/{item} | bookings.items.update | App\Http\Controllers\BookingItemController@update | web |
| | GET|HEAD | bookings/{booking}/items/{item}/edit | bookings.items.edit | App\Http\Controllers\BookingItemController@edit | web |
| | POST | bookings/{id} | bookings.store | App\Http\Controllers\BookingsController@store | web |
| | GET|HEAD | home | | App\Http\Controllers\HomeController@index | web,auth |
| | GET|HEAD | login | login | App\Http\Controllers\Auth\LoginController@showLoginForm | web,guest |
| | POST | login | | App\Http\Controllers\Auth\LoginController@login | web,guest |
| | POST | logout | | App\Http\Controllers\Auth\LoginController@logout | web |
| | GET|HEAD | logout | | Closure | web |
| | POST | password/email | | App\Http\Controllers\Auth\ForgotPasswordController@sendResetLinkEmail | web,guest |
| | GET|HEAD | password/reset | | App\Http\Controllers\Auth\ForgotPasswordController@showLinkRequestForm | web,guest |
| | POST | password/reset | | App\Http\Controllers\Auth\ResetPasswordController@reset | web,guest |
| | GET|HEAD | password/reset/{token} | | App\Http\Controllers\Auth\ResetPasswordController@showResetForm | web,guest |
| | GET|HEAD | register | | App\Http\Controllers\Auth\RegisterController@showRegistrationForm | web,guest |
| | POST | register | | App\Http\Controllers\Auth\RegisterController@register | web,guest |
+--------+-----------+--------------------------------------------+-------------------------+------------------------------------------------------------------------+--------------+
Upvotes: 0
Views: 2570
Reputation: 6335
You need to name the route something else because bookings.store
is already defined in Route::resource('bookings', 'BookingsController');
I would recommend excluding this resource from the resource and defining your bookings.store
with an optional {id?}
parameter you can check if present so you can store a user's bookings or a normal one based on the presence of that parameter in the store method.
Also as @Steve Bauman recommended, remove <input name="_method" type="hidden" value="PUT">
from your form because with that there it is accessing your bookings.update
method.
It should all fit together as follows:
Route::get('/', 'BookingsController@index');
Route::resource('bookings', 'BookingsController', ['excep'=> ['store']]);
Route::post('/bookings/{id?}', ['uses' => 'BookingsController@store', 'as' => 'bookings.store']);
Route::resource('bookings.items', 'BookingItemController', ['except' => ['index', 'show']]);
Route::resource('agents', 'UsersController');
Route::get('/bookings/{bookings}/items/{items}/complete', ['as' => 'bookings.items.complete', 'uses' => 'BookingItemController@complete']);
Auth::routes();
Route::get('/home', 'HomeController@index');
Route::get('/logout', function(){
Auth::logout();
return Redirect::route('bookings.index')->withErrors('You Are Logged Out!');
});
Route::post('/bookings/{id}', ['uses' => 'BookingsController@store', 'as' => 'bookings.store']);
Then in your store method in your controller:
public function store(Request $request, $user_id = null)
{
// define rules
$rules = [
'name' => 'between:2,255',
];
$this->validate($request, [
'name' => 'required|unique:bookings|max:255',
]);
$booking->name = $request->get('name');
$booking->description = $request->get('description');
$booking->user_id = $user_id;
$booking->save();
return Redirect::route('bookings.index')->withMessage('Booking Was Created');
}
This way, it will handle the work for you if there is an id it will apply it and if not then it will be null
Upvotes: 0
Reputation: 8678
Why don't you just grab the authenticated users ID during the creation rather then sending it through the form? This could be a huge security issue as well since a user could modify the HTML of the page and submit a booking under a different user ID.
Here's a fix:
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
*
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
// define rules
$rules = [
'name' => 'between:2,255',
];
$this->validate($request, [
'name' => 'required|unique:bookings|max:255',
]);
$booking = new Booking();
$booking->name = $request->name;
$booking->user_id = auth()->id();
$booking->description = $request->description;
$booking->save();
return Redirect::route('bookings.index')->withMessage('Booking Was Created');
}
Edit:
You have this route here:
Route::post('/bookings/{id}', ['uses' => 'BookingsController@store', 'as' => 'bookings.store']);
But inside your HTML form you're initiating a PUT
request when it should be just a standard POST
:
<input name="_method" type="hidden" value="PUT">
Upvotes: 1