In my application I want to order my posts by category in numerical order.
So I guess I need a mapping table like this:
category_id | post_id | sort_order
then setting up a kind of "Order model" with specific methods that handle it all and use this model as a relationship with the Post model.
But before I start on this project I'd like to know if there is not a Laravel package out there that does the job or another solution that I might have missed.
I'm not 100% sure, if I understand your need correctly, but I guess your posts are stored in a DB.
Then you can simply directly get the posts from DB ordered:
$posts = DB::table('posts')
->orderBy('category_id ', 'asc')
->orderBy('post_id', 'asc')
->get();
See the documentation:
https://laravel.com/docs/8.x/queries#ordering-grouping-limit-and-offset
I don't think, you need a Order model or something similar to realize this.
Related
I am making a multi-vendor ecommerce website using Laravel 7. I am trying to make an Order History page where in a single can user can view only his/her own orders. I am having a problem building the query on my OrderHistoryController. These are the codes on my controller:
$users = User::get();
$orders = Order::find($users);
return view('order-history', compact('orders'));
And I'm trying to loop $orders on my blade file. I have:
#foreach ($orders as $order)
<div>{{ $order->id}}</div>
<div>{{ $order->grand_total}}</div>
#endforeach
I am trying to pass the order id and order grand total to my view. I don't get any error however it shows a different order details from a different customer. How do I do this?
You should use MySQL (or any other database you are using) table relationships and foreign keys.
So, your orders table, should have columns id, user_id, date, and so on. The important thing is user_id column. You want to make that column a foreign key. That basically means that user_id will hold an id value from another table, in this case user. See how to make foreign key columns in laravel migrations here.
Next up is to use Laravel's built in model relationships. You can read more about them here. Basically, in your orders model you want to have a function user which returns $this->belongsTo(App\Models\User::class) and in your user model you want to have a function orders which returns $this->hasMany(App\Models\Order::class) (or whatever the namespace is for both of them).
That way, you can call $user->orders and get a collection of Order models which will contain only the orders of that particular user.
Definitely read the documentation carefully and learn basic concepts of the framework first and how relational databases function!
You can get a lot of this information just by googling it or reading the documentation of Laravel or any other framework you plan on using! Good luck learning :)
I have a bit of an issue that I've been spinning my wheels on for a little while. I have a pretty complex (and maybe not correct - or rather most efficient) data structure that I'm trying to work my way through the logic for.
I am wondering how I perform a query (orderBy) on a second relationship function on a single query. I'm not even sure if that is the right way to describe it, so here's my code:
$players = $team->players()
->wherePivot('year_id', $year->id)
->with(['stats' => function ($query) {
$query->orderBy('score', 'desc');
}])
->get();
It seems like it should be pretty straight forward, but the orderBy clause is not working. The query otherwise works (returns players and their stats). Here is how my relationships are set up:
Team -> belongsToMany Player (and vice versa)
Player -> belongsToMany Stat (and vice versa)
Each of my pivot tables that have consequence in this situation have an extra key besides the two specified tables, they also have a year_id. This is because the relationship is only relevant for a particular year, and I think this may be what is making this more complicated. So for example, my team_player table looks like this:
team_id
player_id
year_id
And my player_stat table looks like this:
player_id
stat_id
year_id
I'm not sure if this is the most efficient or best way to accomplish what I want, but it made sense at the time of build. So how can I work through this architecture to make this query work? Also, any feedback on a data structure that may work better would be appreciated too.
If I understand you correctly you want to sort all players (not stats), you will need to join the tables:
$players = $team->players()
->wherePivot('year_id', $year->id)
->with(['stats'])
->join('stats', 'stats.player_id', '=', 'players.id')
->orderBy('stats.score', 'desc')
->get();
$players = $team->players()->wherePivot('year_id', $year->id)->with('stats')->orderBy('stats.score', 'desc')->get();
Lets say I have three models: Post, Category and Tag.
The Post belongsTo Category and Category hasMany Post.
Theres manyToMany relation between Tag and Category.
I want to list my posts by Category name and paginate the results.
Post::with('category','category.tags')
->orderBy('category.name') //this is the bogus line
->paginate(10);
But this syntax doesn't work.
What I tried is this as:
Post::select('categories.*')
->join('categories','posts.category_id','=','categories.id')
->orderBy('categories.name)
->paginate(10);
But then I lose the eager loaded data.
If I drop the select() clause then I get rubbish data as categories.id overwrites posts.id. See here.
Is there any elegant way to solve this issue? After spending hours on this I'm one step away from iterating through paginated posts and 'manually' loading the relations as:
foreach($posts as $post) {
$post->load('category','category.tags');
}
Not even sure if there's downside to this but it doesn't seem right. Please correct me if I'm wrong.
UPDATE on last step: Eager loading on paginated results won't work so if I go that road I'll need to implement even uglier fix.
You should be able to use both join and with.
Post::select('posts.*') // select the posts table fields here, not categories
->with('category','category.tags')
->join('categories','posts.category_id','=','categories.id')
->orderBy('categories.name)
->paginate(10);
remember, the with clause does not alter your query. Only after the query is executed, it will collect the n+1 relations.
Your workaround indeed loses the eager loading benefits. But you can call load(..) on a collection/paginator (query result) as well, so calling ->paginate(10)->load('category','category.tags') is equivalent to the query above.
I am using laravel 5.2 I have a question. There is Post model and Comment model. I want to get all posts with comments, whether they have comments or not. And I want to order posts by their comments, such as posts have comments are front, posts don't have comments are behind. How do I finish this? Thanks.
You can use withCount and order them by comments count as:
$posts = Post::withCount('comments')
->orderBy('comments_count', 'desc')
->get();
This will order the posts which have comments at first place and rest will follow it.
To count the number of results from a relationship without actually
loading them you may use the withCount method, which will place a
{relation}_count column on your resulting models.
I'm a bit confused about how to do the following.
I have a table of articles and a table of tags with a many to many join and a pivot table between the two. I've got the relationships set up in the models
An articles can have more than one tag.
How can I easily(?) obtain a list of related articles for an article based on the tags attached to the current article.
I've tried querying from the tags side as follows:
foreach($article->tags()->get() as $tag) {
$relatedArticles .= Tag::with('articles')
->where('id','=', $tag->id)
->take(6)
->get();
}
This produces a nil response
I'm not sure about how to query from the articles to find articles with the tags dynamically.
So if an article has attached tag1 and tag2 I then want to retrieve all articles which have either tag1 or tag2 attached to them (ideally sorted on article date). The tags will be different for each article and may just be one or many.
Ideally i'd like to do this with an eloquent query but not essential - I'm not sure how to do in mysql either as a starting point.
Any help appreciated
Provided you are using Laravel 4.1, you can do something like this using the whereHas eloquent method:
$tag_ids = $article->tags()->lists('id');
$relatedArticles = Article::whereHas('tags', function($q) use ($tag_ids) {
$q->whereIn('id', $tag_ids);
})
->orderBy('created_at')
->take(6)
->get();
Breakdown
There's a few things going on here:
lists()
You can use the lists method on a select to get just a particular column, we're only concerned with the ID column in this case.
More info here: http://laravel.com/docs/queries#selects
whereHas()
We're using the new whereHas method which you can read.
More more about here: http://laravel.com/docs/eloquent#querying-relations
use()
Since the whereHas method accepts a closure (or 'anonymous function'), the function doesn't have any access to variables set externally, so we need to send them through to the function. We can do this with use.
More information here: http://www.php.net/manual/en/functions.anonymous.php