Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

ajsmith_codes's avatar

Destroy not working for tasks - TDD

Laravel 7 - I created the Birdboard app from the TDD series. I am trying to add the option to delete a task and am testing first.

I copied the code for deleting projects and changed the info, but I get TypeError : Argument 1 passed to App\Http\Controllers\ProjectTasksController::destroy() must be an instance of App\Task, string given

I created a policy and registered it:

public function delete(User $user, Project $project){

    //check to see if user is the owner of the project
    return $user->is($project->owner);

}

Here is the test:

function test_a_user_can_delete_a_task() {

    $this->withoutExceptionHandling();

    $project = ProjectFactory::withTasks(1)->create();

    $task = factory('App\Task')->create();

    $this->actingAs($project->owner)
        ->delete($project->path() . '/tasks/' . $task->id)
        ->assertRedirect('/projects/');

    $this->assertDatabaseMissing('tasks', $task->only('id'));
}

This is in ProjectTasksController:

public function destroy(Task $task){

    $this->authorize('manage', $task);

    $task->delete();

    return redirect('/projects');

}
0 likes
27 replies
drewdan's avatar

Your controller is saying the information you are passing it does not match what it expects to get.

if you run php artisan route:list can you show me the the output of the route you are trying to hit?

Also,

$this->authorize('manage', $task);

should that not be::

$this->authorize('delete', $task);

As that is the policy method you have shown us?

ajsmith_codes's avatar

@drewdan Thanks for looking at this! I did change manage to delete, but no change. I expect the main issue is keeping that error from showing.

Here is the route list:

+--------+-----------+--------------------------------------+------------------+------------------------------------------------------------------------+--------------+

```+--------+-----------+--------------------------------------+------------------+------------------------------------------------------------------------+--------------+
```|        | GET|HEAD  | /                                    |                  | Closure                                                                | web          |
```|        | GET|HEAD  | api/user                             |                  | Closure                                                                | api,auth:api |
```|        | GET|HEAD  | home                                 | home             | App\Http\Controllers\HomeController@index                              | web,auth     |
```|        | POST      | login                                |                  | App\Http\Controllers\Auth\LoginController@login                        | web,guest    |
```|        | GET|HEAD  | login                                | login            | App\Http\Controllers\Auth\LoginController@showLoginForm                | web,guest    |
```|        | POST      | logout                               | logout           | App\Http\Controllers\Auth\LoginController@logout                       | web          |
```|        | GET|HEAD  | password/confirm                     | password.confirm | App\Http\Controllers\Auth\ConfirmPasswordController@showConfirmForm    | web,auth     |
```|        | POST      | password/confirm                     |                  | App\Http\Controllers\Auth\ConfirmPasswordController@confirm            | web,auth     |
```|        | POST      | password/email                       | password.email   | App\Http\Controllers\Auth\ForgotPasswordController@sendResetLinkEmail  | web          |
```|        | POST      | password/reset                       | password.update  | App\Http\Controllers\Auth\ResetPasswordController@reset                | web          |
```|        | GET|HEAD  | password/reset                       | password.request | App\Http\Controllers\Auth\ForgotPasswordController@showLinkRequestForm | web          |
```|        | GET|HEAD  | password/reset/{token}               | password.reset   | App\Http\Controllers\Auth\ResetPasswordController@showResetForm        | web          |
```|        | POST      | projects                             | projects.store   | App\Http\Controllers\ProjectsController@store                          | web,auth     |
```|        | GET|HEAD  | projects                             | projects.index   | App\Http\Controllers\ProjectsController@index                          | web,auth     |
```|        | GET|HEAD  | projects/create                      | projects.create  | App\Http\Controllers\ProjectsController@create                         | web,auth     |
```|        | DELETE    | projects/{project}                   | projects.destroy | App\Http\Controllers\ProjectsController@destroy                        | web,auth     |
```|        | GET|HEAD  | projects/{project}                   | projects.show    | App\Http\Controllers\ProjectsController@show                           | web,auth     |
```|        | PUT|PATCH | projects/{project}                   | projects.update  | App\Http\Controllers\ProjectsController@update                         | web,auth     |
```|        | GET|HEAD  | projects/{project}/edit              | projects.edit    | App\Http\Controllers\ProjectsController@edit                           | web,auth     |
```|        | POST      | projects/{project}/invitations       |                  | App\Http\Controllers\ProjectInvitationsController@store                | web,auth     |
```|        | POST      | projects/{project}/tasks             |                  | App\Http\Controllers\ProjectTasksController@store                      | web,auth     |
```|        | DELETE    | projects/{project}/tasks/{task}      |                  | App\Http\Controllers\ProjectTasksController@destroy                    | web,auth     |
```|        | PATCH     | projects/{project}/tasks/{task}      |                  | App\Http\Controllers\ProjectTasksController@update                     | web,auth     |
```|        | GET|HEAD  | projects/{project}/tasks/{task}/edit |                  | App\Http\Controllers\ProjectTasksController@edit                       | web,auth     |
```|        | GET|HEAD  | register                             | register         | App\Http\Controllers\Auth\RegisterController@showRegistrationForm      | web,guest    |
```|        | POST      | register                             |                  | App\Http\Controllers\Auth\RegisterController@register                  | web,guest    |
```+--------+-----------+--------------------------------------+------------------+------------------------------------------------------------------------+--------------+
drewdan's avatar

So you are hitting this route? projects/{project}/tasks/{task}

First thing, I am fairly certain that in your controller you will need to type hint project too

public function delete(Project $project, Task $task) {
    //stuff in there
}

Laravel will be expecting those to be there.

It might be worth dumping the route you are trying to hit:

dd($project->path() . '/tasks/' . $task->id);

just to see if the route is getting the information is requires.

ajsmith_codes's avatar

@drewdan I did check the path, just like you suggested. It's nice to know I'm doing the troubleshooting correctly (at least part of it). :)

Here is what dumps: "/projects/1/tasks/2"

I added Project to delete and still got the same error, but now with 2 arguments:

TypeError : Argument 2 passed to App\Policies\TaskPolicy::delete() must be an instance of App\Project, instance of App\Task given, called in C:\xampp\php\crm_clone\vendor\laravel\framework\src\Illuminate\Auth\Access\Gate.php on line 706 C:\xampp\php\crm_clone\app\Policies\TaskPolicy.php:13

ajsmith_codes's avatar

Route::delete('/projects/{project}/tasks/{task}', 'ProjectTasksController@destroy');

drewdan's avatar

Ah!

Sorry, I made a mistake! in my code snippet I put delete, it should have read:

public function destroy(Project $project, Task $task) {

My apologies!

drewdan's avatar

Right one last thing, in your policy, we need to tell it about the project

Your policy wants the project, you have typehinted the project, but you have given it a task in your controller

$this->authorize('manage', $task);

If you give it the project you just type hinted

$this->authorize('delete', $project);

Laravel should be a little happier now

ajsmith_codes's avatar

@drewdan Do I add the second line you wrote or change $task to $project? And this is in the ProjectTasksController, correct?

drewdan's avatar

This is in the ProjectTasksController yes. And replace the first line with the second.

$this->authorize('delete',  $project);

Your controller will look a little like:

public function destroy(Project $project, Task $task) {

    $this->authorize('delete', $project);

    $task->delete();

    return redirect('/projects');

}
ajsmith_codes's avatar

@drewdan Yay! We changed the error! That's progress. Now I get: Illuminate\Auth\Access\AuthorizationException : This action is unauthorized.

I don't want an unauthorized user to delete a task, but I should be allowed to since I'm a user. I thought that this line would do it:

    $this->actingAs($project->owner)
        ->delete($project->path() . '/tasks/' . $task->id)
        ->assertRedirect('/projects/');
drewdan's avatar

Excellent, we are reaching your policy! Your policy does look ok to me. I would put a dd in your policy to see what it is receiving and see if it matches up with what you think it should be getting. So in your policy, I would

dd($user, $project);

see if its what you think it should be. If won't be of course, because the policy is failing, but, it should give you an idea of where it is going wrong :)

ajsmith_codes's avatar

@drewdan I added it:

public function delete(User $user, Project $project){
    dd($user, $project);

    //check to see if user is the owner of the project
    return $user->is($project->owner);

}

But can't get it to give any result. Sounds like it's not hitting the policy. Could it be hitting my ProjectPolicy?

Here is the code for that one:

public function manage(User $user, Project $project){

    //check to see if user is the owner of the project
    return $user->is($project->owner);

}
drewdan's avatar

Sounds like the next step I would take. Certainly feels like its hitting the wrong policy, have you got a delete method on your project policy? Put a DD in and see, if you hit it, you'll know where it is going

drewdan's avatar

In your task policy create a method like this

public function delete(User $user, Task $task) {
	dd('hit this', $user, $task);
}

And see if you can hit that

ajsmith_codes's avatar

@drewdan I added that to both policies, but the only one that changed was the ProjectPolicy. Here is the error I get:

TypeError : Argument 2 passed to App\Policies\ProjectPolicy::delete() must be an instance of App\Policies\Task, instance of App\Project given, called in

ajsmith_codes's avatar

@drewdan This is what I get in the browser:

C:\xampp\php\crm_clone\vendor\laravel\framework\src\Illuminate\Auth\Access\Gate.php on line 706

drewdan's avatar

at the top, import your Task probably something like

use App\Task;
ajsmith_codes's avatar

@drewdan I added that, but it's still looking in the wrong policy:

"App\Policies\ProjectPolicy::delete() must be an instance of App\Policies\Task, instance of App\Project given"

drewdan's avatar

Can you post the method in your controller again please?

ajsmith_codes's avatar

@drewdan Sure!

public function destroy(Project $project, Task $task){

    $this->authorize('delete', $project);


    $task->delete();

    return redirect('/projects');

}
ajsmith_codes's avatar

@drewdan I got it! After all the changes, I change 'delete' back to 'manage' and it worked. However, now I have a redirect issue. I will work on that and let you know if I can't get it. Thanks!

ajsmith_codes's avatar

@drewdan Ok, after getting my test green, I can successfully delete a task. However, after it redirects, I get this error on the show.blade.php (project) page:

Trying to get property 'body' of non-object (View: C:\xampp\php\crm_clone\resources\views\projects\activity\created_task.blade.php)

I can't remember what that error means.

EDIT: Project doesn't have 'body'. Only tasks do...

drewdan's avatar

body? Would that be an attribute on your model? Can you post your show.blade.php? And also post the relevant part of the controller which loads this view?

ajsmith_codes's avatar

@drewdan I tracked it to the activity tracking. It's a separate issue (I think). Do you want me to start a new post?

drewdan's avatar

Might be a good idea, will help people who are searching the forum find relevant posts :)

Please or to participate in this conversation.