Laravel 5: Trying to get property of non-object through method injection - php

I am using Route-Model-Binding with method injection to retrieve the $post->id of the post I am commenting on, but I keep getting this error
Trying to get property of non-object (View: C:\xampp\htdocs\reddit\resources\views\partials\post.blade.php) (View: C:\xampp\htdocs\reddit\resources\views\partials\post.blade.php)
This is the method I have, injecting Post $post then trying to get $post->id
dd($post) retrieves nothing at all even if I dump the model alone.
public function post_this_comment(Request $request, Post $post) {
$post = Post::whereId($post->id)->first(); // this is where I'm getting the post
$comment = new Comment;
$comment->user_id = Auth::id();
$comment->comment = $request->input('commenter_comment');
$comment->parent_id = $request->input('commenter_parent');
if($comment->parent_id > 0){
$my_parent = Comment::find($comment->parent_id);
$comment->parents = $my_parent->parents.'.'.$comment->parent_id;
}else{
$comment->parents = '0';
}
$comment->save();
$per_page = $request->input('per_page');
$comment_list = view('post/show')
->with('comments', $this->comment_list($per_page, $request))
->with('total_comments', $this->total_comments())
->with('per_page', $per_page)
->with('post', $post)
->render();
$response = array(
'status' => 'success',
'msg' => 'Comment Saved!',
'comment_list' => $comment_list
);
return Response::json($response);
}
This is the view, I have opened a form even though I don't need it because I'm submitting data via ajax.
{!! Form::open(['route' => ['post_this_comment', $post]]) !!}
<div class="comment-fields">
<div class="commenter-comment">
<div class="form-group col-md-12">
<textarea id="commenter_comment" name="commenter_comment" class="form-control comment-field" title="User's comment" placeholder="Comment Text"></textarea>
</div>
</div>
<div class="commenter-name-email">
<input type="hidden" id="commenter_parent" name="commenter_parent" class="commenter-parent" value="0">
</div>
<div class="commenter-captcha">
<div class="col-md-3 text-right">
Comment
</div>
</div>
{!! Form::close() !!}
Routes
Route::resource('posts', 'PostsController');
Route::post('{post}/post_this_comment', ['as' => 'post_this_comment', 'uses' => 'PostsController#post_this_comment']);
RouteServiceProvider
$router->model('articles', 'App\Article');
$router->model('subreddit', 'App\Subreddit');
$router->model('posts', 'App\Post');
$router->model('moderators', 'App\Moderator');
$router->model('comments', 'App\Comment');

The parameter in your route needs to match the one you used for your route model binding. In your case you have defined posts: $router->model('posts', 'App\Post'); but you are using {post} (without the 's') as the parameter in your route. Instead your route should be:
Route::post('{posts}/post_this_comment', ['as' => 'post_this_comment', 'uses' => 'PostsController#post_this_comment']);
If you want to inject your Post model in to you method.

You should bind the model using something like this:
$router->model('post', 'App\Post'); // 'post' parameter is used here
So that you can use the following:
Route::post(
'{post}/post_this_comment', // post parameter is used here
[
'as' => 'post_this_comment',
'uses' => 'PostsController#post_this_comment'
]
);
Bith parameters should match. When you bind some model using a parameter for example, $router->model('user', 'App\User') you said the framework to bind the appropriate User model when it sees a user parameter used in a route.

Related

Trying to get property of non-object laravel when accessing database

I am trying to code the edit route for laravel and for some reason keep getting the error "Trying to get property of non-object laravel". The Create controller works fine, however when I use the controller#update route I keep getting this error
My Controller for adding an event: (update)
public function update(Request $request, $id)
{
//create event
$my_user = my::find($id);
$my_user->programme = $request->input('programme');
$my_user->goal1 = $request->input('goal1');
$my_user->goal2 = $request->input('goal2');
$my_user->goal3 = $request->input('goal3');
$my_user->goal4 = $request->input('goal4');
$my_user->goal5 = $request->input('goal5');
$my_user->user_id = auth()->user()->id;
$my_user->save();
return redirect('/home')->with('success','Event Created');
}
edit page
#extends('layouts.app')
#section('content')
<div class="container">
<h1>Edit Post</h1>
{!! Form::open(['action' => ['myUserController#update', $my_user], 'method' => 'POST']) !!}
<div class="form-group">
{{Form::label('title', 'Event Name')}}
{{Form::text('goal1', $my_user->goal1, ['class' => 'form-control', 'placeholder' => 'Goal One'])}}
</div>
{{Form::hidden('_method','PUT')}}
{{Form::submit('Submit', ['class'=>'btn btn-primary'])}}
{!! Form::close() !!}
</div>
#endsection
Given that you are using a Route::resource you can type-hint your parameters by writing something like
public function update(Request $request, MyUser $myuser){
// The $myuser parameter comes from the Route::resource and can be verified using php artisan route:list in your terminal
// edit $my_user
$my_user->save();
return redirect('/home')->with('success','Event Created');
}
Update after reviewing LaravelCollective documentation for Form
Thank you Sohel0415 for mentioning that you do not need to call $my_user->id for providing the route parameter with the Form facade.
You can use this method on your code:
{{ Form::open(array('url'=>'admin/users/store' , 'method' =>'POST')) }}
and your route define by this method in web.php file:
Route::post('users/store', 'admin\UserController#store');

Laravel trying to output posts but Controller function seem to work wrong

I'm trying to output my posts and for that in a specific page I call a function with foreach to load all the posts, and the function in my controller is something like:
public function getDashboard()
{
$posts = Post::all();
return view('dashboard', ['posts' => $posts]);
}
and my route is something like this:
Route::get('/dashboard',[
'uses' => 'PostController#getDashboard',
'as' => 'dashboard'
]);
but get an error when I try to load the page when i'm not logged in
the error is something like:
Undefined variable: posts (View: C:\wamp64\www\projectname\resources\views\dashboard.blade.php)
Anything you say is highly appreciated.
(I use Laravel 5.3.26 )
Here you go this is my blade, but I don't think this is where the problem is:
#extends('layouts.master')
#section('content')
#foreach($posts as $post)
<article class="post">
<div class="media w3-border-left w3-border-blue">
<div class="media-left media-top">
</div>
<div class="media-body">
<header><h4 class="media-heading">{{ $post->title }}</h4></header>
<p>{{ $post->body }}</p>
<div class="info">
Posted by {{ $post->user->name }} on {{ $post->created_at }}
</div>
<div class="interaction">
Like |
Dislike |
Edit |
Delete
</div>
</div>
</div>
<br>
</article>
#endforeach
#endsection
Try:
public function getDashboard()
{
$posts = Post::all();
return view('dashboard', compact('posts'));
}
I'm thinking it's your authentication redirecting to a different controller method (which is not injecting the Posts).
Try a composer in your routes\web.php
View::composer( ['dashboard.blade'] , function($view) {
$action = app('request')->route()->getAction();
dump($action);
return $view->with(
[
'posts' => Post::all(), // you may need the fully qualified namespace here
]
);
});
This is a bit dirty and you won't want to keep this but it should give you some further info to go off - if you can post the output of the dump and check that posts are still injected when logged out;
Using this method the output of my dump was
array:7 [▼
"middleware" => array:2 [▼
0 => "web"
1 => "auth"
]
"uses" => "App\Http\Controllers\Admin\TestController#home"
"controller" => "App\Http\Controllers\Admin\TestController#home"
"namespace" => "App\Http\Controllers\Admin"
"prefix" => "/admin"
"where" => []
"as" => "admin.test"
]

How to pass 2 parameters in a route, but make one hidden in Laravel?

I want to make an edit_Item functionality, but I'm having a little bit of trouble with routing when submiting the edited form. I get this error:
InvalidArgumentException in UrlGenerator.php line 314:
Route [userItems] not defined.
First of all, in my Edit page, I have a form which passes 2 arguments from the Items table (item_id and user_id) to the controller and it looks like this:
{!! Form::model($items, ['action' => ['ItemController#update', $items->id, $items->user_id], 'method' => 'PUT']) !!}
//Form inputs
{{ Form::close() }}
My Update controller looks like this:
public function update($id, $user_id){
// validate
// read more on validation at http://laravel.com/docs/validation
$rules = array(
'title' => 'required',
'description' => 'required|description',
);
// store
$items = Item::find($id);
$items->title = Input::get('title');
$items->description = Input::get('description');
$items->save();
// redirect
Session::flash('message', 'Successfully updated item!');
return Redirect::route('userItems');
}
And my Route with the Update method looks like this:
Route::put('/userItems/{id}/{user_id}', 'ItemController#update');
Now, when I submit I'm currently getting routed to:
http://localhost:8000/userItems/26/3
And I need to get routed to:
http://localhost:8000/userItems/3
Any ideas on how to make the item_id(26) disappear from the route?
You could use an hidden input
Define a hidden field (not visible to a user).
Your form
{!! Form::model($items, ['action' => ['ItemController#update', $items->user_id], 'method' => 'PUT']) !!}
<input type="hidden" name="item_id" value="{{$items->id}}">
//Form inputs
{{ Form::close() }}
Your route
Route::put('/userItems/{user_id}', 'ItemController#update');
Your controller
public function update($user_id){
// validate
// read more on validation at http://laravel.com/docs/validation
$rules = array(
'title' => 'required',
'description' => 'required|description',
);
// store
$item_id = Request::input('item_id');
$items = Item::find($item_id);
$items->title = Input::get('title');
$items->description = Input::get('description');
$items->save();
// redirect
Session::flash('message', 'Successfully updated item!');
return Redirect::route('userItems');
}

Laravel conflicting routes

My routes.php excerpt:
Route::group(['prefix' => 'admin', 'namespace' => 'Admin'], function() {
Route::resource('posts', 'PostsController', [
'except' => ['show']
]);
Route::delete('posts/trash', [
'as' => 'posts.trash.empty',
'uses' => 'PostsController#emptyTrash'
]);
});
My PostsController.php excerpt:
/**
* DELETE /admin/posts/{id}
*/
public function destroy($id)
{
// code
}
/**
* DELETE /admin/posts/trash
*/
public function emptyTrash()
{
// code
}
The problem is that Laravel confuses the 'trash' string in a DELETE /admin/posts/trash request as an {id} parameter. As a consequence, the destroy() method is called instead of emptyTrash(). Why and What can I do for this?
Firstly, order matters. Laravel will search the routes for a match in the order you register them. As you figured out, Laravel will take trash as an id and therefore the URI matches the resource route. Since that route is registered before your additional one, it will use the resource route.
The simplest fix is to just change that order:
Route::delete('posts/trash', [
'as' => 'posts.trash.empty',
'uses' => 'PostsController#emptyTrash'
]);
Route::resource('posts', 'PostsController', [
'except' => ['show']
]);
If you don't like that you can try to limit the parameter for your resource route to numbers only. Unfortunately you can't just add a ->where() to the resource route like you could with others.
Instead you have to define a global pattern for the route parameter. The route parameter Route::resource chooses is the resource name (in snake_case).
So this should work for you:
Route::pattern('posts', '[0-9]+');
Somewhere in your view, you should have a button or a link for actually deleting the post. The view should look something like this:
#section('content')
<div class="panel panel-default">
<div class="panel-heading clearfix">
<b>{{ $post->post_name . ' (id:' . $post->post_id . ')' }}</b><br />
<b> {{ link_to_route('overview', 'Go Back To Post List') }} </b>
<div class="pull-right">
// FORM FOR DELETING POST
{{ Form::open(array('route' => array('delete_post', $post->post_id))) }}
{{ link_to_route('edit_post', 'Edit Post', array('id' => $post->post_id), array('class' => 'post_img_button_edit')) }}
{{ Form::hidden('_method', 'DELETE') }}
{{ Form::submit('Delete Post', array('class' => 'post_img_button_delete')) }}
{{ Form::close() }}
</div>
<div class="pull-right">
// FORM FOR EMPTYING TRASH
{{ Form::open(array('route' => 'empty_trash')) }}
{{ Form::hidden('_method', 'DELETE') }}
{{ Form::submit('Empty Trash', array('class' => 'post_img_button_delete')) }}
{{ Form::close() }}
</div>
</div>
/* Additional HTML code within view */
Your controller should be similar to this:
public function destroy($id)
{
$this->post->delete($id);
return \Redirect::route('overview');
}
public function emptyTrash()
{
// code for collecting and emptying Trash
}
And your routes should look similar to this:
Route::delete('admin_posts/admin_posts/{id}/destroy', array('as'=>'delete_post', 'uses'=>'PostsController#destroy'));
Route::delete('posts/trash', array('as'=>'empty_trash', 'uses'=>'PostsController#emptyTrash'));
The name of your route for actually deleting posts be 'delete_post'.
The name of your route for emptying your trash will be empty_trash
Basically you're explicitly defining your routes so that you'll avoid less ambiguity and Laravel will know which routes to take. Hopefully this information will help!

Generating URL::route with parameter in Laravel 4

I am having trouble getting getting my parameter of 'item id' to tack onto the end of my route being generated for my form action url.
I have a page setup to 'update' an existing item. The routes looks something like this:
Route::get('/item/edit/{id}', array(
'as' => 'item-edit',
'uses' => 'ItemController#getEditItem',
));
Route::post('/item/edit/{id}', array(
'as' => 'item-edit-post',
'uses' => 'ItemController#postEditItem',
));
and my ItemController contains these methods:
public function getEditItem($id) {
$states = State::where('user_id', '=', Auth::user()->id)->get();
$types = Type::where('user_id', '=', Auth::user()->id)->get();
$item = Item::where('user_id', '=', Auth::user()->id)
->where('id', '=', $id)
->first();
return View::make('items.edit')
->with('item', $item)
->with('states', $states)
->with('types', $types);
}
public function postEditItem($id) {
// Validate input for Item changes
$validator = Validator::make(Input::all(),
array(
'label' => 'required|min:3|max:128|unique:items,label,null,id,user_id,' . Auth::user()->id,
'type_id' => 'required|integer',
'state_id' => 'required|integer',
)
);
if( $validator->fails() ) {
return Redirect::route('item-edit')
->withErrors($validator)
->withInput();
} else {
$item = Item::find($id);
$item->label = Input::get('label');
$item->type_id = Input::get('type_id');
$item->state_id = Input::get('state_id');
$item->save();
return Redirect::route('item-create')
->with('global', 'Your new item has been edited successfully!');
}
}
The last piece of the puzzle is my items.edit view:
#extends('layout.main')
#section('content')
<form action="{{ URL::route('item-edit-post', $item->id) }}" method="post" class="form-horizontal form-bordered" autocomplete="off">
<!-- some inputs and such -->
</form>
#stop
The action URL being generated here is wrong:
<form method="POST" action="http://manageitems.com/item/edit/%7Bid%7D" accept-charset="UTF-8" hello="hello" class="form-horizontal form-bordered">
For some reason it is escaping my {id} in the route and not adding on the actual item ID on the end of the route. I have tried a few different ways of doing this and read through the route parameter docs, but I haven't made any progress. I also tried using Laravel's for builder like so:
{{ Form::open(array('action' => 'ItemController#postEditItem', $item->id, 'class'=>'form-horizontal form-bordered')) }}
but this did the same thing. I am new to Laravel so this may be a simple problem that I am overlooking, any help is much appreciated.
Use an array in the second parameter.
URL::route('item-edit-post', ['id' => $item->id])
Or the route helper (what I would go with, fits more in view files).
route('item-edit-post', ['id' => $item->id])
It seems that $item->id returns null.
And this is how you do it, when you specify action or route in the Form::open:
Form::open(['route' => ['some.route', $param]]);
Form::open(['action' => ['controller#action', $param]]);

Categories