Passing data through pivot tables? - php

I have three tables, the activity, the category and the activity_categories table.Each activity may belong to many categories therefore the category_id and activity_id are saved in activity_categories.
I am trying to get only one category per product, because to display use one category image per activity but on search I have to show them in all belonging categories.I have created my models as follow:
class Activity extends Model
{
protected $table = "activities";
public function category()
{
return $this->belongsToMany('App\Category','activity_categories');
}
}
//Controller
public function userActivities()
{
$user_id = Auth::user()->id;
$activities = Activity::all()->where('user_id', $user_id);
return view('user_profile.activities', compact( 'activities' ));
}
//View
#foreach($activities as $activity)
<div class="col-lg-4 col-md-4 col-xs-12" id="profile-card">
<div class="widget-head-color-box navy-bg p-lg text-center"
style="background-image: url('{{asset('/images/categories/'.$activity->category->first()->image)}}')">
<img src="/storage/profile/{{Auth::user()->image}}" class="img-small-profile" alt="profile">
<button id="heart-favorite" class="btn btn-danger btn-circle btn-outline"
type="button"><i
class="fa fa-heart"></i></button>
</div>
<div class="widget-text-box">
<h3 class="media-heading m-t-md"><b>{{$activity->title}}</b></h3>
<h5 class="media-heading m-t-md" style="text-align: justify">
{{$activity->description}}<br><br>
</h5>
</div>
</div>
#endforeach
When i use dd($activity->category->first()->image) it shows the data but when i place the same in the view id shows the error "Trying to get property of non-object"

Related

Trying to get property of non-object after passing an array

I have a users table and a photos table. The photos table has been linked to the users table (and some other tables) through imageable_id and imageable_type. Everything's working fine for that.
Now I wanted to return an array to a view that contains: user's name, user's email, user's desc, and user's image path (which is from the photos table).
What I did was I created an array that holds a collection of arrays from each user's data, and then passed that array to the view:
$user_admins = array();
$admin_id = 1;
$admins = User::where('role_id', $admin_id)->orderBy('name', 'asc')->get();
foreach($admins as $admin)
{
$photo = Photo::where('imageable_id', $admin->id)->where('imageable_type', 'App\User')->first();
$admin_data = array('name'=>$admin->name, 'email'=>$admin->email, 'desc'=>$admin->desc, 'path'=>$photo->path);
array_push($user_admins, $admin_data);
}
// return $user_admins;
//Return View
return view('pages/home_admin', compact('user_admins'));
However on the view page, I get a Trying to get property of non-object that points out to my:
<h5 class="card-title">{!!$admin->name!!}</h5>
How can I access those user's data on my view?
Thanks a lot!
Update
I also tried:
foreach($admins as $admin)
{
$admin_data['name'] = $admin['name'];
$admin_data['email'] = $admin['email'];
$admin_data['desc'] = $admin['desc'];
$photo = Photo::where('imageable_id', $admin->id)->where('imageable_type', 'App\User')->first();
$admin_data['path'] = $photo['path'];
// $admin_data = array('name'=>$admin->name, 'email'=>$admin->email, 'desc'=>$admin->desc, 'path'=>$photo->path);
array_push($user_admins, $admin_data);
}
// return $user_admins;
//Return View
return view('pages/home_admin', compact('user_admins'));
Still got the same error :<
View's code:
#foreach ($user_admins as $admin)
<div class="card text-center shadow-sm ml-3" style="width: 18rem;">
<div class="card-body">
<img src="../user_images/img_defaultprofile.png" class="mb-3" style="height: 10vh;" alt="" srcset="">
<h5 class="card-title">{!!$admin->name!!}</h5>
<h6 class="card-subtitle mb-2 text-muted">{!!$admin->email!!}<h6>
<p class="card-text">{!!$admin->desc!!}</p>
View Profile
</div>
</div>
#endforeach
You can handle it by defining relationship between user and photo, On your user model define a relationship with photo model
public function photo()
{
return $this->hasOne('App\Photo','imageable_id');
}
Then on your controller
$user_admins = User::where('role_id', $admin_id)->orderBy('name', 'asc')->get();
return view('pages/home_admin', compact('user_admins'));
As the relationship has been defined on user model you can retrieve the photo and user data as follows on view
#foreach ($user_admins as $admin)
<div class="card text-center shadow-sm ml-3" style="width: 18rem;">
<div class="card-body">
<img src="{!!$admin->photo->path!!}" class="mb-3" style="height: 10vh;" alt="" srcset="">
<h5 class="card-title">{!!$admin->name!!}</h5>
<h6 class="card-subtitle mb-2 text-muted">{!!$admin->email!!}<h6>
<p class="card-text">{!!$admin->desc!!}</p>
View Profile
</div>
</div>
#endforeach
So the error message is saying Trying to get property of non-object. That means, you are trying to access property of a variable which is not an object but something else. You are getting this error because, the variable you are passing $user_admins is an array but you are trying to access it as an object.
How to access an array? This should be the your code in view:
#foreach ($user_admins as $admin)
<div class="card text-center shadow-sm ml-3" style="width: 18rem;">
<div class="card-body">
<img src="../user_images/img_defaultprofile.png" class="mb-3" style="height: 10vh;" alt="" srcset="">
<h5 class="card-title">{!!$admin['name']!!}</h5>
<h6 class="card-subtitle mb-2 text-muted">{!!$admin['email']!!}<h6>
<p class="card-text">{!!$admin['desc']!!}</p>
View Profile
</div>
</div>
#endforeach

Laravel Collection get one of values by key

I'm new to Laravel and I'm trying to get one of the values in one collection by one ID retrieved from another collection.
My function returns 2 Collections:
public function index()
{
$category = BlogCategory::all(['id', 'name']);
$post = BlogPost::orderBy('id', 'desc')->take(14)->get();
return view('blog.index', ['posts' => $post], ['categories' => $category]);
}
In a foreach loop I'm getting values from collections:
#foreach($posts as $post)
#if($loop->iteration > 2)
<div class="col-sm-6 col-md-3 d-flex justify-content-center other-post">
<a href="#">
<img src="#" alt="">
<p class="post-category">{{ $categories->get($post->category_id) }}</p>
<h5 class="post-title">{{ $post->title }}</h5>
</a>
</div>
#endif
#endforeach
I'm partially getting the result as you can see in the image below, but I want to get only the name.
Here is the code that I'm trying to figure out
{{ $categories->get($post->category_id) }}
If there is a better or correct way to do it, let me know.
Blog Posts migration:
public function up()
{
Schema::create('blog_posts', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('title');
$table->longText('content');
$table->mediumText('slug');
$table->bigInteger('author_id')->unsigned();
$table->bigInteger('category_id')->unsigned();
$table->timestamps();
$table->foreign('author_id')->references('id')->on('blog_authors');
$table->foreign('category_id')->references('id')->on('blog_categories');
});
}
You should put in place the relationships between BlogPost and BlogCategory models, seen that you already have a category_id field in BlogPost model, i.e.:
in BlogPost Model:
public function category(){
return $this->belongsTo(\App\BlogCategory::class);
}
in BlogCategory Model:
public function posts(){
return $this->hasMany(\App\BlogPost::class);
}
Next you can eager load categories with the $posts in your controller with only two queries:
public function index()
{
$posts = BlogPost::with('category')->orderBy('id', 'desc')->take(14)->get();
return view('blog.index', compact('posts'));
}
Then in your view you can access each $post->category object directly because eager loaded in the controller:
#foreach($posts as $post)
#if($loop->iteration > 2)
<div class="col-sm-6 col-md-3 d-flex justify-content-center other-post">
<a href="#">
<img src="#" alt="">
<p class="post-category">{{ $post->category->name }}</p>
<h5 class="post-title">{{ $post->title }}</h5>
</a>
</div>
#endif
#endforeach
It could be optimized, first, you need to make relation one to many from categories to posts
first: make sure that you have in posts migrations category_id column
Second: Open Category Model and write this method this will allow you to fetch posts that belong to the category
public function posts(){
return $this->hasMany(\App\Post::class);
}
Third: open shop model and write this method this will allow you to fetch category that belongs to the post
public function catgeory(){
return $this->belongsTo(\App\Category::class);
}
Finally: you will edit your view like this one
#foreach($posts as $post)
<div class="col-sm-6 col-md-3 d-flex justify-content-center other-post">
<a href="#">
<img src="#" alt="">
<p class="post-category">{{ $post->category->title }}</p>
<h5 class="post-title">{{ $post->title }}</h5>
</a>
</div>
#endforeach
and of course, you wouldn't call categories in your controller anymore
public function index()
{
$post = BlogPost::orderBy('id', 'desc')->take(14)
->with('category')->get();
return view('blog.index', ['posts' => $post]);
}
Maybe it better use a relation to drive this situation. You can load in the controller the data in this way.
In the Model Post:
function categories(){
return $this->belongsToMany('App\BlogCategory')->select(array('id', 'name');
}
Maybe is hasOne -> the relationship if you don't have a table pivot...
In the Controller:
public function index()
{
$data['posts'] = BlogPost::orderBy('id', 'desc')->take(14)->with('categories')->get();
return view('blog.index', $data);
}
In the View:
#foreach($posts as $post)
#if($loop->iteration > 2)
<div class="col-sm-6 col-md-3 d-flex justify-content-center other-post">
<a href="#">
<img src="#" alt="">
<p class="post-category">{{ $post->categories->name }}</p>
<h5 class="post-title">{{ $post->title }}</h5>
</a>
</div>
#endif
#endforeach
this line $categories->get($post->category_id) return for you an array of category, so the solution for you here is just like bellow:
{{ $categories->get($post->category_id)['name'] }}

Working with whereDoesntHave() in Laravel 5.4

How do I implement a scope where in the user will claim a reward on a specific level and once they claim their rewards, the reward field will no longer display the reward that they have claimed. So for example:
The user is on level 20, on his reward panel, there are 3 available rewards to be claimed, level 10, 15 and 20. So if the user claimed the level 10 reward, it will no longer display on the panel except for level 15 and 20 rewards.
Here is the code for the blade:
#foreach(App\LevelRewards::getRewards()->get() as $rewards)
#if(Auth::user()->level >= $rewards->level_required || Auth::user()->level == $rewards->level_required)
#if(App\ClaimReward::claimLevel()->get())
<div class="col-lg-2 col-md-3 col-sm-6 col-xs-6" style="margin: 5px 0px;">
<div class="hovereffect">
<a href="#" class="d-block mb-4 h-100">
<input type ="hidden" name="id" value="{{$rewards->id}}"/>
<img class="img-responsive" src="{{asset('rewards_img/'.$rewards->picture)}}" alt="">
</a>
<div class="overlay">
<h2 style="font-size: 14px;">{{$rewards->details}}</h2>
#if($rewards->type == 'physical')
<button type="button" class="btn btn-success btn-sm" data-toggle="modal" data-target="#claimPhysical" data-details="{{$rewards->details}}" data-id="{{$rewards->id}}" data-level="{{$rewards->level_required}}" data-physical="{{$rewards->item_name}}">
CLAIM
</button>
#else
<button type="button" class="btn btn-success btn-sm" data-toggle="modal" data-target="#claimDigital" data-id="{{$rewards->id}}" data-level="{{$rewards->level_required}}" data-physical="{{$rewards->item_name}}">
CLAIM
</button>
#endif
</div>
<div style="background: #2d2d2d; padding: 9px;">
<span class="credits_top">Required Level: <span>{{$rewards->level_required}}</span></span>
<p>{{$rewards->item_name}}</p>
</div>
</div>
#endif
#endif
#endforeach
And this is the code for the model ClaimReward model:
public function scopeClaimLevel2($query)
{
return $query->join('level_rewards','level_rewards.id','=','claim_rewards.reward_id')->select('level_rewards.*');
}
Any links and source of information regarding this question will be highly appreciated. Thank you.
Edit: I tried;
public function scopeClaimLevel($query)
{
return $query->join('claim_rewards','claim_rewards.reward_id','=','level_rewards.id')->select('level_rewards.*');
}
public function scopeGetRewards($query)
{
return $query
->join('claim_rewards','claim_rewards.reward_id','=','level_rewards.id')
->whereDoesntHave('claimLevel', function (Builder $query) {
$query->where('claim_rewards.status', '=', '0');
})
->select('level_rewards.*');
}
But it says
Call to undefined method Illuminate\Database\Query\Builder::getRelated()'
add another table that will hold rewards thats user already claimed,
and in the foreach check if this reward id exists in this user claimed rewards,
if not so show it and if yes so skip it.
the table will hold 2 fields:
1) user_id
2) rewards_id
regarding the comments above,
and after your edit to what you tried,
looks like the order of the query is wrong... put whereDoesntHave before the select,
and change to implementation of it as wrote in Laravel documentation example.
try this:
public function scopeClaimLevel2($query)
{
return $query
->join('claim_rewards','claim_rewards.reward_id','=','level_rewards.id')
->whereDoesntHave('claim_rewards', function (Builder $query) {
$query->where('status', '=', '0');
})
->select('level_rewards.*');
}
edit:
try to change the join, as wrote here: https://laravel.com/docs/5.4/queries#joins
build the join and in it's function set how to join and where status=0
return $query
->join('claim_rewards', function ($join) {
$join->on('claim_rewards.reward_id', '=', 'level_rewards.id')->where('status', '=', '0');
})
->select('level_rewards.*');

Invalid argument supplied for foreach() in laravel 5.3

I do not know exactly how this works, so that's why I'm asking. I'm still working on a Bulletin Board System and now I want under each category, a subcategory.
For example:
I have done this using the following thread on LaraCasts:
https://laracasts.com/discuss/channels/eloquent/eloquent-getting-subcategories-from-the-categories
Now my IndexController looks like this:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Thread;
use App\Chat;
use App\Category;
class IndexController extends Controller
{
/**
* Show the application dashboard.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
$threads = Thread::all()->toArray();
$chats = Chat::orderBy('id', 'DESC')->take(50)->with('author')->get();
$categories = Category::with('sub_category')->get();
return view('index', compact('threads','chats','categories'));
}
}
This is my Category Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
public function sub_category()
{
return $this->belongsTo(self::class, 'parent_id', 'id');
}
public function parent_category()
{
return $this->hasMany(self::class, 'id', 'parent_id');
}
}
My view (index.blade.php):
#foreach($categories as $category)
<div class="col-md-8">
<div class="panel panel-primary">
<div class="panel-heading"><i class="fa fa-angle-right" aria-hidden="true"></i> {{ $category->caption }}</div>
<div class="panel-body">
#foreach($category->sub_category as $sub_category)
<div class="row forum-row">
<div class="col-xs-12 col-md-8 col-sm-8">
<div class="hidden-xs visible-sm visible-lg visible-md pull-left forum-icon-read">
<i class="fa fa-comment"></i>
</div>
{{ $sub_category->caption }}<br>
<small>{{ $sub_category->desc }}</small>
</div>
<div class="col-xs-12 col-md-4 col-sm-4 forum-latest-container">
<p class="forum-data cutoff">Test</p>
<small>
door <a class="Donateur" href="/user-Sygun">Sygun</a>
<p class="forum-data">
2 minuten geleden </p>
</small>
</div>
</div>
#endforeach
</div>
</div>
</div>
#endforeach
I also have two database tables:
Sub_categories (id, caption, parent_id, min_rank, desc)
Categories (id, caption, min_rank, desc)
The error message I get:
Invalid argument supplied for foreach()
Can you tell me what is the right way to achieve this?
Create two model named Category and SubCategory.
In Category model
public function subcategories()
{
return $this->hasMany('App\SubCategory', 'parent_id');
}
In SubCategory model
public function parent_category()
{
return $this->belongsTo('App\Category', 'parent_id');
}
Then in your controller query it like:
$categories = Category::with('subcategories')->get();
And hopefully your foreach will work.
Category model
public function subcategories(){
return $this->hasMany('SubCategory', 'parent_id');
}
On view
#foreach($categories as $category)
#foreach($category->subcategories as $subcategory)
{{$subcategory->caption}}
#endforeach
#endforeach
And make sure you create SubCategory model.

How to make relationship between two models and update the database

It's me again but now I need some more help from you, I have some version of shopping cart and the whole idea is when I click on the product button the database to be update with the informations which user(id) has order that product(id). First I make orders table with informations(id, product_name, price), other table is users table (id, user_name) and the final table user_order table(id, user_id, order_id);
After that I make two models, one is the Orders model for the products and the second one is the User model. The relationship that I want to make is between this two models.
User model function:
public function orders(){
return $this->belongsToMany('App\Orders', 'user_order', 'user_id', 'order_id');
// return $this->belongsToMany('App\Orders');
}
Orders model function:
public function users(){
return $this->belongsToMany('App\User', 'user_order', 'order_id', 'user_id');
//return $this->belongsToMany('App\User');
}
This is the main html where I show all products with the submit button:
<div class="row">
#foreach($orders as $order)
<div class="col-sm-4 col-lg-4 col-md-4">
<div class="thumbnail">
<img src="http://placehold.it/320x150" alt="">
<div class="caption">
<h4 class="pull-right">{{ $order->cena }}</h4>
<h4>{{ $order->order_name }}
</h4>
<p>See more snippets like this online store item at <a target="_blank" href="http://www.bootsnipp.com">Bootsnipp - http://bootsnipp.com</a>.</p>
</div>
<div class="ratings">
<p class="pull-right">15 reviews</p>
<p>
<span class="glyphicon glyphicon-star"></span>
<span class="glyphicon glyphicon-star"></span>
<span class="glyphicon glyphicon-star"></span>
<span class="glyphicon glyphicon-star"></span>
<span class="glyphicon glyphicon-star"></span>
</p>
</div>
<div class="btn-group center">
Order this product!
</div>
<br>
</div>
</div>
#endforeach
Controller function:
public function makeOrder(Request $request, $id){
$user = User::where('email', $request['email'])->first();
$findorder = Orders::find($id);
//$user->orders()->detach();
$user->orders()->attach(Orders::where('id', $findorder))->first();
return redirect()->back();
}
And the route:
Route::get('/add-to-database/{id}',[
'uses' => 'AppController#makeOrder',
'as' => 'product.makeOrder'
]);
The whole idea is how to make function after submiting the button the table user_order to be updated with the id of the user, and id of the product.
Any help?
Your makeOrder() should be as:
public function makeOrder(Request $request, $id) {
$user = User::where('email', $request->get('email'))->first();
// this is to make sure that order is available in database
$order = Orders::findOrFail($id);
$user->orders()->attach($order->id);
return redirect()->back();
}

Categories