I'm encountering a problem where a redirect from one route to another is calling the targeted controller method twice. This question addresses a similar issue, but the OP passing a 301 status code was deemed to be the issue in the accepted answer, and I'm not specifying any status code. I'm also using the session state for parameters. The relevant code looks something like this:
public function origin(Request $request) {
// Assume I have set variables $user and $cvId
return redirect()
->action('SampleController#confirmUser')
->with([
'cvId' => $cvId,
'userId' => $user->id,
]);
}
public function confirmUser(Request $request) {
$cvId = session()->get('cvId');
$userId = session()->get('userId');
if (is_null($cvId) || is_null($userId)) {
// This is reached on the second time this is called, as
// the session variables aren't set the second time
return redirect('/home');
}
// We only see the view for fractions of a second before we are redirected home
return view('sample.confirmUser', compact('user', 'cvId'));
}
Any ideas what could be causing this? I don't have any next middleware or any of the other possible causes that are suggested in related questions where controllers are executed twice.
Thanks for any help!
Have you tried passing values in parameters? Try the below code.
public function origin(Request $request) {
// Assume I have set variables $user and $cvId
return redirect()->action(
'SampleController#confirmUser', ['cvId' => $cvId, 'userId'=>$user->id]
);
}
public function confirmUser(Request $request) {
$cvId = $request->cvId;
$userId = $request->userId;
if (is_null($cvId) || is_null($userId)) {
// This is reached on the second time this is called, as
// the session variables aren't set the second time
return redirect('/home');
}
// We only see the view for fractions of a second before we are redirected home
return view('sample.confirmUser', compact('user', 'cvId'));
}
I'm working on L5.5 and I need to delete user but not his/her posts. So I basically need to assign his/her posts to another user which has to be Non-removable.
What I need:
Create a user which can't be deleted at least not from front-end even by owner of website but can be edited. (mostly is like bot for this application)
If I delete a user and that user had post(s) those post(s) remain and assign to this user (bot). It means this bot will become author of those posts.
Check for number 2 that only if user with post that happens if user has no post just delete him/her.
This is my usecontroller destroy method currently:
public function destroy($id)
{
$user = User::findOrFail($id);
Storage::delete($user->image);
$user->delete();
return redirect()->route('users.index')->with('flash_message', 'User successfully deleted');
}
Thanks.
According to your needs, you will require softDeletes in your User model and their respective tables in the database, now this solves your 1st problem where your not deleting the user from table simply adding deleted_at column.
Edit: As you are using Zizaco\Entrust\Traits\EntrustUserTrait you need to have your user model look something like this:
class User extends Model implements AuthenticatableInterface
{
use Authenticatable;
use EntrustUserTrait { restore as private restoreA; }
use SoftDeletes { restore as private restoreB; }
public function restore()
{
$this->restoreA();
$this->restoreB();
}
}
For more information about this error you need to look: https://github.com/Zizaco/entrust/issues/742
so now coming to the 2nd point, retrieving the post with deleted model can be used withTrashed() something like:
$user = User::withTrashed()->all();
$user = User::withTrashed()->where('id', 1);
$posts = $user->posts()->get();
// Or do your relational things
Even if you want to assign it to different user then you need to create a new user and apply update methods to all the relational model while deleting the user which seems a bad idea.
Edit:
So in this case you can have:
$oldUser = User::find($id);
$user = User::find($botID); // Find the bot user
$oldFoods = $oldUser->food()->get();
foreach($oldFoods as $food)
{
$food->user_id = $user->id;
$food->save();
}
Now for your 3rd point if the user has no post then you can do a small check something like this:
$user = User::find($request->id);
$posts = $user->posts()->get()->first();
if(isset($posts))
{
$user->delete();
}
else
{
$user->forceDelete();
}
Hope this justifies all your needs.
Conclusion So fnally you can have your destroy method in userController as:
public function destroy($id)
{
$user = User::findOrFail($id);
$foods = $user->food()->get();
if(isset($foods))
{
$botUser = User::where('username', '=', 'bot'); // Find the bot user
foreach($foods as $food)
{
$food->user_id = $botUser->id;
$food->save();
}
$user->delete();
}
else
{
$user->forceDelete();
}
Storage::delete($user->image);
return redirect()->route('users.index')->with('flash_message', 'User successfully deleted');
}
Edit your database with
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users')
->onDelete('restrict')
->onUpdate('restrict');
im using laravel 5.4
upon submitting the form, the user_id of the submitter will be inserted in the database. and im not sure if its the right way so if you have any idea please help me thanks
can anyone help me please this my controller as of now.
public function index()
{
$user = Auth::user();
$rfq_table = $user->rfq_table;
return view('admin.sales.rfq.index',compact('rfq_table'));
}
public function create()
{
return view('admin.sales.rfq.create',compact('rfq_table'));
}
public function store(Request $request)
{
$user=Auth::user();
$rfq= $user->rfq_table()->create($request->all());
return redirect()->route('admin.sales.rfq.index');
}
I'm not sure how your DB looks, but you can create a var $user_id = Auth::user()->id; and save that in your DB
If you are using a form, insert the session user id like this in your insert controller:
Create your variable out of the user()'s id:
$user_id = Auth::user()->id;
Then use the variable here:
$insert->usr_id = $user_id;
$insert->postcode = request('postcode');
Your Other Inserts from your submitted form go here.
I'm continuing my adventure with Laravel 5.1. I have a small project I'm working on and I'm looking to find a nice way to load a User's gecko ideally without having the user id in the URI.
This is my current URI which works as it is:
Route::get('gecko/{user_id}/{name}', 'GeckoController#show');
As you can see i'm holding the user id in the URI and then i'm querying it to find the right gecko. As shown below:
public function show($user_id, $name)
{
$name = str_replace('-', ' ', $name);
$gecko = Gecko::where(compact('user_id', 'name'))->first();
return view('gecko.show', compact('gecko'));
}
So to get this to work, I would do project.dev/gecko/1/Zilly - It works, but having the User ID in there kind of sucks. I decided that having the User ID was important in case there were multiple users who have geckos with the same name.
Any help on this is greatly appreciated, and if you need any extra code let me know :)
Andy
If you would like to use username instead of user_id:
Routes:
Route::get('gecko/{username}/{geckoname}', 'GeckoController#show');
Controller:
public function show($username, $geckoname) {
$user_id = User::where('username', $username)->first()->id;
$geckoname = str_replace('-', ' ', $geckoname);
$gecko = Gecko::where(compact('user_id', 'geckoname'))->first();
return view('gecko.show', compact('gecko'));
}
If the user authenticated you can use Auth::user()->id and you should add only the gecko id.
For example:
Routes:
Route::get('gecko/{gecko_id}', 'GeckoController#show');
Controller:
public function show($id) {
$gecko = Gecko::find($id)->where('user_id', Auth::user()->id)->first();
return view('gecko.show', compact('gecko'));
}
If you would like to use geckoname:
Routes:
Route::get('gecko/{geckoname}', 'GeckoController#show');
Controller:
public function show($geckoname) {
$gecko_id= Gecko::where('geckoname',$geckoname)->first()->id;
$gecko = Gecko::find($gecko_id)->where('user_id', Auth::user()->id)->first();
return view('gecko.show', compact('gecko'));
}
I am trying to create a page where I can see all the people in my database and create edits on them. I made a form where I fill in the data from the database of certain fields.
I would like to navigate trough them by a Next and Previous button.
For generating the next step I have to take the ID larger than the current one to load the next profile.
For generating the previous step I have to take the ID smaller than the current one to load the previous profile.
My route:
Route::get('users/{id}','UserController#show');
Controller:
public function show($id)
{
$input = User::find($id);
// If a user clicks next this one should be executed.
$input = User::where('id', '>', $id)->firstOrFail();
echo '<pre>';
dd($input);
echo '</pre>';
return View::make('hello')->with('input', $input);
}
View:
The buttons:
Next
What is the best approach to get the current ID and increment it?
Below are your updated controller and view files derived from #ridecar2 link,
Controller:
public function show($id)
{
// get the current user
$user = User::find($id);
// get previous user id
$previous = User::where('id', '<', $user->id)->max('id');
// get next user id
$next = User::where('id', '>', $user->id)->min('id');
return View::make('users.show')->with('previous', $previous)->with('next', $next);
}
View:
Previous
Next
// in your model file
public function next(){
// get next user
return User::where('id', '>', $this->id)->orderBy('id','asc')->first();
}
public function previous(){
// get previous user
return User::where('id', '<', $this->id)->orderBy('id','desc')->first();
}
// in your controller file
$user = User::find(5);
// a clean object that can be used anywhere
$user->next();
$user->previous();
In your App\Models\User.php
...
protected $appends = ['next', 'previous'];
public function getNextAttribute()
{
return $this->where('id', '>', $this->id)->orderBy('id','asc')->first();
}
public function getPreviousAttribute()
{
return $this->where('id', '<', $this->id)->orderBy('id','asc')->first();
}
In your Controller you can simply do this:
public function show(User $user)
{
return View::make('users.show')
->with('user', $user)
->with('previous', $user->previous)
->with('next', $user->next);
}
I understand the approach being taken here by user2581096 but I am not sure it is efficient (by any standards). We are calling the database 3 times for really no good reason. I suggest an alternative that will be way more efficient and scalable.
Do not pass the previous and next IDs to the view. This eliminates 2 unnecessary database calls.
Create the following routes:
users/{id}/next
users/{id}/previous
These routes should be used in the href attributes of the anchor tags
Add methods in the controller to handle each of the new routes you have created. For example:
public function getPrevious(){
// get previous user
$user = User::where('id', '<', $this->id)->orderBy('id','desc')->first();
return $this->show($user->id);
}
This function will only be called when you actually click on the button. Therefore, the database call is only made when you need to actually look up the user.
in-case you want to retrieve the prev/next records along with their data,
you can try
$id = 7; // for example
$prev = DB::table('posts')->where('id', '<', $id)->orderBy('id','desc')->limit(1);
$next = DB::table('posts')->where('id', '>', $id)->limit(1);
$res = DB::table('posts')
->where('id', '=', $id)
->unionAll($prev)
->unionAll($next)
->get();
// now $res is an array of 3 objects
// main, prev, next
dd($res);
1- the query builder is usually much faster than eloquent.
2- with union we are now only hitting the db once instead of 3.
To get next and previous post we can use max and min functions on Model id in laravel. here is an example to get this
https://usingphp.com/post/get-next-and-previous-post-link-in-laravel
The Controller:
public function post($id)
{
$post = Post::find($id);
$previous = Post::where('id', '<', $post->id)->max('id');
$next = Post::where('id', '>', $post->id)->min('id');
return view( 'post', compact( 'post', 'next', 'previous' ));
}
The View:
#if($next)
{{$next->title}}
#endif
#if($previous)
{{$previous->title}}
#endif
Here's a link I found that should help: http://maxoffsky.com/code-blog/laravel-quick-tip-get-previous-next-records/
It looks like for next you want to use: $next = User::where('id', '>', $id)->min('id'); and have the view as: Next
Also don't forget to pass $next to the view.
Simplest approach
// User.php
public static function findNext($id)
{
return static::where('id', '>', $id)->first();
}
// UserController.php
$nextUser = User::findNext($id);
// view
Next
Lazy approach :
// view
Next
// routes.php (should be optimized, this is just to show the idea)
Route::get('users/{user}/next', function($id) {
$nextUser = User::findNext($id);
return Redirect::to('user/' . $id);
});
// yourModel.php
public function previous()
{
return $this->find(--$this->id);
}
public function next()
{
return $this->find(++$this->id);
}
Works like magic, you can chain it:
$prevprev = Model::find($id)->previous()->previous();
$nextnext = Model::find($id)->next()->next();
First, get a record out of the database.
$post = Post::where('slug', $slug)->first();
With a database record, we can get the previous record where the record id is less than the id stored inside $post order by the id in descending order and use first() to get a single record back.
$previous = Post::where('id', '<', $post->id)->orderBy('id','desc')->first();
To get the next record it's almost the same query, this time get the record where the id is more than the id stored in $post.
$next = Post::where('id', '>', $post->id)->orderBy('id')->first();
Controller:
public function show($id)
{
// get the current user
$user = User::find($id);
// get previous user id
$previous = User::offset($user->id-2)->first();
// get next user id
$next = User::offset($user->id)->first();
return View::make('users.show')->with('previous', $previous)->with('next', $next);
}
i developed the code.
it work all times, even if we don't have any next or prev post
public function nextPost($table, $id)
{
$next = DB::table($table)->where('id', '>', $id)->orderBy('id','asc')->first();
if(!$next)
$next = DB::table($table)->orderBy('id','asc')->first();
return $next;
}
public function prevPost($table, $id)
{
$prev = DB::table($table)->where('id', '<', $id)->orderBy('id','desc')->first();
if(!$prev)
$prev = DB::table($table)->orderBy('id','desc')->first();
return $prev;
}