Create conditional in Model methods - php

Hi guys i wish to create a custom method on my Category Model but i need to create some conditionals with it.
table post:
- id;
- category_id
-name...
table Category:
- id
- parent_id
- name
Imagin that i have a post, and in this post there is a category called SomeSubcategoryName, i my posts table i have a column called category_id.
When i call the post record i have a relation with the Category Model, but i wish to have in my Category Model a method called masterCategory, where i give the mster category by checking if the parent_id is null or not, in case that the record have a parent_id of null great, i return the record but if is not i need to use the parent_id value and search on the Model category column id for the record and return the result.
Imagine this scenario:
$post = Post::find(2);
//this call should return the main category and not the subcategory info.
$post->masterCategory();

In your category model define a relationship on its self:
public function masterCategory()
{
return $this->belongsTo(App\Category::class, 'parent_id', 'id');
}
Eager load the relationships on your Post when you query it:
$post = Post::with(['category', 'category.masterCategory'])->firstOrFail($id);
Access it like this:
$post->category->masterCategory; // will be the mastery category or null
Otherwise us:
$post->category;
Don't over complicate it.

In your Category model you should have something like this
public function master()
{
return $this->belongsTo(Category::class, 'parent_id');
}
public function isMaster()
{
if($this->parent_id)
return false;
else
return true;
}
Now you can check that post's category is master or not :
if($post->category->isMaster())
....
The second way is using relations and eloquent
$post = Post::with(['category', 'category.master'])->first($id);

Related

How to get relation of relation Count in laravel?

i have laravel models
Category: id,name
public function posts(){
return $this->hasMany(PostCategory::class,'category_id','id');
}
PostCategory : post_id, category_id
public function post(){
return $this->belongsTo(Post::class,'post_id');
}
POST: id, ..so on
public function solutions(){
return $this->hasMany(PostSolution::class,'post_id','id');
}
I need to get count of all posts fall under a category and also solutions under one category.. there is no direct relation of category and solution so how to get count of solutions in one category.
$categories = Category::withCount('posts')->get();
I think use hasManyThrough relation
// Category Class
public function solutions()
{
return $this->hasManyThrough(PostSolution::class, Post::class);
}
// Then get the data in the same old manner
$categories = Category::->withCount('posts')->get();
I hope this will help

In Laravel Eloquent how to define relationship through secondary table? (Always returning 0 relations)

I feel like this should work. I have a list of products and categories (types).
Tables:
Products
- id
- name
- etc
Types
- id
- name
- etc
ProductTypes
- product_id
- type_id
Now, I feel like in the Type model in Laravel, I should be able to define this relationship:
public function products()
{
return $this->hasManyThrough(Product::class, ProductType::class, 'type_id', 'id');
}
I've tried other variations with the secondary ids in the additional parameters but no luck, always an empty list. Is ProductTypes a pivot table and therefore should be dealt with differently?
Edit: What's weird is that for the final 2 parameters ($localKey = null, $secondLocalKey = null) even if I enter complete garbage no error is thrown but these 2 parameters $firstKey = null, $secondKey = null have to be correct).
You are using the wrong relationship. Based on your database structure, a product can belong to many type. Therefore, it should be a BelongsToMany instead of a HasManyThrough.
You can achieve what you want with the following method, by passing the table name of your ProductTypes as the second parameter:
public function products()
{
return $this->belongsToMany(Product::class, 'product_types');
}
If your ProductType model extends Illuminate\Database\Eloquent\Relations\Pivot, you can do:
public function products()
{
return $this->belongsToMany(Product::class, 'product_types')
->using(ProductType::class);
}
For more information about Many to Many relationships: https://laravel.com/docs/6.x/eloquent-relationships#many-to-many

How do I get a field from a sub-relation in Laravel?

Objective:
Include category_name field in $posts attributes. The corresponding FK - category_id is currently included in my return.
Controller returns all Posts with their PostChilds
return $posts = Post::with('postchildren')->get();
Post Model hasMany PostChild
public function postchildren() {
$this->hasMany('App\PostChild')
}
PostChild Model hasOne Category
(This table has a category_id field which is a FK for id in the Category model.)
public function category() {
$this->hasOne('App\Category');
}
Category Model
This table has a category_name field
You should be able to get all the categories associated with the children via the HasManyThrough relationship e.g.
class Post
{
public function categories()
{
return $this->hasManyThrough(PostChild::class, Category::class);
}
}
Then you can access the categories directly on the post object e.g.
$categories = Post::first()->categories;
or if you're wanting an array of them something like
$posts = Post::with('categories')->get();
If you always want the categories loaded on the Post class you can define
class Post
{
protected $with = ['categories'];

show category level in laravel

Let say I have product under parent->child one and another product under parent->child one->child one child all i can get is last category name like:
child one and child one child but parent names before them i cannot get.
Code
Category model:
public function categories()
{
return $this->hasMany(Category::class);
}
public function childs() {
return $this->hasMany(Category::class,'category_id','id') ;
}
public function products(){
return $this->hasMany(Product::class);
}
Product model:
public function category(){
return $this->belongsTo(Category::class);
}
And I store category id in products table, column named category_id.
PS: in this column i store last category id, like if i have:
parent->child one i store child one id in there.
UPDATE
Base on answers I've made some changes in my category model and by code below I've tried to get my product category levels:
#if($product->category->isParent())
{{ucfirst($product->category->title)}} </br>
#else
{{ucfirst($product->category->parent->title)}} > {{ucfirst($product->category->title)}} </br>
#endif
Issue
Issue by code above is: if my product is in third level (or more) I only get parent of last category and not all the way top. EXAMPLE
my product is in : Laptop->HP->PAVILION all I get is HP->PAVILION cannot get laptop category.
I'm not sure if I understand good but...
Into Category Model
public function parent()
{
return $this->belongsTo(Category::class,'category_id');
}
public function childs() {
return $this->hasMany(Category::class);
}
public function isParent()
{
return !$this->category_id ? true : false; // if category_id is null => is a Parent Category
}
You can do $category->isParent() to know if is a Parent or not.
If is parent category you can do $category->childs to get all sub categories.
If is not a parent you can do $category->parent to get parent Category.
From your code it seems you are defining wrong relationships between the classes. Please refer this link https://laravel.com/docs/5.6/eloquent-relationships#one-to-many laravel documentation for the same.
Also if you want to call a particular child through a parent model, one way to call is as below:
$children = App\Category::find(1)->childs;
Because you have defined your relationship function with name "childs" you have to use same name to access the children for that class.

Laravel relations

I am creating a basic forum just so I have something meaningful to do while learning Laravel.
So just like every forum is organized, on the main page i would like to have a list of categories and their subcategories, a total count of posts in every subcategory while also a link to latest post
So relationship is nested hasMany:
Category -> has Subcategories -> has Threads -> has Posts.
In controller method I have
$cat = Category::with('subcategory')->get();
return View::make('forum.index', compact('cat'));
and this works for basic list of categories and subcategories but I can't figure out the rest.
This sure doesnt work
Category::with('subcategory')->with('threads')->with('posts')->get();
since relation between them is not set. Looking at Laravel docs, there is hasManyThrough relation. Is that a solution?
class Category extends Eloquent {
public function subcategory() {
return $this->hasMany('Subcategory');
}
public function posts() { // not sure about this cause it doesnt work
return $this->hasManyThrough('Post', 'Thread');
}
}
And on top of that how do I get posts->count() for every subcategory? Is it possible to have it split? Chaining could get complicated..
EDIT
Table columns are
Categories
id | title
Subcategory
id | title | category_id
Threads
id | title | subcategory_id | user_id
Posts
id | title | body | thread_id | user_id
EDIT 2
What would be the code for grabing only latest post? This doesnt work
$data = Category::with('subcategories.threads')->with(array('posts' => function($query)
{
$query->take(1);
}))->get();
You have setup only one relation that works and that is:
class Category extends Eloquent {
public function subcategory() {
return $this->hasMany('Subcategory');
}
}
Declare other relationships in other models:
class Subcategory extends Eloquent {
public function threads() {
return $this->hasMany('Thread');
}
}
class Thread extends Eloquent {
public function posts() {
return $this->hasMany('Post');
}
}
Once you have declared relationships then you may use:
$categories = Category::with('subcategory.threads.posts')->get();
Since the one Category has many subcategories so use the plural name for subcategories instead of subcategory in your Category model, so for example, you may use:
class Category extends Eloquent {
public function subcategories() {
return $this->hasMany('Subcategory');
}
}
Then also:
$categories = Category::with('subcategories.threads.posts')->get();
All relationships will be retrieved as nested object collections. For example:
$categories->subcategories; // Will be a collection of Subcategory models
$categories->subcategories->threads // Will be a collection of Thread models
$categories->subcategories->threads->posts // Will be a collection of Post models
You may declare a hasManyThrough relationship between Subcategory and Post using something like this:
class Subcategory extends Eloquent {
public function threads() {
return $this->hasMany('Thread');
}
public function posts() {
return $this->hasManyThrough('Post', 'Thread');
}
}
Also, you may build a relationship between Category and Thread through Subcategory.
I have
QuestionCategory and Questions['category_id'] and ItemsOfQuestion['question_id']
This Code has Work for my I hope that is useful for you
$categories=ExamCategory::with(['question' => function ($query) use($exam){$query->where('exam_id','=',$exam->id)->with('Items');}])->get();

Categories