I'm facing a problem with name conventions for mysql's tables in laravel, expecially for categories name.
I found out to have a lot of category-like tables to identify a Model category.
In some cases I managed to rename them avoiding the prefix 'category'. For example the model UserCategory has become Role, and the table has become roles. With this trick I can have a readable role_user pivot table.
In other cases I can't find a proper name: ProductCategory, CarCategory, StyleCategory and so on. What is the best approach in this case? And what is the best name could I assign to the model and to the table?
Furthermore, if a model has multiple categories of his type I should have something like product_productcategory pivot table and that's orrible. That's why I always prefer to avoid the word category in a model/table, but I'm afraid there are no other ways in these cases.
What is your approach? Are there some best practices?
If your category tables have columns in common, I would suggest using many-to-many polymorphic relation:
product
id - integer
name- string
car
id - integer
manufacturer - string
model - string
categories
id - integer
name - string
categorizable
category_id - integer
categorizable_id - integer
categorizable_type - string
The Product and Car models will both have a categories method that calls the morphToMany method on the base Eloquent class:
class Product extends Model
{
/**
* Get all of the categories for the product.
*/
public function categories()
{
return $this->morphToMany('App\Category', 'categorizable');
}
}
Inverse of the relationship:
class Category extends Model
{
/**
* Get all of the products that are assigned this category.
*/
public function products()
{
return $this->morphedByMany('App\Product', 'categorizable');
}
/**
* Get all of the cars that are assigned this category.
*/
public function cars()
{
return $this->morphedByMany('App\Video', 'categorizable');
}
}
Related
I have two tables. Customer and address. The relationship of the table is that a CUSTOMER can have many ADDRESSES. So what I want as a result to my query is to get the list of customer and only one latest address
ADDRESS TABLE
id : 1
city:"cebu"
zip_code:"600"
cus_id:1
id:2
city:"mandaue"
zip_code:"6001"
cus_id:1
CUSTOMER TABLE
id: 1
name:"JOHN DOE"
What I want to get the customer "JOHN DOE" and the address with ID "2"
I'm using laravel query builder
If you want to get only one latest address, you can use hasOne same as :
// Customer model relation
public function lastestAddress()
{
return $this->hasOne(Address::class, 'customer_id')->orderBy('id', 'desc');
}
And
$model = Customer::with('lastestAddress')
you can use Eloquent ORM in laravel.
Eloquent :
You must setting in your customer model
Class Customer(){
public function address()
{
return $this->hasMany(Address::class, 'cuss_id', 'id')->latest();
}
in your Adress model :
Class Address(){
public function customer()
{
return $this->belongsTo(Customer::class, 'id', 'cuss_id')
}
Then in your controller you can call the model :
$data = Customer::with('address')->get();
So you have two tables: customers and addresses, with a "one customer can have many addresses" relationship.
In Laravel, we normally use Eloquent models to query the database. So to get a customer and all its addresses, we must first model the database; each table with its own Eloquent model. (See details in the docs.)
class Address extends Model
{
// although empty for now, this class definition is still important
}
class Customer extends Model
{
/**
* Get the latest address.
*/
public function currentAddress()
{
return $this->hasOne(Address::class, 'cus_id')->latestOfMany();
}
}
In the Customer model, our currentAddress() method defines how a Customer instance related to the Address instances.
It's like we're saying,
"A customer may have many Addresses. Just get one which is the latestOfMany. That's how we'll get the customer's currentAddress.
Now that we have the necessary Eloquent models setup, we can lookup John Doe and his current address.
$johnDoeId = 1;
// query the database for customer 1, including its current address
$johnDoe = Customer::with('currentAddress')->find($johnDoeId);
$johnDoe->currentAddress; // 👈 John's latest address, at Mandaue
Here is my problem. I have a table called user and table called skills, also I have a pivot table that connects these two called EmployeeSkill. I am trying to fetch the skills that belong to the user but when i use tinker it returns Base table or view not found: 1146 Table 'pfe_sirh_db.skill_user' doesn't exist (SQL: select skills.*, skill_user.user_id as pivot_user_id, skill_user.skill_id as pivot_skill_id, skill_user.employee_id as pivot_employee_id from skills inner join skill_user on skills.id = skill_user.skill_id where skill_user.user_id = 1)' and am using swagger by the way it returns this "withTimestamps": false
class User extends Authenticatable{
protected $table = "users";
public function skills()
{
return $this->belongsToMany(Skill::class);
}
}
and
class Skill extends Model
{
public function User()
{
return $this->belongsToMany(User::class);
}
}
and the pivot table
class EmployeeSkill extends Model
{
protected $table = "employee_skills";
protected $fillable = [
'employee_id', 'skill_id', 'note'
];
}
Your pivot table should be named skill_user (singular) following the model name they belong to. And you don't need a EmployeeSkill model for this relation to work, you only need the table.
As said in the documentation:
to determine the table name of the relationship's joining table, Eloquent will join the two related model names in alphabetical order. However, you are free to override this convention. You may do so by passing a second argument to the belongsToMany method
And then you should exclude this line:
protected $table = "employee_skills";
change your table name to skill_user
And in your pivot table you should use user_id as a foreign key
You can retrieve all skills from a user by doing this:
$user = User::find(1);
$user->skills();
This will give you all the skills from the user with the id 1
Be aware that you can use any table name and any foreign key name but if you do that you need to specify the names on the relations. So i recommend you doing what i 've told you, since is the standard way
Have three tables / models:
Clients:
id - client
Brands:
id - brand
BrandModels:
id - model - brand_id
BrandModelClients:
id - brandmodel_id - client_id
I would like to get a "group by" clients list based on the brands in the cleanest way. Right now, I'm doing it in a dirty way.
So the point is that if I have a client who has three different cars of the same brand, get just one client element.
I not getting a proper structure of your database, but you should use eloquent relation like below: for more read eloquent-relationships
Class Brand extends Model{
public function models(){
return $this->hasMany('App\BrandModel', 'brand_id');
}
}
Class BrandModel extends Model{
public function clients(){
return $this->hasMany('App\BrandModelClient', 'brandmodel_id');
}
}
Class BrandModelClient extends Model{
public function client(){
return $this->hasOne('App\Client', 'client_id');
}
}
$brands = Brand::with('models.clients.client')->get();
Fixed with two queries this way:
//One to get all models
$models_list = BrandModel::whereIn('brand_id', $list_fav_brands)->get()->pluck('id','model');
//Second to get the clients
$client_list = BrandModelsClient::whereIn('brands_model_id', $models_list)->with('client')->get()->pluck('client.id','client.name');
Let's say I have a webapp where users can follow other users.
In my database, I have a User table, and a Following table.
The Following table just has two values: a followingUserId and a followedUserId.
In Java, I have a User class. Most tutorials I see involve one object containing a set of objects it's related to. So many tutorials can describe how to have Users have a set of users following that user, and a set of users followed by a user. But that would require a lot of memory.
I'm thinking of an alternate structure where a User object has no info about following. Instead, there is a Following object that looks like this
#Entity
#Table(name = "Following")
public class Following {
RegisteredUser follower;
RegisteredUser followed;
}
and corresponds to the join table. When I want to get all the followers of a user, I can do a query for all Following objects with that user as the follower.
My issues are:
The Followers Table has a composite key of each of the two userids. How can I use annotations to represent that composite key? The #Id annotation denotes a single variable as the key
How can I do such a query?
If it's relevant, I am using MySQL as the db
If using JPA > 2.0, you can mark relationships as your ID:
#Entity
#Table(name = "Following")
#IdClass(FollowingId.class)
public class Following {
#Id
RegisteredUser follower;
#Id
RegisteredUser followed;
}
public class FollowingId implements Serializable {
private int follower;
private int followed;
}
the types within the followingId class must match the type of the RegisteredUser Id. There are plenty of more complex examples if you search on JPA derived ID.
For queries, it depends on what you are looking for. A collection of followers for a particular user could be obtained using JPQL:
"Select f.follower from Following f where f.followed = :user"
When I try to access articles vie category it works properly here is category.php model
public function articles(){
return $this->belongsToMany('App\Article');
}
but when I try to access category name view article it doesn't work as it's supposed to, I made I mistake there and trying to fix it, but no luck so far. here is the Article model
public function category(){
return $this->hasOne('App\category');
}
and there is a table for relation those two to each others it's called article_category in page where I get all articles for the given tag, I want to do something like $article->category->name there is something sound very wrong to me but I can't figure it out.
The error I'm receiving is
Column not found: 1054 Unknown column 'category.article_id' in 'where clause' (SQL: select * from category where category.article_id = 1 and category.article_id is not null limit 1) (View: C:\wamp64\www\loremipsum\bluhbluhbluh\articleByTag.blade.php)
Btw the way I save the relationship for the article_category when an article is created is
$article->category()->sync($request->category, false);
You've said that article might have only one category. In this case, delete pivot table and add category_id into the articles table.
Then in the Article model define this relationship:
public function category()
{
return $this->belongsTo(Category::class);
}
And in the Category model:
public function articles()
{
return $this->hasMany(Article::class);
}
When you'll do that, you'll be able to access article's category with:
$article->category->name
You have the relationship established incorrectly. Remove the intermediate table and add category_id to the articles table.
Relationships are not set correctly
Category model should be like :
class Category extends Model
{
protected $table='category';
//give me all articles associated with the given category
public function articles()
{
return $this->hasMany('App\Article');
}
}
And Article model
class Article extends Model
{
protected $table='article';
//get the category associated with the given article
public function category()
{
return $this->belongsTo('App\Category');
}
}
for attaching articles to a category:
$article->category()->associate($category)->save();