Laravel, Using two user relationships in model - laravel

Connection Model :
protected $table = 'connections';
protected $fillable = ['user_id_1','user_id_2','connection_status'];
public function user_id_1()
{
return $this->belongsTo('App\User', 'user_id_1');
}
public function user_id_2()
{
return $this->belongsTo('App\User', 'user_id_2');
}
Controller :
public function show($id){
$user_id_1_connections = Connection::whereUser_id_1AndConnection_status($id, 1)->get();
$user_id_2_connections = Connection::whereUser_id_2AndConnection_status($id, 1)->get();
return view('connection.showConnection',['user_id_1_connections' => $user_id_1_connections, 'user_id_2_connections' => $user_id_2_connections]);
}
Blade:
#foreach($user_id_1_connections as $user_id_1_connection)
{{ $user_id_1_connection->user_id_1 ? $user_id_1_connection->user_id_1->name : 'unknown' }}
#endforeach
#foreach($user_id_2_connections as $user_id_2_connection)
{{ $user_id_2_connection->user_id_2 ? $user_id_2_connection->user_id_2->name : 'unknown' }}
#endforeach
I am making two relationships to user in my model Connection.php. I'm getting the error: "Trying to get property of non-object " in line 2nd and 5th in blade.

First change:
public function user_id_1()
{
return $this->belongsTo('App\User', 'user_id_1');
}
public function user_id_2()
{
return $this->belongsTo('App\User', 'user_id_2');
}
into:
public function user1()
{
return $this->belongsTo('App\User', 'user_id_1');
}
public function user2()
{
return $this->belongsTo('App\User', 'user_id_2');
}
to avoid collisions between table columns and relationships
Instead of this:
public function show($id){
$user_id_1_connections = Connection::whereUser_id_1AndConnection_status($id, 1)->get();
$user_id_2_connections = Connection::whereUser_id_2AndConnection_status($id, 1)->get();
return view('connection.showConnection',['user_id_1_connections' => $user_id_1_connections, 'user_id_2_connections' => $user_id_2_connections]);
}
you can do:
public function show($id){
return view('connection.showConnection', ['connection' => Connection::findOrFail($id)]);
}
And now your template could look like this:
User 1 name: {{ $connection->user1 ? $connection->user1->name : 'unknown' }}
User 2 name: {{ $connection->user2 ? $connection->user2->name : 'unknown' }}
But to be honest it's hard to get what you really want to achieve - you are using strange function whereUser_id_1AndConnection_status what you should rather don't do so probably you should read carefully relationships documentation for Laravel.

Related

How can I get video of specific model?

I want to display videos for each model in my table, where to define they are connected by their ids?
In my controller:
public function index()
{
$model_video = NewModelVideos::all();
return view('admin.model_new_videos.index')
->with('models', $models)
->with('model_video', $model_video);
}
in my Model:
class NewModelVideos extends Model
{
public function model()
{
return $this->belongsTo('App\Models\NewModels\NewModel', 'model_id');
}
}
class NewModel extends Model
{
public function videos()
{
return $this->hasMany('App\Models\NewModels\NewModelVideos', 'model_id', 'id');
}
}
and View:
#foreach($model_video as $model)
{{ $model->video }}
#endforeach
You should update your code like this:
public function index()
{
$model_video = NewModelVideos::all();
$models = NewModel::all();
return view('admin.model_new_videos.index')
->with('models', $models)
->with('model_video', $model_video);
}
and blade:
#foreach($models as $model)
{{ $model->videos }} //get videos
#endforeach
#foreach($model_video as $video)
{{ $video->model }} //get model
#endforeach

Trying to retrieve posts from table by category slug

Hello i am trying to loop posts that are associated to each category by the slug. It works when i use the ids but when i change my controller function to search by slug it retrieves the slug but does not load the foreach loop.
I have tried so many methods and i don't know where i am going wrong please help.
Category Model :
protected $table = 'post_categories';
public function posts()
{
return $this->hasMany('App\Post', 'id', 'name', 'catslug');
}
Post Model
public function user()
{
return $this->belongsTo('App\User');
}
public function postCategories()
{
return $this->belongsTo('App\PostCategory');
}
Controller
public function getPostCategory($catslug) {
$postCategories = PostCategory::with('posts')
->orderBy('name', 'asc')
->where('catslug', '=', $catslug)
->first();
return view ('articles.category.categoriesposts')->with('postCategories', $postCategories);
}
Route
Route::get('articles/category/{catslug}', [
'uses' => 'ArticlesController#getPostCategory' ,
'as' => 'PostCategory'
] );
View
#foreach($postCategories->posts as $post)
<h4>{{ substr($post->title, 0, 50) }}</h4>
<p>{{ substr($post->body, 0, 90) }}</p>
#endforeach
When i use id there is no problem i cant see what i am doing wrong any feedback will be truly appreciated
Thanks
Ash
Save category id in posts table insted of category name or slug.
Change in post category model:
public function posts()
{
return $this->hasMany('App\Post', 'category_id');
}
Your controller method:
public function getPostCategory($catslug)
{
$postCategories = PostCategory::with('posts')->where('catslug', $catslug)->first();
return view('articles.category.categoriesposts')->with('postCategories', $postCategories);
}
If you want to order posts by name then add orderBy() in relationship :
public function posts()
{
return $this->hasMany('App\Post', 'category_id')->orderBy('name', 'asc');
}

One-to-many and one-to-many relationship 1 laravel

i did this(sorry my english it's bad bad....)
controller:
public function index()
{
$lessons = course::find(1)->lesson;
return view('home',compact('lessons'));
}
model lesson
public function course() {
return $this->belongsTo(Course::class);
}
model courses
public function lesson() {
return $this->hasMany(Lesson::class);
}
blade
#foreach ($lessons as $lesson )
<h4>{{$lesson->title}}</h4>
#endforeach
in browser nothing appears
why?:(
First rename your lesson method with plural lessons.
// Course model
public function lessons() // plural
{
return $this->hasMany(Lesson::class);
}
Now get the lesson's collection.
public function index()
{
$lessons = Course::find(1)->lessons;
return view('home', compact('lessons'));
}
#foreach ($lessons as $lesson )
<h4>{{$lesson->course->title}}</h4>
#endforeach
Have you tried it like this:
return view('greeting')->with('lessons', $lessons);
Now you can call '$lessons' in your view. Take a look at this link
https://laravel.com/docs/5.6/views
Can you try to use return $lessons; and show me what it says?

type casting in laravel json response in relationships eager loading

This is my post model.
class Post extends Model
{
use SoftDeletes;
protected $table = 'posts';
protected $fillable = ['title','featuring_image', 'brief', 'body', 'seen_count'];
public function user(){
return $this->belongsTo(User::class);
}
public function comments()
{
return $this->hasMany(Comment::class);
}
public function someComments()
{
return $this->comments()->limit(Constants::COMMENTS_COUNT_LIMIT);
}
public function commentsCount()
{
return $this->comments()
->selectRaw('post_id, count(*) as count')
->groupBy('post_id');
}
public function likes()
{
return $this->hasMany(Like::class);
}
public function isLiked()
{
return $this->likes()->where('user_id', auth()->check() ? auth()->user()->id : 0);
}
public function likesCount()
{
return $this->likes()
->selectRaw('post_id, count(*) as count')
->groupBy('post_id');
}
}
I executed this query on this model.
$post = Post::with(['categories', 'user', 'commentsCount', 'likesCount', 'isLiked'])->find($post->id);
Because of the relation between this table and like and comment table, The output of this query for 'commentsCount', 'likesCount', 'isLiked' is an array. But I need to receive numbers for 'commentsCount' and 'likesCount', and a boolean for 'isliked' as an output, in laravel josn response.
You might find it easier to use the withCount() the comes with Eloquent instead.
Then for is_liked you could use a scope to get the value and the cast it to a boolean:
public function scopeIsLiked($query)
{
if (is_null($query->getQuery()->columns)) {
$query->select([$query->getQuery()->from . '.*']);
}
$relation = Relation::noConstraints(function () {
return $this->likes();
});
$q = $this->likes()->getRelationExistenceCountQuery(
$relation->getRelated()->where('user_id', auth()->check() ? auth()->user()->id : 0)->newQuery(), $query
);
$query->selectSub($q->toBase(), 'is_liked');
}
Please note you will need to add the use statement for Relation to the top of the class:
use Illuminate\Database\Eloquent\Relations\Relation;
You model could then look like:
class Post extends Model
{
use SoftDeletes;
protected $table = 'posts';
protected $fillable = ['title', 'featuring_image', 'brief', 'body', 'seen_count'];
public function user()
{
return $this->belongsTo(User::class);
}
public function comments()
{
return $this->hasMany(Comment::class);
}
public function someComments()
{
return $this->comments()->limit(Constants::COMMENTS_COUNT_LIMIT);
}
public function likes()
{
return $this->hasMany(Like::class);
}
/**
* Scope to add the "is_liked" flag.
*
* #param $query
*/
public function scopeIsLiked($query)
{
if (is_null($query->getQuery()->columns)) {
$query->select([$query->getQuery()->from . '.*']);
}
$relation = Relation::noConstraints(function () {
return $this->likes();
});
$q = $this->likes()->getRelationExistenceCountQuery(
$relation->getRelated()->where('user_id', auth()->check() ? auth()->user()->id : 0)->newQuery(), $query
);
$query->selectSub($q->toBase(), 'is_liked');
}
}
And your query would look something like:
$post = Post::with('categories', 'user')
->withCount('likes', 'comments')
->isLiked()
->find($post->id);
Hope this helps!
You can use Laravel casts:
Inside the each model you can add the following to cast a value, per example:
protected $casts = [
'isLiked' => 'boolean',
];
Rwd's answer gives a nice solution using scopes, but for laravel 5.4+ you could get away with aliasing the withCount() result and then casting it to boolean with a $cast variable on the model or an accessor (with accessor, you can only get snake case is_liked). This way we don't need to write complex scopes.
The model would be
class Post extends Model
{
// rest of model
protected $casts = ['isLiked'=>'boolean'];
public function likes()
{
return $this->hasMany(Like::class);
}
}
Then in your controller
$post = Post::with('categories', 'user')
->withCount(
[
'likes as likesCount', 'comments as commentsCount',
'likes as isLiked' =>function($query){
$query->where('user_id', auth()->check() ? auth()->user()->id : 0);
}
]
)
->find($post->id);
And now you get likesCount (int), commentsCount (int) and isLiked (boolean)

posts and attachments, Undefined property: Illuminate\Database\Eloquent\Collection::$name

when i try to get the attachment's name like this:
{{$post->attachments->name}}
i get the following error
Undefined property: Illuminate\Database\Eloquent\Collection::$name (View: C:\wamp\www\Sites\app\views\public\categories\show.blade.php)
Post model
class Post extends \Eloquent implements SluggableInterface {
public function category(){
return $this->belongsTo('Category');
}
public function attachments(){
return $this->hasMany('Attachment');
}
}
Attachment Model
class Attachment extends \Eloquent {
protected $fillable = ['name', 'type', 'extension', 'user_id', 'post_id', 'size'];
public function post(){
return $this->belongsTo('Post');
}
}
CategoriesController
class CategoriesController extends \BaseController {
public function show($id, $slug = null)
{
$category = Category::find($id);
$posts = Post::whereCategoryId($category->id)->orderBy('date', 'DESC')->paginate(4);
return View::make('public.categories.show', compact('category', 'posts'));
}
}
categorie View
#foreach($posts as $post)
{{$post->title}} // work fine
{{$post->body}} // work fine
{{$post->attachments}} // return this :
[
{
"id":14,
"name":"29-01-2015-134",
"type":"image\/jpeg",
"extension":"jpg",
"created_at":"2015-01-29 13:04:35",
"updated_at":"2015-01-29 13:04:35",
"user_id":1,
"post_id":134,
"size":136130
}
]
#endforeach
any ideas?!!!
According to your relationship definition there can be many attachments, that means the relation will return a collection of models. You can either get only the first one:
#if($attachment = $post->attachments()->first())
{{ $attachment->name }}
#endif
Or loop over all attachments
#foreach($post->attachments as $attachment)
{{ $attachment->name }}
#endforeach

Resources