how do we add a limit to many-to-many relation. Following the example in the documentation let's say we have 3 tables post, category and post_category. Let's say I have a list of posts and on every post a possibility to choose a category.
How can I 'limit' the relation so that there can't be more then 5 categories per post and 100 posts per category?
I have managed to do so using a checking if count(post->books) < 5 on the create action of post_category controller but am looking for a way to do it more Yii friendly, if that exists.
Working on Yii 1.1.14.
You can using custom validation rules. For example in your PostCategory model, add the following rule
public function rules()
{
return [
[['post'], 'validateSize'],
];
}
Then anywhere in the model add validateSize()
public function validateSize($attribute_name,$params){
if(sizeof($this->post->categories) > 4)
$this->addError($attribute_name, Yii::t('post', 'You cant have more than 5 categories per post'));
}
This will give an error when trying to create a new category belonging to a post that already has 4 categories
Related
Need tips for displaying this one to many related data on a heirarchical
order in laravel view page. Here vegetable, groceries are category and
other's are there related product.
Here is the image for data.
Need to show this every 1 to many related data on a hierarchical order on
a single view page. I want to loop through these array and
want my result like tree view:
Based on your given information I will try to help you as much as possible.
Looking at your image, shows me that you already have duplicated data in your database. Where possible try to use different tables for different entities. In this case your Category is used over and over again. So try to create a new table for it.
That being said, you still have 2 options for this. A one to many or many to many relationship between your ingredient and category. This depends on what you want, do you want an ingredient to be able to have one or many categories. I have added a image below to show the 2 types of database structures for this. (Left: One to many, Right: Many to many)
You will have to create 2 models for both the Category and the Ingredient and make sure that you can use those models to store and receive data from your database. If you would like some more information about models take a look here:
https://laravel.com/docs/6.x/eloquent#defining-models
After creating your models, you should define your relation methods inside your models. This is different based on the choice you have made. (many to many or one to many).
One to many:
In the one to many example an ingredient can have only 1 category. Therefor you have to create a method in your ingredient called category and this should return a HasOne:
/**
* #return HasOne
*/
public function category(): HasOne
{
return $this->hasOne(Category::class);
}
Then your category can have multiple Ingredients so your Category should get a method called ingredients and it must return a BelongsToMany:
/**
* #return BelongsToMany
*/
public function ingredients(): BelongsToMany
{
return $this->belongsToMany(Ingredient::class);
}
Many to many:
In a many to many relation your category will be the same because it still has many ingredients. Only the ingredient will change because it not also has many categories. The method for the categories will now just be the same as the one for the ingredients:
/**
* #return BelongsToMany
*/
public function categories(): BelongsToMany
{
return $this->belongsToMany(Category::class);
}
That is that! Now how to use this (and hopefully the answer to your question). When you have a category like:
$category = Category::first();
You are able to use the ingredients method to get all the ingredients having this category:
$category = Category::first();
$ingredients = $category->ingredients;
This will give you a Collection with all the ingredients of this category.
You could also use this for every category.
$categories = Category::all(); //Get all categories
foreach ($categories as $category) {
$ingredients = $category->ingredients; //Get all ingredients
}
Extra:
Note that i'm not using the () after ingredients, this has to do with the mysql queries that are executed (Without () it will look if it has results (if yes it will use these of no it will query your database and then use the results)).
There are 3 entities:
Categories
Subcategories
Photos
(3 tables, 3 controllers, 3 models).
We need to implement CRUD operations for each entity. How to implement routing?
For example, to delete a subcategory, you need to make a DELETE request to:
categories / {category_id} / subcategories/{subcategory_id}
In the blade in href or in form action you need to write the following, for example:
{{ route('subcategories.destroy', [$category->id, $subcategory->id])}
But I don't need $category_id to delete a subcategory, just id subcategory is enough.
If then the same thing is implemented for photo, then you have to pass 3 parameters, 2 of which I do not need, but only the id of the photo.
I think I'm going some wrong way, can someone tell me how to implement routing and crud operations for categories and their subcategories?
routes/web.php:
// Category routes
Route::resource('categories', 'CategoryController');
// Subcategories routes
Route::prefix('categories/{category_id}')->group(function (){
Route::resource('subcategories', 'SubcategoryController');
});
SubcategoryController#destroy:
public function destroy($category_id, $subcategory_id)
{
$subcategory = Subcategory::findOrFail($subcategory_id);
$subcategory->delete();
return redirect('/categories/' . $subcategory->category_id);
}
Tables:
categories
subcategories
photos
I am using Laravel with Voyager for the back-end.
I made a relationship between Posts model and Categories model.
When adding a new Post, I can choose an according category using a dropdown.
How can I make this dropdown show Categories according to certain conditions? (Let's say, only subcategories)
You can easily filter the shown relationship options by defining a local scope in the foreign model. For example, if you want to only show active entries of categories in a relationship input, create a scope as given in your Category model,
public function scopeSubcategories($query){
return $query->where('parent_id', '!=' , null);
}
Now, go to the BREAD builder and add the following to the relationship options
{
"scope": "subcategories"
}
The value is the name of your scope-method without the word scope.
The value for scopeSubcategories() is subcategories.
I am currently using Laravel (PHP framework) in order to construct an ecommerce site.
The site will have a lot of categories(for products) of which there is ruffly 100-150 and will probably be more as there will be a backend site to add more.
Some times it will be necessary for a category to appear in more than 1 parent category on the site.
Category Relationships I am trying to achieve:
A category can have many child categories.
A category may have more than one parent category.
I am very confused as to how to set up the second of these two relationships correctly within Laravel.
So my question is:
How do I set up a database structure and Model relations so that a category can belong to many other category without any duplication in the categories table.
I would like to know what tables/columns I need and also what types of relationships need to be set in the models please.
This model seems to work:
I have a table called category_category and relation:
public function parentCategories()
{
return $this->belongsToMany('TottonTimber\Category', 'category_category', 'category_id', 'parent_id');
}
public function childCategories()
{
return $this->belongsToMany('TottonTimber\Category', 'category_category', 'parent_id', 'category_id');
}
Yet this doesn't seem like the correct way of doing it as both are "belongsTo"
In Many to Many to relations. Both models do have a belongs to relation with the other. For example in classic User & Roles Scenerio, User Belongs to Many Roles & Roles Belongs to Many Users.. So as you see 'Belongs to' relationship both sides. Here as you have same model for both ends of your relations, you have to put 'belongsto' for both your relation definations. That is perfectly ok it seems.
I have 3 tables
--- Posts (all the posts)
rows = id, title, content
--- Boards (all the boards)
rows = id, title
--- board_post (the link between boards and posts: many <-> many)
rows = board_id, post_id
2 Eloquent classes named board and post
now I would love to select all the posts from a board, based on board_post
I was thinking in the way of:
Posts::whereIn('id', $board->post_ids())
how would I be able to do this, that first off
that if I do Board::find(1)->post_ids I get all the post id's of that board
And then how wuld I be able to get all the post opbjects from that?
greetings Glenn
Why are you using a many-to-many relationship for Posts and Boards? It would most likely be a one-to-many relationship: A Board may have several posts, but a Post should only belong to one board (this would simplify your database structure to remove the board_post table).
You would then do:
Inside of Board class:
public function posts() {
return $this->hasMany('Post', 'board_id');
}
Then, Board::find(1)->posts would get you all of the posts for that board (use posts, not posts()).
To do it with your current database setup, use belongsToMany instead:
public function posts() {
return $this->belongsToMany('Post', 'board_post');
}
If you want to load a Board WITH all of it's posts (eager-loading) use this:
Board::with('posts')->find(1)
Otherwise, just to get the posts for a particular board, use:
Board::find(1)->posts
In Board model make sure you define belongsToMany relationship
public function posts()
{
return $this->belongsToMany('Post', 'board_post');
}
Now you should be able to do this:
Board::find({id})->posts
Forther reading material: http://laravel.com/docs/eloquent#relationships