Type error: Argument 2 passed to Controller::show() must be an instance of modal, string given - php

Adding up and down voting functions to a classified page. Using Laravel, and Vue.
The error I get is:
(1/1) FatalThrowableError
Type error: Argument 2 passed to Hustla\Http\Controllers\ListingVoteController::show() must be an instance of Hustla\Listing, string given
I have included the vue file, the vote controller, the listing model, and the route. I was hoping someone could help me out.
Listing Model
public function votesAllowed()
{
return (bool) $this->allow_votes;
}
public function commentsAllowed()
{
return (bool) $this->allow_comments;
}
public function votes()
{
return $this->morphMany(Vote::class, 'voteable');
}
public function upVotes()
{
return $this->votes()->where('type', 'up');
}
public function downVotes()
{
return $this->votes()->where('type', 'down');
}
public function voteFromUser(User $user)
{
return $this->votes()->where('user_id', $user->id);
}
Vote Controller
public function show(Request $request, Listing $listing)
{
$response = [
'up' => null,
'down' => null,
'can_vote' => $listing->votesAllowed(),
'user_vote' => null,
];
if ($listing->votesAllowed()) {
$response['up'] = $listing->upVotes()->count();
$response['down'] = $listing->downVotes()->count();
}
if ($request->user()) {
$voteFromUser = $listing->voteFromUser($request->user())->first();
$response['user_vote'] = $voteFromUser ? $voteFromUser->type : null;
}
return response()->json([
'data' => $response
], 200);
}
Vote.vue
<template>
<div class="listing__voting">
<a href="#" class="listing__voting-button">
<span class="glyphicon glyphicon-thumbs-up"></span>
</a> 1
<a href="#" class="listing__voting-button">
<span class="glyphicon glyphicon-thumbs-down"></span>
</a> 2
</div>
</template>
<script>
export default {
data () {
return {
up: null,
down: null,
userVote: null,
canVote: false
}
},
props:{
listingId: null
}
}
</script>
Route
Route::get('/{location}/{listing}/votes',[
'uses' => '\Hustla\Http\Controllers\ListingVoteController#show'
]);

Your route definition has two parameters defined: {location} and {listing}. The parameters are passed to the controller method in the order in which they are defined.
Your controller method, however, is only defined to accept one route parameter. The first route parameter is what will be passed to the method, and in this route definition, that is the {location} parameter. Since {location} does not match $listing, the string value will be passed in, and you'll get the error you're seeing.
You need to add the second route parameter to your controller action:
public function show(Request $request, $location, Listing $listing)
{
// code
}
If $location is a model as well, you can go ahead and add the type hint to enable the implicit route model binding.

Related

Why Is Laravel Giving Me This Error, and How Do I Fix it? Argument #2 ($post) must be of type App\Models\Post, App\Models\User given

I am trying to use a Gate to see if the currently authenticated user matches the user_id column of the "posts" table.
However, when attempting to use the Gate inside my controller, it is giving me the following error, and I am at a loss.
App\Providers\AuthServiceProvider::App\Providers\{closure}(): Argument #2 ($post) must be of type App\Models\Post, App\Models\User given, called in [path]\vendor\laravel\framework\src\Illuminate\Auth\Access\Gate.php on line 535
Thanks.
My Controller:
class updatePost extends Controller
{
public function updatePost(Request $request, Post $post) {
if (Gate::allows('updatePost', auth()->user(), $post)) {
$post->title = $request->input('title');
$post->body = $request->input('body');
$post->save();
return redirect()->route('readPost', ['id' => $post->id]);
} else {
echo 'ERROR';
}
}
}
My Gate:
Gate::define('updatePost', function (User $user, Post $post) {
return $user->id === $post->user_id;
});
The define callback always receives the logged in user as first parameter followed but the parameters given by allows().
Try this
if (Gate::allows('updatePost', $post)) {
// your code
}

How to show id in Resource Routes url?

Update:
This line of code in the frontend was the culprit:
<inertia-link v-if="options.edit" :href="'/admin/gallery/edit/1'">
I had to change it to:
<inertia-link v-if="options.edit" :href="'/admin/gallery/1/edit'">
to make it comply with the laravel resource format for edit, provided by #Babak.
Original Post:
How would I transform this route in web.php:
Route::get('/admin/gallery/edit/{id}', function ($id) {
$data = Gallery::find($id);
return inertia('backend/cms-gallery-edit', ['data' => $data]);
});
to a resource route with its resource controller function:
Route::resource('/admin/gallery', GalleryController::class);
GalleryController.php:
public function edit($id)
{
$data = Gallery::find($id);
// assign id to end of route
return inertia('backend/cms-gallery-edit', ['data' => $data]);
}
Edit:
I've tried both approaches of #Babak's answer, which work for index and create routes but the edit route still throws a 404. It is the only route encompassing an id.
web.php:
Route::resource('/admin/gallery', GalleryController::class)->only('index', 'create', 'edit');
GalleryController.php:
public function edit($gallery)
{
$data = Gallery::find($gallery);
return inertia('backend/cms-gallery-edit', ['data' => $data]);
}
Inertia passes the id from the frontend via href:
<inertia-link v-if="options.edit" :href="'/admin/gallery/edit/1'">
Browser shows:
GET http://127.0.0.1:8000/admin/gallery/edit/1 404 (Not Found)
There is a fixed structure for laravel resource route method, you can see full list here. For edit page, it will generate something like '/admin/gallery/{gallery}/edit'
You can write it like below:
In your web.php file:
Route::resource('/admin/gallery', GalleryController::class)->only('edit');
And in your controller, name of the resource must be the same as your function's parameter.
public function edit($gallery)
{
$data = Gallery::find($gallery);
// assign id to end of route
return inertia('backend/cms-gallery-edit', ['data' => $data]);
}
Or, you can customize it using parameter method. Refer to here
Route::resource('/admin/gallery', GalleryController::class)->only('edit')->parameters([
'gallery' => 'id'
]);
And your controller
public function edit($id)
{
$data = Gallery::find($id);
// assign id to end of route
return inertia('backend/cms-gallery-edit', ['data' => $data]);
}

Laravel Undefined variable: intent Facade\Ignition\Exceptions\ViewException

I tried looking for all the possible solutions none of it worked and this is very basic trying to send data from a controller to view in Laravel.
Paymentcontroller
public function payment() {
$plans =[
'Basic' => "Monthly"
];
$intent = $user->createSetupIntent();
return view('pages.subscription', compact('intent', 'plans'));
}
PageController
public function index(string $page)
{
if (view()->exists("pages.{$page}")) {
return view("pages.{$page}");
}
return abort(404);
}
View pages.subscription
<div>
{{ $intent }}
</div>
route
Route::get('{page}', ['as' => 'page.index', 'uses' => 'PageController#index']);
Route::get('/subscription', 'PaymentController#payment');
This makes the page work but doesn't display the data
Move Route::get('/subscription', 'PaymentController#payment'); before Route::get('{page}',.... (it should be your last route in the list).
Currently when you call /subscription endpoint you are calling PageController#index, but it doesn't contain logic of your PaymentController#payment and doesn't pass any data to view.

GET parent id in nested resource

Im trying to get all comments under post #{any nos.} , but I'm stuck on how can I get the post_id when I hit the URI below. for example post #1
on GET URI : /posts/1/comments/
on CommentController :
public function actions() {
$actions = parent::actions();
unset($actions['index']);
return $actions;
}
public function actionIndex($post_id)
{
return Comments::find()->where(['post_id' => $post_id])->all();
}
make use of _urlManager in yii2
return [
'class'=>'yii\web\UrlManager',
'enablePrettyUrl'=>true,
'showScriptName'=>false,
'rules'=>[
// url rules
'posts/<post_id:\d+>/comments' => 'posts/index',
]
];

Laravel Error : ErrorException Missing argument 1?

I am using Laravel 4 and I am getting ERROR: when I visit admin/profile/: Missing argument 1 for AdminController::getProfile()
My AdminController code :
public function getProfile($id) {
if(is_null($id)) Redirect::to('admin/dashboard');
$user = User::find($id);
$this->layout->content = View::make('admin.profile', array('user' => $user));
}
My routes.php :
Route::controller('admin', 'AdminController');
My admin/profile (blade) view :
#if(!is_null($user->id))
{{ $user->id }}
#endif
How could I fix this? I want when they go to admin/profile without ($id) to redirect to dashboard.
You told Laravel that your getProfile method has one parameter:
public function getProfile($id) {
}
If you want to a request to succeed, you have to pass it in your URL:
http://appdev.local/admin/profile/1
If you want to see it fail (redirect to dashboard), you'll have to add a default value to your function argument:
public function getProfile($id = null) { ... }
But you better add this value to it anyway, since you can have bots (or even people) trying to access that route without the parameter.
Your view is too generic too, you have to check if your $user is set:
#if(isset($user) && !is_null($user->id))
{{ $user->id }}
#endif
As noted in the comments, the line
if(is_null($id)) Redirect::to('admin/dashboard');
Must have a return:
if(is_null($id)) return Redirect::to('admin/dashboard');
About sharing the user to your layout, the problem is that your getProfile($id) is already passing a $user to your view, so what you could do is to add this to your __construct():
if (Auth::check())
{
$user = Auth::getUser();
View::share('loggedUser', $user);
}
And in your view:
#if(isset($user) && !is_null($user->id))
{{ $user->id }}
#else
{{ $loggedUser->id }}
#endif
About the user not found problem, you have many options, this is one:
public function getProfile($id) {
if (is_null($id))
{
return Redirect::to('admin/dashboard');
}
if ($user = User::find($id))
{
$this->layout->content = View::make('admin.profile', array('user' => $user));
}
else
{
return Redirect::to('admin/dashboard')->withMessage('User not found');
}
Try setting a default null value to $id like this :
public function getProfile($id = null) {
...
}

Categories