3
votes

I am trying to insert a blog post on db, I do have two tables posts and tags tables. When I insert the create the post I want to be able to insert the data from the form in those two different tables.

create.blade.php;

<div class="account_grid">

<div class="col-md-6 login-right wow fadeInRight col-md-offset-3" data-wow-delay="0.4s">
    <h3>CREATE A BLOG POST</h3>
    <p>Please fill out the required fields *</p>
    <form method="post" action="/posts"  enctype="multipart/form-data">
         {{csrf_field()}}
        <div>
            <span>Title:<label>*</label></span>
            <input type="text" id="title" name="title"  > 
        </div>
        <div>
            <span>Body<label>*</label></span>
            <textarea id="body" name="body" rows="14"  ></textarea>
        </div>
        <div>
            <span>Tags:<label>*</label></span>
            <input type="text" id="tags" name="tags">
        </div>
        <div>
            <span>Image<label>*</label></span>
            <input type="file" name="image" id="image"  >
        </div>
        <input type="submit" value="Publish">

    </form>

@include('layouts.errors')
</div>  
<div class="clearfix"> </div>
</div>

On my route file I have the path that leads to PostsController.php which has a store method like below:

PostsController.php

    public function store(Request $request){

        $this->validate($request, [

            'title' =>'required|max:48',
            'body'=>'required',
            'image'=>'required',
            'tags' =>'required|max:200'
        ]);

        $post = new Post;

        $destination ='uploads';
        $image = $request->file('image');
        $filename = $image->getClientOriginalName();
        $image->move($destination, $filename);
        $location=$destination.'/'.$filename;
        $tags = request('tags');


           Post::create([
            'title'=>request('title'),
            'body' =>request('body'),
            'user_id'=>auth()->id(),
            'image' =>$destination.'/'.$filename

        ]);

        $tag = new Tag;

        Tag::create([

            'name' => $tags
        ]);

        return redirect('/blog');
    }
}

The thing is that when I call the method I want the form data to be saved on two different tables, I have tried like below but I am getting ERROR:

MassAssignmentException in Model.php line 232: name

I did research the issue but no luck; and yes I do have the 'name' listed in the protected $fillable array. Any suggestion on how to store data in two different tables or what type of relationship should i use.

On post.php model i do have a relationship specified. Tags belongsToMany as well as on my tag.php model Post belongsToMany

p.s New to Laravel.

tag.php model:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Tag extends Model
{
    //

        public function posts(){

        return $this->belongsToMany(Post::class);
    }

    public function getRouteKeyName(){

        return 'name';

    }
}

Post.php model:

<?php

namespace App;
use Carbon\Carbon;
class Post extends Model
{

    public function comments(){

        return $this->hasMany(Comment::class);
    }

    public function addComment($body, $name, $email, $user_id){

        $this->comments()->create(compact('body','name','email', 'user_id'));
    }

    public function user(){ // $comment->user->name

        return $this->belongsTo(User::class);
    }

    public function scopeFilter($query, $filters){

        if($month =$filters['month']){
//            
            $query->whereMonth('created_at', Carbon::parse($month)->month);
        }

        if($year = $filters['year']){

            $query->whereYear('created_at',$year );
        }
    }

    public static function archives(){
        return static:: selectRaw('year(created_at)year, monthname(created_at)month, count(*) published')
       ->groupBy('year','month')
       ->orderByRaw('min(created_at) desc')
       ->get()
       ->toArray();
    }

    public function tags(){

        return $this->belongsToMany(Tag::class);
    }



}
4
Can you run dd($tags); and post the result. I need to see the tag format you pass from the form. Also you shouldn't create tags like that when you have a relationship. Share your Post and Tag model along with the table structure. I'll show you how to do this right. - Sandeesh
I have done dd I get the tags as a string (thats how I want to insert it later on I will str_replace) i just need to get it right for now. Yes I will add them. - Leo
Just share the value please. You're working with relationships here, so you need to split the tags properly and then create them and attach it to the post. - Sandeesh
check it now. they are there - Leo
The models look fine except you're missing the $fillable property. Without which your create call on model won't work. Did you remove it while posting or do you not have it in your model? Also share the value of the tag field coming from the form. - Sandeesh

4 Answers

4
votes

Based on the comments and discussion you have a couple of issues. The original MassAssignmentException was due to the fact that you have a custom base model in which you define a single $fillable property for all the models. But you still referenced the default Eloquent model when extending your Tag model.

Then the next issue would be attaching the tags to the post. You're passing a space delimited tag value and you're planning to separate them when accessing. That's not how tags work when you use many-to-many relationship. You need to split the tags up before storing them and attach each one to the post.

public function store(Request $request)
{
    $this->validate($request, [
        'title' => 'required|max:48',
        'body' => 'required',
        'image' => 'required',
        'tags' => 'required|max:200'
    ]);

    $destination = 'uploads';
    $image = $request->file('image');
    $filename = $image->getClientOriginalName();
    $image->move($destination, $filename);
    $location = $destination . '/' . $filename;

    $post = Post::create([
        'title' => request('title'),
        'body' => request('body'),
        'user_id' => auth()->id(),
        'image' => $location
    ]);

    $tags = explode(' ', request('tags'));

    $tagInstances = [];

    foreach($tags as $tag) {
        $tagInstances[] = new Tag(['name' => $tag]);
    }

    $post->tags()->saveMany($tagInstances);

    return redirect('/blog');
}
1
votes

I solve this exception and this exception throws when you have not define $table and $fillable in your each model separately.

protected $table = 'table_name';

protected $fillable = [fields which you define in your table];

visit https://laravel.com/docs/5.0/eloquent#mass-assignment then you can get clear understanding about this

0
votes

Just declare Protected $fillable =['column 1','column 2'];

$fillable variable use for create method for insterting data. If you are using create method to insert data then you must specify $fillable variable in model class

In $fillable variable, you specify specific column which you want to allow to insert data in table

I think your issue in

  1. Either you are not declare $fillable variable or
  2. You are not specify column in $fillable which you want to insert.
0
votes

Step 1: Check your model and database. See the Tag struct table, if it has the column name.

Step 2: To insert data with Eloquent::create you need to create one variable called fillable, in which you pass the fields that you want created in your table. Look at the example:

class Flight extends Model
{
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = ['name'];
}

With that you can insert in your database, you can use other approach to insert which goes something like this

$your_table = new YourTable();
$your_table->attr = "hello world";
$your_table->save();

Also, you don't need to create the variable new Post and after call Post::create. You can call only Post::create.

See the Laravel Eloquent doc: https://laravel.com/docs/5.4/eloquent