How to list related blog posts in OctoberCMS - laravel

I am building an App with OctoberCMS and wanted to list related blog posts at the bottom of each post page basing on categories. I figured out rainlab_blog_posts table does not have a foreign key pointing to blog categories table. To achieve what wanted I thought of extending the blog_posts table and added category_id as foreign key using a plugin. I defined foreign key constraints in table migration. Everthing seem to be fine. My challenge is, How can I insert category id in posts table each time a new post is created. OctoberCMS create post backend has an option where the author assigns a category to a new blog post by selecting from list. Just don't understand how to pass this category id and insert into rainlab_blog_posts table in category_id field.
This is what I want to achieve in my API:
routes.php
use Rainlab\Blog\Models\Post;
Route::get('apiv1/related-posts/{postid}',function($id)
{
$post = Post::where('id',$id)->first();
$posts = Post::where('category_id',$post->category_id)
->where('id','!=',$id)
->orderBy('views','desc')
->get()->take(5);
return $posts;
});
Or if there is a better way of achieving this will appreciate. Cheers!

Hmm seems something wrong here,
As first I can see from Blog Plugin that Blog <=> Category it is MM relation so you will not find category_id in rainlab_blog_posts table as all relation is maintained by this mm-relation table rainlab_blog_posts_categories.
So I think you will select only one category for blog so you can get related blogs for only that category. [ assuming from your code and description ]
we can utilize relationships for that.
So your code can look like this
use Rainlab\Blog\Models\Post;
Route::get('apiv1/related-posts/{postid}', function($id)
{
$post = Post::where('id',$id)->first();
// we need this because there will be mm relation so
// we fetch first category and this will be based on
// [ name sorting - does not matter as there will be only one cat. ]
$firstCategory = $post->categories()->first();
// now we fetch only that post which are related to that category
// but we skip current post and sort them and pick 5 posts
$posts = $firstCategory->posts()
->where('id', '!=', $id)
->orderBy('views','desc')
->limit(5) // use limit instead of take()
->get();
// use limit instead of take() as we don't need extra data so
// just put limit in sql rather fetching it from db then
// putting limit by code - limit() is more optimised way
return $posts;
});
Good thing now you don't need to add that category_id field on rainlab_blog_posts. So, I guess now you Also don't need to worry about adding it during post insertion.
if any doubts please comment.

Incase you simply want to display related blog posts without having to customize the blog database, there is an OctoberCMS plugin called Related Articles
that requires rainlab blog plugin. It will display all the other articles belonging to the post's category.
On your Backend menu, go to settings,on System, go to Updates and Plugins.
Go to Install plugins. Search for plugin Related articles. The creator is Tallpro. Install it.
Go to CMS. On the page you want related articles, go to components and drag Related articles. Save and preview it. You can also fork the component to edit how you want your related articles to be displayed. You will find more information on the documentation.
If you encounter any problems feel free to inquire or you can check out the plugin reviews for problems faced and their solution.

Related

How to Get Order Details per a single User in Laravel 7

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 :)

How to order by the number of relationships

I am trying to create a "tag cloud" that lists the tag with the most relationships on a many-to-many pivot table schema.
I'm afraid I don't even know what to search in order to begin. I would appreciate any links or code examples, but prefer references so I can learn this once and for all.
I have a table named companies and a table named categories. There is a pivot table named category_company and the proper relationships are setup and working great.
Simply using withCount() should get you there.
$companies = Company::withCount('categories');
Now you are able to access the count like so.
foreach ($companies as $company) {
$company->categories_count; // gives out the count for this companies categories.
}
See the docs.

Multi categories posts

I'm using laravel 5.6 and i have two tables categories and posts
I have created category_id in posts table which looks like
{id, category_id, title, description, created_at, updated_at}
I created a drop-down on the post create and edit form to select the category which works fine.
Now I am looking for something more advanced where a post can have multiple categories. I have changed belongTo to HasMany categories in post model.
I feel I am doing it the wrong way. Do i need to create another table i.e.,
post_categories
{id, category_id, post_id}
The reason i want to do this is because i have multiple posts which belong to multiple categories and my route is like this
site.com/categoryname/post-slug
So few posts appear in multiple categories.
You probably will need to use the pivot table. That way you can data mine. Even if you don't have a multi-select, you'll easily be able to collect posts linked to categories and vice versa. laraveldaily-good example. They use the sync method, one of my favs. when you save the form data you can just do something like App\Post::find($id)->categories()->sync(request()->input(categories')) and laravel will handle the rest for you.
Your relationships look like they are thought out. to me, it looks like your on the right track.
Just use the belongsToMany relationship instead of HasMany
Laravel has great documentation on this: laravel many to many

Laravel Search Model

Im new to laravel and have completed a project on the latest version laravel 5.6
However, the only thing that is pending to learn and implement is the search functionality which is the core of every application. The application i have coded is a huge project and i do not want to mess it up so would like to learn how search functionality works in order to implement in multiple sections of the project.
Let's say i have a the following models 1.Country 2.State 3.City 4.Professional_Categories 5.Professionals and i have added the relations in the models accordingly
I fetch the records normally using the following code
public function index()
{
$categories = ProfessionalCategory::all();
$topprofessionals = Professional::where('status', 1)->limit(12)->get()->sortByDesc('page_views');
$professionals = Professional::where('status', 1)->latest()->paginate(9);
return view('professionals.index',compact('professionals', 'categories', 'topprofessionals'));
}
I can pull up Countries, States and Cities as i pulled in categories and with foreach i can display them in the select box. Or i could use pluck('name', 'id') that works good too. But i have never tried search queries.
I want a search form on the professionals page where a user can select country, state, city, category and type keywords in locality and professional name to find the professionals. My next step would be to learn dependent dropdown for country, state and city.
And how the results can be displayed on the view file where im currently fetching records with foreach($professionals as $professional)
I do not need code, but just a basic example on how these kind of things work in laravel. Once i learn the basics i want to implement auto suggest from database and things like that. And a single form to search all the models.
It sounds like you'll need full text searching across a number of tables and associated columns. I'd recommend using Laravel Scout or a similar service (such as elastisearch) for this.
These will index your records in a way to allow for fast and efficient fuzzy searching. Using Scout as an example, you can directly query on your models like:
$orders = App\Order::search('Star Trek')->get();
Searching with Scout
This will save you from writing numerous queries using LIKE which becomes very slow and inefficient quite quickly.
Using Eloquent you might do something like this in your Controller:
public function search(Request $request)
{
$countries = Country::where('name', 'like', '%' . $request->search_value . '%')->get();
}
This will return the countries whose name contains the search_value provided by the user.

laravel eloquent get related articles based on a tag

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

Resources