payello's avatar

Trying to get property of non-object - Laravel Form

I am creating a form with a many-many relationship. I have a posts table and an activities table. There is a many to many link using pivot table. I am creating a form to add one or more activities to the posts. I am receiving an 'ErrorException' - Trying to get property of non-object. I cannot understand why this is not working.

I would be grateful for any assistance you can offer me.

My relevant code is below.

//Posts/create.blade.php

{!!Form::open(['action' => 'PostController@store','method' => 'POST', 'class'=>'form-group'])!!}
  {{Form::bsText('title','',['placeholder' => 'Trip Name'])}}
  {{Form::bsTextarea('body','',['placeholder' => 'Trip Description'])}}
  {{Form::bsSubmit('submit')}}



  {{Form::label('activities', 'Activity:') }}
  <select class="form-control select2-multi" name="activities" multiple="multiple">
    @foreach($activities as $activity)
    <option value="{{ $activity->id }}">{{ $activity->activity_name}}
    </option>
    @endforeach

  </select>

{!! Form::close() !!}


// PostsController

public function create()
    {
      $activities = Activity::all();
        return view('posts.create')->withActivities($activities);
        $posts = Post::all();

    }

    public function store(Request $request)
    {
        // Create a new post using the request data
        // Save it to the database
        $this->validate(request(), [
            'title' => 'required',
            'body' => 'required',

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



        // And then redirect to somewhere in  application
        return redirect()->route('posts.show', $post->id);
    }
0 likes
22 replies
sujancse's avatar

Are you getting values in $activities in create page trying dd() or dumping it.

tykus's avatar

There is nothing in your code what would appear to give rise to that error, can you post the entire stack trace??

Aside: 'activity_id' => id() what is this id() method???

payello's avatar

Thank you for your reply @st8113 - the dd($activities) function does collect the data. id and activity_name are both fields within the activities table.

sujancse's avatar

@payello Could you show me the dd() result? I think one of your activity doesn't contains both id and activity_name.

payello's avatar
Collection {#214 ▼
  #items: array:2 [▼
    0 => Activity {#215 ▼
      #table: "activities"
      #fillable: array:1 [▶]
      #guarded: []
      #connection: "mysql"
      #primaryKey: "id"
      #keyType: "int"
      +incrementing: true
      #with: []
      #withCount: []
      #perPage: 15
      +exists: true
      +wasRecentlyCreated: false
      #attributes: array:4 [▼
        "id" => 1
        "activity_name" => "Skiing"
        "created_at" => "2017-09-11 13:15:37"
        "updated_at" => "2017-09-11 13:15:37"
      ]
      #original: array:4 [▼
        "id" => 1
        "activity_name" => "Skiing"
        "created_at" => "2017-09-11 13:15:37"
        "updated_at" => "2017-09-11 13:15:37"
      ]
      #casts: []
      #dates: []
      #dateFormat: null
      #appends: []
      #events: []
      #observables: []
      #relations: []
      #touches: []
      +timestamps: true
      #hidden: []
      #visible: []
    }
    1 => Activity {#216 ▶}
  ]
}
payello's avatar

This is my complete code:


// Activity Controller

<?php

namespace App\Http\Controllers;

use App\Activity;

use Illuminate\Http\Request;


class ActivityController extends Controller
{
    protected $fillable = [
      'activity_name'
    ];

    public function __construct(){
      $this->middleware('auth');
    }

    public function posts()
    {
        return $this->belongsToMany('App\Post')->using('App\activityPost')->withTimestamps();

    }
    public function index(Activity $activity)
    {
      $posts = $activity->posts;
      return view('posts.index', compact('posts'));
    }

    public function edit(Activity $activity)
    {

        $posts = App\Post::get()->pluck('title','body','id')->sortBy('title');
        return view('activities.edit', compact('activities', 'posts'));
    }
    public function update(Request $request, Activity $activity)
    {

        $activity->update($request->all());
        $activity->posts()->sync($request->posts);
        return redirect ('posts/create');
    }

    public function create()
    {
        return view('activities.create');
    }
/** To submit data */
    public function store(Request $request)
    {

      $activity = new Activity;
      $activity->activity_name = request('activity_name');
      $activity->save();

      return view('activities/index');


      $this->validate(request(), [
        'activity_name'=>'required',
        'body'=> 'required']);

      Comment::create([
        'body'=> request('body'),
        'post_id'=>$post->id,
        'user_id'=>auth()->id()
      ]);

      return back();

    }

    public function show(Activity $activity)
    {
        return view ('activities.activity', ['Activity'=>$activity]);
    }




}

// PostController

<?php

namespace App\Http\Controllers;

use App\Post;
use Carbon\Carbon;
use Illuminate\Http\Request;
use App\Activity;


class PostController extends Controller
{

    public function __contruct()
    {
        $this->middleware('auth')->except(['index', 'show']);
    }
    public function index()
    {
        $posts = Post::latest()->get();

        return view('posts.index', compact('posts'));
    }

    public function show(Post $post)

    {
        return view('posts.show', compact('post'));
    }

    public function create()
    {
      $activities = Activity::all();
        return view('posts.create')->withActivities($activities);
        $posts = Post::all();

    }

    public function store(Request $request)
    {
        // Create a new post using the request data
        // Save it to the database
        $this->validate(request(), [
            'title' => 'required',
            'body' => 'required',

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

    $activities = Activity::all();

        // And then redirect to somewhere in  application
        return redirect('/');
    }


        public function activities()
    {
        return $this->belongsToMany('App\Activity')->using('App\activityPost');
    }
        public function update(Request $request, Post $post)
    {
        $post->update($request->all());
        $post->activities()->sync($request->activities);
        return redirect('post');
    }

    public function edit(Post $post)
    {
      return view('posts.edit', compact('post'));
    }


}

//Model - Activity.php

<?php

namespace App;


class Activity extends Model
{
    protected $table = 'activities';
    protected $fillable = ['activity_name'];

    public function posts()
    {
        return $this->belongsToMany('App\Post');
    }
    public function index()
    {
        $activities = Activity::orderBy('activity_name', 'asc')->paginate(10);
        return view('activities.index', ['activities'=>$activities]);
    }
    public function store()
    {
        return $this->belongsToMany('App\Post');
    }


    public function getRouteKeyName()
    {
        return 'activity_name';
    }

    public function create()
    {
        return view ('activities.create');
    }


}

// Model - Post.php 

<?php

namespace App;

class Post extends Model

{


    public function countries()
    {
        return $this->hasMany(Country::class);
    }
    public function comments()
    {
        return $this->hasMany(Comment::class);
    }
    public function user()
    {
        return $this->belongsTo(User::class);
    }
    public function addComment($body)
    {
        $this ->comments()->create(compact('body'));
    }
    public function activities()
    {
        return $this->belongsToMany('App\Activity');
    }
    

}

// pivot table
    public function up()
    {
        if(!Schema::hasTable('activity_post')) {
            Schema::create('activity_post', function (Blueprint $table) {
                $table->integer('activity_id')->unsigned()->index();
                $table->foreign('activity_id')->references('id')->on('activities')->onDelete('cascade');

                $table->integer('post_id')->unsigned()->index();
                $table->foreign('post_id')->references('id')->on('posts')->onDelete('cascade');

            });
        }
    }

// Activities Table
class CreateActivitiesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        if(!Schema::hasTable('activities')) {
            Schema::create('activities', function (Blueprint $table) {
                $table->increments('id');
                $table->string('activity_name');
                $table->timestamps();
            });
        }
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('activities');
    }
}
//Posts table
class CreatePostsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
            if(!Schema::hasTable('posts')){
            Schema::create('posts', function (Blueprint $table) {
                $table->increments('id');
                $table->integer('user_id');
                $table->string('title');
                $table->text('body');
                $table->timestamps();
                });
            }
    }


    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('posts');
    }
}



// posts/create.blade.php

@extends('layouts.master')
{!! Html::style('css/select2.min.css') !!}


@section('content')

<div class="col-sm-8 blog-main">
@if(Auth::check())
<h1>Create new Trip</h1>

<hr>
<div class="form-group">


{!!Form::open(['action' => 'PostController@store','method' => 'POST', 'class'=>'form-group'])!!}
  {{Form::bsText('title','',['placeholder' => 'Trip Name'])}}
  {{Form::bsTextarea('body','',['placeholder' => 'Trip Description'])}}
  {{Form::bsSubmit('submit')}}



  {{Form::label('activities', 'Activity:') }}
  <select class="form-control select2-multi" name="activities" multiple="multiple">
    @foreach($activities as $activity)
    <option value="{{ $activity->id }}">{{ $activity->activity_name}}
    </option>
    @endforeach

  </select>

{!! Form::close() !!}




    @endif
    @include('layouts.errors')
</div>

@if(Auth::guest())
<a href="/login" class="btn btn-info">You must login to make amendments</a>
@endif
</div>

  {!! Html::script('js/select2.min.js') !!}
  <script type="text/javascript">
  $('.select2-multi').select2();
  </script>
@endsection

payello's avatar

I realise that the 'activity_id' => id() is an error and have removed it

tykus's avatar

Can you not check your logs to see where the Exception is being thrown?

payello's avatar

Thanks @tykus

ErrorException Trying to get property of non-object (View: /home/vagrant/Code/holidaysite/resources/views/posts/create.blade.php)

It is showing that it is on line 30 which is on of the form in the create blade

payello's avatar

Unfortunately I still haven't been able to solve the problem

tykus's avatar

Which is line 30? I can see nothing in the view code you have posted to give rise to the error you describe; it is not the most logic template I have ever seen however!

payello's avatar
  {{Form::label('activities', 'Activity:') }}
  <select class="form-control select2-multi" name="activities" multiple="multiple">
    @foreach($activities as $activity)
    <option value="{{ $activity->id }}">{{ $activity->activity_name}}
    </option>
    @endforeach

  </select>

{!! Form::close() !!}

The error is showing at the </select> tag. This is in the posts/create.blade.php file

payello's avatar

Sorry, I am new to posting in forums, which would explain why it is a bit confusing

mattsplat's avatar

Did you dd($activities) in the controller or the view?

wickley's avatar

Ignore the line 30 reference. Your problem is almost certainly here:

{{ $activity->id } and {{ $activity->activity_name}}

That's the only code I see in your view that would give an error of "Trying to get property of non-object".

Remove the @foreach temporarily from the view page and do a {{ dd($activities) }} in place of that as mattsplat mention above.

payello's avatar

This was the result from {{ dd($activities) }} on my create.blade.php

Collection {#267 ▼ #items: array:2 [▼ 0 => "Skiing" 1 => "Climbing" ] }

payello's avatar

When I isolate the foreach loop I receive the 'Trying to get property of non-object' error again. So I know that it is the error. But I am not sure why. I get the array as stated above when I dd. But I cannot loop over this collection.

sujancse's avatar

Your collection is returning only activity_name that is why you are not able to access id and activity_name. They doesn't exist in your collection. Try updating your controller method like

public function create()
{
        $activities = Activity::all();
        return view('posts.create', compact('activities'));
 }
payello's avatar

That still gives the same error message unfortunately

sujancse's avatar

Make sure that the data is coming from the controller you showed us

wickley's avatar
wickley
Best Answer
Level 3

Collection {#267 ▼ #items: array:2 [▼ 0 => "Skiing" 1 => "Climbing" ] }

The problem is that $activities is coming through as a simple array with no keys, just values, thus {{ $activity->id } and {{ $activity->activity_name}}, which reference nested keys from an expected object does not exist in the $activities value.

Not sure why that's the case here as your controller seems correct and I don't see where it's converting to an array. Your first dd from inside the controller shows the correct object for Activity with id, activity_name, created_at and updated_at, yet your dd from the view shows a simple array.

In any case, here's a work around solution that's a bit more code but simple enough. Note that I coded this from memory, not in an editor, so there might be some minor syntax or other issues.

Try something like this in your PostController:

public function create()
{
    $activities = Activity::all();
    $activitiesArray = [];
    foreach($activities as $activity) {
        $activitiesArray[$activity->id] = $activity->activity_name;
    }
        return view('posts.create')->with('activitiesArray', $activitiesArray);
}

Then in posts/create.blade.php change the @foreach section to:

@foreach($activitiesArray as $key => $activity)
    <option value="{{ $key }}">{{ $activity }}
    </option>
@endforeach

Please or to participate in this conversation.