Laravel > route, filter URL against database - laravel

I'm trying to build the new version of our site with the Laravel 5 framework.
The problem is, we have now the following site structure (and this may not be changed):
domain.com/[productname] <- dynamic
domain.com/[categoryname] <- dynamic
domain.com/some-static-page1
domain.com/some-static-page2
....
In our database, we have a list of different product names and different categories.
I want to route the [productname] to a productController and the [categoryname] to the categoryController. But therefor, i need query our database with each request to see if the URL parameter is either a product or a category.
Any ideas to get me on right direction?
Thanks in advance!

I think this would be the best way to do it:
Route:
Route::get('/cat={name}', 'CatagoryController#cataFind');
Route::get('/prod={name}', 'ProductController#prodfind');
Controller:
public function cataFind($name){
//get all the rows with that cata
$catas = Product::where('cata', $name)->get();
return view('cata')->with('catas', $catas);
}
public function prodFind($name){
//get all the rows with that prod name
$prod = Product::where('name', $name)->get();
return view('prod')->with('prod', $prod);
}
If you need any exsplnation on what's going on,, then just comment and I'll update the post. But this is the path you should be taking I should of thought!

Related

Get latest 10 products gives me the last product 10 times in Laravel8

I am trying to create a New Arrivals section at the home page, but I have the following issue:
This is my controller:
public function home() {
$products = Product::get();
$newArrivals = Product::orderByDesc('id')->take(10)->get();
return view('client.home')->with('products', $products)->with('newArrivals', $newArrivals);
}
I am ordering using id because I did a stupid mistake at the beginning by deleting the created_at column and I have around 1000 products now. The problem is, I am expecting to get the last 10 products but instead I am getting the last product 10 times. Do you guys have any work around for that without relying on created_at?
You can add the following in your base model to ignore created_at
public $timestamps = false;
or
const CREATED_AT = NULL;
Latest() is a built-in method to handle some common practices.
$newArrivals = Product::latest()->take(10)->get();
I managed to solve it, as #N69S suggested, it was a mistake in my blade view.

How to search for all associations in a relationship tree in Laravel?

I'm having a problem. I have tables that relate:
internal_clients->subsidiaries->departments->job_titles->users
I also have their respective models.
My doubt is:
How do I get all the data associated with users from the top of the tree (internal_clients)
?
I'm trying to follow the Laravel documentation using hasManyThrough.
However, in the documentation it explains only how to do it in a chain of three tables. They teach how to place an intermediate table (model) as the second parameter of the hasManyThrough method (BaseClasse::class, IntermediaryClass::class).
However, in my case that has several tables between users and internal_clients, how would I do this? What would be the intermediate table?
I would like to make a query that returns the user's internal_client, subsidiary, department and jobTitle (associated with users).
I'm trying to do it this way:
Model InternalClient
public function users()
{
return $this->hasManyThrough(User::class, InternalClient::class);
}
Controller UserController
public function allRelations($internalClientId)
{
$internalClient = InternalClient::find($internalClientId);
$users = $internalClient->users;
return response()->json($users, 201);
}
The InternalClient id arrives at the controller above.
When I access the route, the error below is returned:
In short: I would like to know if there is a way to get all the data (from all tables that are in this hierarchical tree) that are associated with the User.
I couldn't find an answer on the Stackoverflow PT-BR.
Thank you!

Laravel eloquent query with sum of related table

I have a table users and posts with columns user_id and post_views.
In post_views I keep information how many times post was display.
And now, in query I would like to get user with sum of post_views all his posts.
I tried do something like this:
User::where(['id'=>$id])->with('posts')->get();
And in model I defined:
public function posts()
{
return $this->hasMany('App\Models\Post')->sum('post_views','AS','totalViews');
}
But without success.
How to do it?
Thank you
You can use a modified withCount():
public function posts()
{
return $this->hasMany('App\Models\Post');
}
$user = User::withCount(['posts as post_views' => function($query) {
$query->select(DB::raw('sum(post_views)'));
}])->find($id);
// $user->post_views
You can use
User::withCount('posts')->find($id)
to get the user with the id $id and a posts_count attribute in the response
I'm not fully sure what the intention of ->sum('game_plays','AS','totalVies'); is - you would need to add more context if you want this
Just something to add with regards to your shown code: No need to query by id using where + the get() at the end will make you query for a collection. If you want to get a single result use find when searching by id
As always laravel has a method for that : withSum (Since Laravel v8)
Note : I know that at the time of the message was posted, the method did not exist, but since I came across this page when I was looking for the same result, I though it might be interesting to share.
https://laravel.com/docs/9.x/eloquent-relationships#other-aggregate-functions
In your case it should be :
$user = User::withSum('posts as total_views', 'post_views')->find($id);
Then you can access to the result :
$user->total_views

Laravel Backpack : Storing Belongs To Many relationships using custom view

I have a flight class and this flight has a custom view field like so:
This represents a belongs to many relationship which stores website_id / flight_id and pricing as pivot data in a pivot table.
The custom view uses JS to send this data back to the controller in this format:
{"1":{"price_adult":"434","price_child":"545"},"2":{"price_adult":"323","price_child":"324"},"3":{"price_adult":"434","price_child":"43"}}
Trying to send this data with the request doesn't create the relations fields, and because I do not have a flight ID at the point of creating this within the controller I can not loop this JSON to make the relations manually.
Can anyone point out what the best course of action is or if there is support for this? I took a look at the docs but they are woefully short and patchy in terms of being much help.
EDIT:
I should have said I can probably make this work using a custom name attribute on the model for the relation, then add a set mutator to loop this data and update the prices relation but I don't want to go down this route if there is support for this I am missing out of the box in backpack.
EDIT2:
Someone asked about the relation:
$this->belongsToMany(Website::class, 'website_pricing')->withPivot('price_adult', 'price_child');
This is working fine its not a problem with the relation working its how can I get backpack to store the data as a relation when the flight has no ID yet, or how can I pass the data I posted above in such a way that the backpack crud controller can handle it?
You may need to create a flight first, if no flight id is being provided. Can you explain the database relational structure more?
Basically thought I should post what I did because no one could provide an answer to this.
So basically you have to copy the store / update functions from the parent, changing a few lines.
$this->crud->hasAccessOrFail('create');
// fallback to global request instance
if (is_null($request)) {
$request = \Request::instance();
}
// replace empty values with NULL, so that it will work with MySQL strict mode on
foreach ($request->input() as $key => $value) {
if (empty($value) && $value !== '0') {
$request->request->set($key, null);
}
}
// insert item in the db
$item = $this->crud->create($request->except(['save_action', '_token', '_method']));
$this->data['entry'] = $this->crud->entry = $item;
// show a success message
\Alert::success(trans('backpack::crud.insert_success'))->flash();
// save the redirect choice for next time
parent::setSaveAction();
return parent::performSaveAction($item->getKey());
Basically any line which references a function in the parent class using $this->method needs to be changed to parent::
This line is what I used to submit the relations JSON string passed to the controller as relations $item->prices()->sync(json_decode($request->input('prices'), true));
This is done after the line containing $item = $this->crud->create as the item id that just got stored will be available at that point.

SEO friendly URLs with category/subcategories/article slug? [Laravel]

First of all, I have Article model and articles table in the database. Each article can be shown using Laravel's standard URI structure: www.example.com/articles/5 (where 5 the article id.). Each article has a slug field (slug column in the articles table) , so with Route Model Binding it is easy to change this and have a slug instead of id in the URI:
In RouteServiceProvider.php I just added:
public function boot(Router $router)
{
parent::boot($router);
\Route::bind('articles', function($slug) {
return \App\Article::where('slug', $slug)->firstOrFail();
});
}
... and now I can open articles with: www.example.com/articles/this-is-some-slug .
On the other hand, each article belongs to one category. For example, let's say that there are the following categories:
Politics
Sport
Football
Tennis
ATP
WTA
Culture
I created these categories by using Baum (an implementation of the Nested Set pattern for Laravel 5's Eloquent ORM). So there is a Category model and categories table in the database:
$table->increments('id');
$table->string('name');
$table->integer('parent_id')->nullable();
$table->integer('lft')->nullable();
$table->integer('rgt')->nullable();
$table->integer('depth')->nullable();
$table->timestamps();
Of course, in articles table there is a column category_id because of One-to-Many relationship (one Article belongs to one Category, one Category can have many Articles).
All articles belonging to some category can be displayed via the following URL: www.example.com/articles/category/1 (where 1 is the id). If we add slug column to the categories table & set Route Model Binding :
\Route::bind('category', function($slug) {
return \App\Category::where('slug', $slug)->firstOrFail();
});
then we will use a slug instead of id: www.example.com/articles/category/politics (this will display all the articles belonging to the category politics).
But I would like to have URIs with the following structure:
www.example.com/sport/tennis/wta/article_slug (/category/subcategory/subcategory/article_slug)
www.example.com/politics/article_slug (/category/article_slug )
and so on...
The problem is that I have no idea how to do this with Laravel. Is it even possible? How would you solve this problem?
Thanks in advance and sorry for my bad English.
SEO friendly URLs with category/subcategories/article slug?
To produce a url that's example.com/category/subcategory/article is pretty simple, but you're obviously looking to add the complexity of multiple subcategories. For that we'll need to look at route parameter regex constraints.
Using regex in your route parameter constraints you can get the subcategories as a string eg. subcategory1/subcategory2 and then pass it via another custom binding or directly to your controller.
Here's an example of the route you need with the route parameter constraint added:
// Route to closure
Route::get('/{category}/{subcategories}/{article}', function($category, $subcategories, $article)
{
return $subcategories;
})->where('subcategories', '(.*)');
// Route to controller method
Route::get('/{category}/{subcategories}/{article}', 'ArticlesController#show')->where('subcategories', '(.*)');
And an example of a custom binding for your subcategories parameter that returns the subcategories as an array:
$router->bind('subcategories', function ($value) {
return explode('/', $value);
});
Caveat: The only problem you will run into using the route parameter bindings in the way you've described, is that the article loaded here is only dependant on the slug being correct. It will still load if the categories in the url are unrelated, which you'll need to take care of in your controller logic.

Resources