J. Robinson J. Robinson - 30 days ago 9
HTML Question

YouTube Vid Attached - How do you remove an associated category_id from 'posts' table upon deletion of category in 'categories' table in Laravel?

Question semi-solved/narrowed down. Read the EDIT/UPDATE.

So, I have a Blog App... in that blog app i have two routes...

blog.index
and
blog.single
. The index lists the blog posts and links to the
blog.single
view and passes in the slug to identify the specific post. I'm attaching a YouTube video of the problem with me narrating... I've never come across this issue before.

Basically if I click on the "read more" button on the index page, only SOME posts are displayed correctly on the single page... However some posts are giving me the following error.

Trying to get property of non-object (View: /home/vagrant/sites/blog/resources/views/blog/single.blade.php)


Here is my code for
single.blade.php
:

@extends('main')

@section('title', $post->title)

@section('content')

<div class="row">
<div class="col-md-8 col-md-offset-2">
<h1>{{ $post->title }}</h1>
<h5>Published: {{ date('M j, Y', strtotime($post->created_at)) }}</h5>
<p>{{ $post->body }}</p>
<hr>
<p>Posted In: {{ $post->category->name }}</p>
</div>
</div>

@endsection


I just added a new comments migration and controller, and I have edited the Post model to this:

namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
// Access to category model
public function category() {
return $this->belongsTo('App\Category');
}

// Access to Tags Model
public function tags() {
return $this->belongsToMany('App\Tag');
}

// Access to Comments Model
public function comments() {
return $this->hasMany('App\Comment');
}

}


And here is my blog controller code here:

use Illuminate\Http\Request;

use App\Post;

class BlogController extends Controller
{

// Get the Index of Blog Posts
public function getIndex() {
// Grab all of the posts from the DB
$posts = Post::orderBy('created_at', 'desc')->paginate(10);

// Return the Index View
return view('blog.index')->withPosts($posts);
}


// Get Single Post
public function getSingle($slug) {
// Grab the post via slug
$post = Post::where('slug', '=', $slug)->first();

// Return the Via Pass in Post Object
return view('blog.single')->withPost($post);
}

}


In my youtube video i give you a brief overview of the database, and the code. Its about 6 minutes long.

Youtube video here: https://youtu.be/F78QzqQ4rts

Youtube Tutorials I'm following here: https://www.youtube.com/watch?v=z-KyDpG8j34&index=47&list=PLwAKR305CRO-Q90J---jXVzbOd4CDRbVx

EDIT/UPDATE:

So i've narrowed down the issue to this line of code... which sometimes works and then again sometimes doesn't...

<p>Posted In: {{ $post->category->name }}</p>


So, i thought to myself, lets take a look at the Post Model to see if category is defined correctly so that we can access it.

Here is my Post Model for Category...

// Access to category model
public function category() {
return $this->belongsTo('App\Category');
}


Everything looked good, and so I went directly to the database using SQL Pro to see what category is on the posts that work, and what categories are on the post that dont work. This is defined by the 'category_id' column in the 'posts' table.

I noticed that the posts that worked used category id '2'. The other posts that didn't work, had a category OTHER THEN '2'. So I went to my 'categories' table, and looked to see if there even was a category other then 2. There wasn't.

Somehow long the way, when deleting the category, I wasn't removing the association in the posts table. I'm not sure how to upon deletion of the category from the categories table to also wipe clean all references to the category id in the posts table.

Here is my Migration up function for the categories table creation

public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
}


Here is the up function for adding the category_id column to the 'posts' table.

Schema::table('posts', function (Blueprint $table) {
// Add category id to posts table
$table->integer('category_id')->nullable()->after('slug')->unsigned();
});


And here is my destroy function for the category in the category controller.

public function destroy($id)
{
$category = Category::find($id);

$category->delete();

Session::flash('success', 'Deleted the Category');

return redirect()->route('categories.index');
}


So, with this information you should be able to help... How do I get rid of the association in the posts table upon deletion of the category in the categories table?

Here is a youtube video explaining the narrowed down question:

https://www.youtube.com/watch?v=LGP14VH6miY

Answer Source
$table->integer('category_id')->nullable()->after('slug')->unsigned();

This migration suggests that your post may or may not belong to category since category_id is a nullable field.

So {{ $post->category->name }} won't always work because their may be certain posts that don't belong to any category.

Two ways to solve this:

  1. Remove nullable if you want to make sure that every post belongs to a category OR
  2. Alter {{ $post->category->name }} to {{ $post->category_id ? $post->category->name : "" }}

As to how to get rid of the association in the posts table, there are 2 options:

  1. If you want to delete all posts related to a category when the category is deleted, use $category->posts()->delete();
  2. If you want to just dissociate the posts, just use $category->posts()->update(['category_id' => null]);