I have a customer table and a user table, they have a M:M relationship set in user_has_customer.
The entire application is a Rest API, and i use extraFields() and GET customers?expand=users to get the connected users when looking at customers.
user_has_customer stores some additional information on when the user was assigned to the customer and a few other fields, and several fields can have the same combination of user and customer. To be able to update or delete a relation, I need the relation id (user_has_customer.id) to be visible when looking at customers.
This function will return the customer, and its related users:
public function getUsers() {
return $this->hasMany(User::className(), ['id' => 'user_id'])
->viaTable('user_has_customer', ['customer_id' => 'id'])
->select(['id', 'username']);
}
This function will return the user-customer relationship:
public function getUserRelations() {
return $this->hasMany(UserHasCustomer::className(), ['customer_id' => 'id'])
->select(["id",
"customer_id",
"user_id",
"created_by",
"created_at"]);
}
But i would like to know how i can nest these relations, so the result looks like this:
{
"id": 11148,
....
"users": {
"id": 1,
"user_id": 1,
"added": "2017-08-01 22:23:24"
"user": {
"id": 1,
"username": "admin"
}
}
}
or even like this (like a MySQL join):
{
"id": 11148,
....
"users": {
"id": 1,
"user_id": 1,
"added": "2017-08-01 22:23:24"
"username": "admin"
}
}
For some reason this will not work (the created SQL is correct, but the AR refuse to show the fields from user in the result):
public function getUserRelations() {
return $this->hasMany(UserHasCustomer::className(), ['customer_id' => 'id'])
->joinWith('user', true)
- ->select('*');
}
Related
I have to make this JSON response which every product has colors and each color has many images
[
{
"id": 1,
"name": "shirt",
"descriptions": "lorem epsum",
"colors":[
{
"color_name":"red",
"icon":"1.jpeg",
"images": [
{
"url": "1.png"
},
{
"url": "2.png"
},
{
"url": "3.jpeg"
}
]
},
{
"color_name":"blue",
"icon":"1.png",
"images": [
{
"url": "1.png"
},
{
"url": "2.png"
},
{
"url": "3.png"
}
]
}
]
}
]
How can I make the colors using eloquent relationships?
how many tables and columns with foreign keys should I create?
Here you've to make three tables
products -> Product.php(Model name)
id
name
descriptions
created_at
updated_at
colors -> Color.php(Model name)
id
product_id
color_name
created_at
updated_at
3) images -> Image(Model name)
id
color_id
url
created_at
updated_at
Three model with relationship.
Product.php Model
class Product extends Model
{
protected $table = "products";
//get colors
public function colors(){
return $this->hasMany('App\Color','product_id','id');
}
}
Color.php Model
class Color extends Model
{
protected $table = "colors";
//get product
public function product(){
return $this->belongsTo('App\Product','product_id','id');
}
//get images
public function images(){
return $this->hasMany('App\Image','color_id','id');
}
}
Image.php Model
class Color extends Model
{
protected $table = "images";
//get color
public function color(){
return $this->belongsTo('App\Color','color_id','id');
}
}
Now from product model you can access this colors and images
Controller
$products = App\Product::with('colors.images')->get();
return \Response::json($products->toArray());
I want to get the average rates for each product.
I have a rates table which has a foreign key to product table,
the rates table is similar to this
when I try to get products with this code:
$stocks = Stocks::with('images:url,color', 'tags:tag', 'sizes', 'rates')
->get()
->pluckDistant('tags', 'tag')
->pluckDistant('sizes', 'size');
it returns this
[
{
"id": 10,
"name": "name",
"image": "1564964985mI7jTuQEZxD49SGTce6Qntl7U8QDnc8uhVxedyYN.jpeg",
"images": [
{
"url": "1564964985mI7jTuQEZxD49SGTce6Qntl7U8QDnc8uhVxedyYN.jpeg",
"color": ""
},
{
"url": "1564964985EV20c1jGvCVCzpCv2Gy9r5TnWM0hMpCBsiRbe8pI.png",
"color": ""
},
{
"url": "1564964985iFcMox6rjsUaM8CHil5oQ9HkrsDqTrqLNY1cXCRX.png",
"color": ""
}
],
"tags": [
"عطور"
],
"sizes": [],
"rates": [
{
"id": 1,
"stocks_id": 10,
"rate": 2
},
{
"id": 2,
"stocks_id": 10,
"rate": 4
}
],
}
]
How can I get the average of rates as "rates":3 using the eloquent relations to get them all by sql without php proccessing?
You could leverage something like Appending. Say you have a Product model which has a OneToMany relationship with Rate model.
Your Product model would look something like this:
class Product extends Model
{
protected $with = ['rates'];
protected $appends = ['average_rate'];
public function getAverageRateAttribute()
{
return $this->attributes['average_rate'] = $this->rates->avg('rate');
}
public function rates() {
return $this->hasMany(Rate::class);
}
}
Now anytime you query your products from the database, you'll have the rate appended with the result.
array:7 [▼
"id" => 1
"created_at" => "2019-08-12 14:08:09"
"updated_at" => "2019-08-12 14:08:09"
"average_rate" => 4.5
"rates" => array:2 [▶]
]
However, be aware of causing n+1 problem. If you're using this approach make sure to always eager load your rates.
You could just use join and use aggregate function on rates table.
Stocks::with('images:url,color', 'tags:tag', 'sizes')
->join('rates', 'rates.stocks_id', '=', 'stocks.id')
->selectRaw('stocks.*')
->selectRaw('AVG(rates.rate) as average_rating')
->selectRaw('tags.*')
->selectRaw('sizes.*')
->selectRaw('images.*')
->groupBy('stocks.id')
->get()
i have api that returns my data. i have a conditions that if visible==1 then return data otherwise don't return any thing.
but what i have receive is this
{
"data": [null, {
"order": 2,
"path": "http:\/\/controlpanel.test\/uploads\/7bb61115dd77823d8e8e3f2b6afa401b.png",
"visible": 1
}]
}
i want this to be return
{
"data": [{
"order": 2,
"path": "http:\/\/controlpanel.test\/uploads\/7bb61115dd77823d8e8e3f2b6afa401b.png",
"visible": 1
}]
}
without null.
this is my code
if($this->visible==1){
return [
'order' =>$this->order,
'path' => asset('uploads').'/' . $this->path,
'visible'=> $this->visible,
];
}
You need to define FK for post() relation in your comments model like
public function post(){
return $this->belongsTo('App\Posts' , 'post_id');
}
Using App\Posts name convention laravel is looking for posts_id not post_id
update your post model also as
public function comments(){
return $this->hasMany('App\Comment', 'post_id');
}
You have Posts model so while in relation, it search for posts_id in the table attribute.
you can solve the problem using either of the following
update the comment module
public function post(){
return $this->belongsTo(Posts::class , 'post_id');
}
Update the model name
from Posts to Post
The following image describes my model relationship between User and Room.
There is a Many to Many relationship between them,
and I have resolved the Self Reference issue by JSON.NET
and adding some configurations to the Application_Start function.
It looks like:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
JsonConvert.DefaultSettings = () => new JsonSerializerSettings
{
Formatting = Newtonsoft.Json.Formatting.Indented,
ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
};
}
I defined a API like this to return All the users in database as Json.
public ActionResult Index()
{
return Content(JsonConvert.SerializeObject(db.UserSet), "application/json");
}
The point is , when I get a JsonResult , it looks like
(Every "User" has a navigation attribute "Room" )
[
{
"Room": [
{
"User": [
{
"Room": [],
"Id": 3,
"Name": "waterball",
"Account": "pppaass",
"Password": "123"
}
],
"Id": 1,
"Name": "sadafsa"
}
],
"Id": 2,
"Name": "waterball",
"Account": "safasfasd",
"Password": "123"
},
{
"Room": [
{
"User": [
{
"Room": [],
"Id": 2,
"Name": "waterball",
"Account": "safasfasd",
"Password": "123"
}
],
"Id": 1,
"Name": "sadafsa"
}
],
"Id": 3,
"Name": "waterball",
"Account": "pppaass",
"Password": "123"
}, ........
Obviously , the result looks complex ,
How can I get only the Id,Name but NO User attributes of each Room ?
Or what exactly is the common way people handle with this problem?
===========================================================
I have changed my codes to reach my requirement,
but is this actually the common way to resolve this...?
Or does it have some potential problems?
public ActionResult Index()
{
var result = from u in db.UserSet
select new
{
Id = u.Id,
Account = u.Account,
Password = u.Password,
Room = from r in u.Room
select new
{
Id = r.Id,
Name = r.Name
}
};
return Content(JsonConvert.SerializeObject(result), "application/json");
}
i want consume a WEB API by constructing a nested json Object.
i have two entities Class AND Student
i want the JSON output looks Like This Construction
[
{
"ClassId": 1,
"ClassName": "Class A",
"Students": [
{
"StudentId": 1,
"StudentName": "student 1"
},
{
"StudentId": 2,
"StudentName": "student 2"
}
]
},
{
"ClassId": 2,
"ClassName": "Class B",
"Students": [
{
"StudentId": 3,
"StudentName": "student 3"
},
{
"StudentId": 4,
"StudentName": "student 4"
}
]
}
]
i'm facing a problem when i'm trying to manipulate the student data inside of class Data.
i'm trying this code but it gives me an error.
public IQueryable<tbl_mosque> Gettbl_mosque()
{
var Classes = db
.Class
.Include("Students")
.Select(t => new Class
{
id = t.Id,
name = t.Name,
student = t.students.Select(p => new student
{
Id = p.id,
Name = p.Name
})
}).ToList();
return Classes;
}
You just need
return db.Class.Include("Students").ToList();
Include means that engine should include Students on materialization.
P.S. You should mention error and stack trace you have got in your question.
UPDATE
In case if haven't relation between related (in the domain semantic) table you can use JOIN.
As you have one to many relation, this can help:
var classes = db.Classes.GroupJoin(db.Students, c => c.Id, s => s.ClassID,
(c, s) => new {Class = c, Students = s});
Here classes is a list of objects of anonymous type which consists of the Class object and related with him Students.
I can't test it now, but you can join them like follow:
var joined = classesList.Join(studentsList,
_class => _class.Id, _student => _student.ClassId,
(_class, _student) => new Class
{
id = _class.Id,
name = _class.Name,
student = new student
{
Id = _student.id,
Name = _student.Name
})
});