I got some missing data from relationship query from specific id
I have 2 tables articles and comment
There is the model
Article :
class Article extends Model {
public $fillable = [
'title',
'description',
];
public function comments(){
return $this->hasMany(Comment::class, 'article_id');
}
}
Comment
class Comment extends Model {
public $fillable = [
'comment',
'article_id',
'user_id',
];
public function article(){
return $this->belongsTo(Article::class, 'article_id');
}
}
There is my query on getting all articles with comments:
Article::with('comments')->get();
This return all article but the comments missing; then i tried to update manualy the article_id on database for the comment table, this return all data well;
The things crazy about it, in others table and their relationships, there is somethink like, in get all, Some row data got his relationship data and other row has no relationship data in the same query while these data exist.
example i got:
[
{
id: '1',
name: 'name',
comments: [
{
id: '1',
name: 'name',
article_id: '1'
}
]
},
{
id: '2',
name: 'name',
comments: []
}
]
While in database this object with id 2 have data in his relation, and the object with id 1 get his relation foreign key updated manualy.
I use laravl 6.2, i don't know if it's related
Related
In my (Laravel) application receive a JSON which looks like:
{
"name": "order 1",
"customer": "cus123",
"orderItems": [
{
"amount": 1,
"name": "cola",
"price": "2.10"
},
{
"amount": 3,
"name": "fanta",
"price": "2.00"
},
]
}
I have create 2 models in Laravel, one Order and one OrderItem. I want to parse the received JSON to one Order instance $order.
I can get this done so by doing this in my OrderController:
class OrderController extends Controller
{
public function store(Request $request) {
$order = new Order();
$order->forceFill($request->toArray());
}
}
It's possible to access properties now like $order->name and $order->customer in the store function of the controller. When i access the $order->orderItems i receive an array with "orderItemsbut as array, not as instance ofOrderItem`.
I want that $order->orderItems returns an array of OrderItem instances. I tried the following in Order but this does not work as 'orderItems' is not a OrderItem::class but is an array with multiple "OrderItems".
protected $casts = [
'orderItems' => OrderItem::class,
];
How can i achieve that $order->orderItems returns an array of OrderItem instances?
Thanks for any help in advance!
Try to add the following to your controller
validation
manual storing your Order
manual storing each of your order items
.
class OrderController extends Controller
{
public function store(Request $request)
{
$your_rules = [
'name' => 'required|string',
'customer' => 'required|string', // related to customer id ?
'orderItems' => 'array',
'orderItems.*.name' => 'string',
'orderItems.*.amount' => 'integer|gte:1',
'orderItems.*.price' => 'numeric|between:0,99.99',
];
$validated = $request->validate($your_rules);
$order = Order::create([
'name' => $validated['name'],
'customer' => $validated['customer'], // is this customer id or name ?
]);
// I assume you already declare relationship to OrderItem inside your Order model
foreach ($validated['orderItems'] as $orderItem) {
// this array only is optional
$orderItem = Arr::only($orderItem, ['name', 'amount', 'price');
$order->orderItems()->save($orderItem);
}
// reload saved order items
$order->load('orderItems');
dd($order);
}
}
You can also create multiple children in single command.
$order->orderItems()->saveMany([
new OrderItem(['name' => '...', ... ]),
new OrderItem(['name' => '...', ... ]),
]);
Read here for more info https://laravel.com/docs/9.x/eloquent-relationships#the-save-method
You can move this into your model as extra custom method.
For example:
public function saveOrderItems(array $orderItems): void
{
$this->orderItems()->saveMany($orderItems);
}
And you call it as $order->saveOrderItems($orderItems);
P.S.
Dont forget to declare relationship in Order model.
public function orderItems()
{
return $this->hasMany(OrderItem::class);
}
I think you are confuse with the whole Model relationship. Checkout the documentation here, you need to define proper relationship and foreign key between your Order and OrderItem model.
Then your model should be like this;
//Order.php
class Order extends Model {
protected $fillable = [
'name',
'customer',
];
public function items() {
return $this->hasMany(OrderItem::class);
}
}
//OrderItem.php
class OrderItem extends Model {
protected $fillable = [
'amount',
'name',
'price'
];
public function order() {
return $this->belongsTo(Order::class);
}
}
Then your store method
public function store( Request $request ) {
$request->validate([
'name' => 'required',
'customer' => 'required|exists:customers_table,id',
'orderItems' => 'required|array'
]);
$order = Order::create( $request->except('orderItems') );
$items = $order->items()->createMany( $request->input('orderItems') );
}
I am facing an error with Prisma, it does not recognize my request which seems quite simple to me. I need to use "select" to retrieve only certain fields from the table.
Post model:
model Post {
id String #id #default(cuid())
title String
createdAt DateTime? #default(now())
categories CategoriesOnPosts[]
keywords KeywordsOnPosts[]
##map("posts")
}
Category model:
model Category {
id String #id #default(cuid())
name String
createdAt DateTime? #default(now())
posts CategoriesOnPosts[]
##map("categories")
}
CategoriesOnPosts model:
model CategoriesOnPosts {
postId String
categoryId String
post Post #relation(fields: [postId], references: [id])
category Category #relation(fields: [categoryId], references: [id])
##id([postId, categoryId])
##map("categoriesPosts")
}
My Prisma query:
export const getPosts = async () =>
await prisma.post.findMany({
select: {
id: true,
title: true,
categories: {
select: {
name: true,
slug: true,
},
},
createdAt: true,
},
orderBy: [
{
createdAt: 'desc',
},
],
});
I get the following error and I don't know how to fix it.
Unknown field categories for select statement on model Post.
Available options are listed in green.
I need Sql query for this case
here is my code here is my code
here is my controller query
my query is:
Post.query().preload('reactions')
here is my model relation
#hasMany(() => Post,{
localKey :'id',
foreignKey : 'reaction_id',
onQuery: (query) => {
query.select('id','reaction','chat_id',
Database.raw('Count(*) as total_likes')
)
.groupBy('reaction')
}
})
public reactions : HasMany<typeof Post>
posts table columns
id,
post
reactions table columns
id ,
user_id ,
reaction,
post_id
For my case I need the data in the below format
Any one please give me raw query for this case ?
post_lists=[
{
id:1,
post:'Hello everyone',
reactions:[
{
reaction:'like',
total_count:2
},
{
reaction:'love',
total_count:2
}
]
},
{
id:1,
post:'Hello everyone',
reactions:[
{
reaction:'like',
total_count:2
},
{
reaction:'angry',
total_count:2
}
]
},
.........
]
In my case my query return wrong result
I'm new to Eloquent and struggling mightily with the following.
In my database (mysql 5.7), there are 2 tables and structured as below.
article:
{
_id: 1,
title: "xxx",
content: "xxx",
tag_ids: [
4,
5
]
}
tag:
{
_id: 4,
tag: "tag1"
}
In ArticleModel, has a cast
protected $casts = [
"tags" => "array"
];
It is possible to make a many to many relationship without a middle table?
Any help would be greatly appreciated!
I created a package with JSON relationships: https://github.com/staudenmeir/eloquent-json-relations
You can create a many-to-many relationship like this:
class Article extends Model
{
use \Staudenmeir\EloquentJsonRelations\HasJsonRelationships;
protected $casts = [
'tag_ids' => 'array'
];
public function tags()
{
return $this->belongsToJson(Tag::class, 'tag_ids');
}
}
class Tag extends Model
{
use \Staudenmeir\EloquentJsonRelations\HasJsonRelationships;
public function articles()
{
return $this->hasManyJson(Article::class, 'tag_ids');
}
}
As of right now, I'm working on a Laravel-5 project and I would like to build some sort of activity log. I do have a query that combines multiple tables and gives me the data I need, but as soon as I try to put the data on screen, things go wrong.
This is the query I am using right now in me ProfileController:
$activity = DB::select("SELECT user_id, created_at, source, project_id
FROM (
SELECT id as project_id, user_id, created_at, 'project' as source FROM projects
UNION ALL SELECT project_id, user_id, created_at, 'comment' as source FROM comments
UNION ALL SELECT project_id, user_id, created_at, 'favorite' as source FROM favorites
UNION ALL SELECT project_id, user_id, created_at, 'like' as source FROM likes
) as a
WHERE user_id = $id
ORDER BY created_at DESC");
This is what the code in my profile.blade.php looks like:
<ul class="list-group">
#foreach($activity as $act)
#if($act->source == 'project')
<li class="list-group-item">{{ $act->user_id }} added a new project: {{ $act->project_id }}</li>
#elseif($act->source == 'like')
<li class="list-group-item">{{ $act->user_id }} likes {{ $act->project_id }}!</li>
#elseif($act->source == 'comment')
<li class="list-group-item">{{ $act->user_id }} commented on {{ $act->project_id }}</li>
#elseif($act->source == 'favorite')
<li class="list-group-item">{{ $act->user_id }} has {{ $act->project_id }} to his favourites!</li>
#endif
#endforeach
</ul>
And this is what my models look like:
class Project extends Model
{
protected $fillable = [
'title',
'description',
'user_id',
'snapshot',
'views'
];
public function creator() {
return $this->belongsTo('App\User', 'user_id', 'id');
}
public function tags() {
return $this->belongsToMany('App\Models\Tag');
}
}
class Likes extends Model
{
protected $fillable = [
'user_id',
'project_id'
];
public function like() {
return $this->belongsTo('App\User', 'user_id', 'id');
}
public function project() {
return $this->belongsTo('App\Models\Project', 'project_id', 'id');
}
}
class Comment extends Model
{
protected $fillable = [
'user_id',
'project_id',
'comment'
];
public function poster() {
return $this->belongsTo('App\User', 'user_id', 'id');
}
public function project() {
return $this->belongsTo('App\Models\Project', 'project_id', 'id');
}
}
class Favorite extends Model
{
protected $fillable = [
'user_id',
'project_id'
];
public function favorite() {
return $this->belongsTo('App\User', 'user_id', 'id');
}
public function project() {
return $this->belongsTo('App\Models\Project', 'project_id', 'id');
}
}
Now I do know that I am only asking to give me the user_id or project_id on my Blade page, I did this because something like $act->creator->name or $act->project->title would give me an error like:
Undefined property: stdClass::$creator
or
Undefined property: stdClass::$project
I do get that this might have to do something with the way I build my query and that mixing tables this way might have made things more difficult than they should be, but I can't seem to find a way to build this query in Eloquent or to find a way to reach the data that belong to these user_id's and project_id's without having to use the public functions I've created in my models.
With the current setup, you cannot benefit from the Laravel models, as you need to loop through different models. My recommendation is to build a new table called Activity, with 3 columns: id, type, user_id. And use Polymorphic relationship.
Also, you can benefit from Events/Listeners, in order to create the records in the Activity table. You can benefit from the Queued Listeners, so the Activity records are not created online, if this won't impact your customer experience.