Hi i have REGION model but i dont know how rewrite this DB::select. I want it with findOrFail or something for ,,If i find this slug i show page if no i show 404
My web.php route
Route::get('/turnaje/{slug}', [RegionController::class, 'show']);
My Region Controller
public function show($slug)
{
$regions = DB::select('select * from regions where slug = ?', [$slug]);
$regions_list = DB::select('select * from regions');
return view('tournaments.show', [
'regions' => $regions,
'regions_list' => $regions_list,
]);
}
So you can use the model as a facade and write a similar query. I'm assuming you want an exception thrown when there is no region with that slug?
https://laravel.com/docs/8.x/eloquent#not-found-exceptions
public function show($slug)
{
$regions = Region::where('slug', $slug)->firstOrFail();
$regions_list = Region::all();
return view('tournaments.show', [
'regions' => $regions,
'regions_list' => $regions_list,
]);
}
You may want to handle the ModelNotFoundException
You have 2 options:
Changing route model binding form id to slug by defining getRouteKeyName function in your model:
public function getRouteKeyName()
{
return 'slug';
}
Using firstOrFail:
Region::where('slug', $slug)->firstOrFail();
Related
How do I make the post single URL like myweb.com/post-name instead myweb.com/post-id ? its works fine with posts id, but not with post name.
here my current route.
Route::get('/{id}', [App\http\Controllers\PostController::class, 'show']);
and here my controller.
public function show($id)
{
$post = post::find($id);
return view('detail', ['post' => $post]);
}
thank you.
That is because you are using the $id as the identifier to resolve the post object:
myweb.com/25
Then:
public function show($id) // $id = 25
{
$post = post::find($id); // find() search for the PK column, "id" by default
return view('detail', ['post' => $post]);
}
If you want to resolve the $post by a different field, do this:
public function show($name)
{
$post = post::where('name', $name)->first();
return view('detail', ['post' => $post]);
}
This should work for a route like this:
myweb.com/a-cool-post-name
As a side note, you could resolve the model automatically makin use of Route Model Binding.
I am able to filter the Custom Get Attribute field after retrieving it to the collection. I now need to filter before using get()
Example:
For is_paid custom attribute
//is_paid
public function getIsPurchasedAttribute()
{
//Since purchased has one relation with user
return !empty($this->purchasedRelation) ? true : false;
}
I now need to retrieve User based on is_purchased like:
public function index(Request $request){
$isPaid = $request->is_paid;
$users = User::query();
if($isPaid){
$users = $users->where('is_paid', true);
}
$users = $users->paginate(10);
return view('user.index', [
'users' => $users
]);
}
If I do like this, it will return:
Column not found: 1054 Unknown column 'is_paid' in 'where clause
Yes, I can do like but I am now unable to use paginate function:
$users = User::get();
$users = $users->where('is_paid', 1);
return view('user.index', [
'users' => $users
]);
You can return all users that have purchases by using the whereHas() method.
public function index(Request $request){
$users = User::query();
if ($request->is_paid) {
$users->whereHas('purchasedRelation');
}
return view('user.index', [
'users' => $users->paginate(10),
]);
}
If anybody stumbles upon the same error and for future reference, I am posting the method I used to solve the problem:
The created custom getAttribute can be obtained only after retrieving the model.
That is using first() or find()
You cannot filter in the query collection.
So in order to filter only is_paid attribute; I first retrieved the collection of model and filtered afterwards like:
public function index(Request $request){
$isPaid = $request->is_paid;
$users = User::get();
if($isPaid){
$users = $users->where('is_paid', true);
}
$users = $users->paginate(10);
return view('user.index', [
'users' => $users
]);
}
In order to use pagination for collection, I followed Gist For Paginated Collections In Laravel
I have stored my slug in my database but i get 404 Not found when i load the url
NewsController.php
public function show(News $news, $slug)
{
return view('news.single', compact('news'));
}
News.php
protected static function boot() {
parent::boot();
static::creating(function ($news) {
$news->slug = Str::slug($news->subject);
});
}
Route
Route::get('/news/{slug}', 'NewsController#show')->name('news.show');
I am getting 404 not found if load e.g localhost:8000/news/sample-post
The problem is that you are type-hinting News $news in your controller method and Laravel is unable to find the correct object because 1. there's no {news} route parameter and 2. it's looking in the ID column by default.
There are two options to fix it:
1. Manually load the news
public function show($slug)
{
$news = News::where('slug', $slug)->firstOrFail();
return view('news.single', compact('news'));
}
2. Tell Laravel to use the slug column instead of id:
Add this method to your News model:
/**
* Get the route key for the model.
*
* #return string
*/
public function getRouteKeyName()
{
return 'slug';
}
Change the route parameter name:
Route::get('/news/{news}', 'NewsController#show')->name('news.show');
And finally, remove the $slug controller method parameter:
public function show(News $news)
{
return view('news.single', compact('news'));
}
I have a groups table in my database and each group has a slug. I have the following routes defined last in my routes.php file so that if no other URL is matched the app checks whether the slug belongs to a group and shows the group page instead. There is also a form on the group page so the submission of this form needs to be handled as well.
Route::get('{slug}', ['as' => 'dynamic_route', function($slug){
$group = \App\Group::where('slug', $slug)->first();
if(!is_null($group)) {
$app = app();
$controller = $app->make('App\Http\Controllers\GroupsController');
return $controller->callAction('view', ['slug' => $group->slug]);
} else {
abort(404);
}
}]);
Route::post('{slug}', ['as' => 'dynamic_route_submit', function($slug){
$group = \App\Group::where('slug', $slug)->first();
if(!is_null($group)) {
$app = app();
$controller = $app->make('App\Http\Controllers\GroupsController');
return $controller->callAction('handle_register', [$group->slug]);
} else {
abort(404);
}
}]);
Here is my groups controller:
<?php namespace App\Http\Controllers;
use View;
use App\Group;
use App\Lifestyle_question;
use App\Http\Requests\User\RegisterStep1Request;
use App\Http\Requests\User\RegisterStep2Request;
use Breadcrumbs;
class GroupsController extends FrontendController {
public function __construct()
{
parent::__construct();
}
function view($slug)
{
$this->data['group'] = Group::where('slug', '=', $slug)->first();
$this->data['lifestyle_questions'] = Lifestyle_question::all();
Breadcrumbs::setCurrentRoute('dynamic_route', $this->data['group']);
return View::make('groups/view', $this->data);
}
function handle_register(RegisterStep1Request $request1, RegisterStep2Request $request2, $slug)
{
$this->data['group'] = Group::where('slug', '=', $slug)->first();
die("Validation passed");
}
}
The view method works fine however when I submit the form I get the following error message:
ErrorException in GroupsController.php line 27:
Argument 1 passed to App\Http\Controllers\GroupsController::handle_register() must be an instance of App\Http\Requests\User\RegisterStep1Request, string given
I know this has to do with the parameters that are being passed to the controller method from the route definition and so I tried the following in an attempt to sort it:
Route::post('{slug}', ['as' => 'dynamic_route_submit', function($slug){
$group = \App\Group::where('slug', $slug)->first();
if(!is_null($group)) {
$app = app();
$controller = $app->make('App\Http\Controllers\GroupsController');
return $controller->callAction('handle_register', [new \App\Http\Requests\User\RegisterStep1Request, new \App\Http\Requests\User\RegisterStep2Request, $group->slug]);
} else {
abort(404);
}
}]);
This fixed the issue except the requests just didn't get triggered. How can I call this method and ensure that the requests get triggered so that the validation is run?
Never use an anonymous function in the routing if you're going to call a controller inside of it. Declare your route like this:
Route::post('{slug}', ['as' => 'dynamic_route_submit', 'uses' => 'App\Http\Controllers\GroupsController#handle_register']);
Then in the controller handle whatever validation is necessary.
You could try moving your request validations out of the Request classes and into private controller actions:
UserController.php
/**
* Validates a Create User request
*/
protected function validateCreate()
{
$this->validate($this->request, [
'name' => 'required|max:255',
'email' => 'required|unique:users|max:255',
'account_types_id' => 'required|numeric',
]);
}
So do something similar with your code and call these validation methods from within your controller action:
UserController.php
/**
* #return \Illuminate\Http\RedirectResponse
* #throws CreateException
*/
public function create()
{
$this->validateCreate();
As an FYI you can access route parameters by name using request()->route()->getParameter('slug')
$slug = request()->route()->getParameter('slug');
$this->data['group'] = Group::where('slug', '=', $slug)->first();
I try to build a grid view with many-to-many relations. So I need a query for the ActiveDataProvider .
I have a table 'ressource', a table 'type' and between them a table 'historique'.
I have the good relation in my models but I don't know how to create the dataProvider.
In my model Ressource :
public function getHistorique()
{
return $this->hasMany(Historique::className(), ['idType' => 'idType']);
}
public function getType()
{
return $this->hasMany(Type::className(), ['idType' => 'idType'])
->viaTable(Historique::className(), ['idRessource' => 'idRessource']);
}
In my model Historique :
public function getType()
{
return $this->hasOne(Type::className(), ['idType' => 'idType']);
}
public function getRessource()
{
return $this->hasOne(Ressource::className(), ['idRessource' => 'idRessource']);
}
and finally in my model Type :
public function getHistorique()
{
return $this->hasMany(Historique::className(), ['idType' => 'idType']);
}
public function getRessource()
{
return $this->hasMany(Ressource::className(), ['idRessource' => 'idRessource'])
->viaTable(Historique::className(), ['idType' => 'idType']);
}
So in the Controller (in fact my ModelSearch), I want to have ressources with type from the table historique. I don't know what I have to add after
Ressource::find();
I think you use RessourceSearch()->search() method. So inside it you have something like this:
$query = Ressource::find();
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
if (!($this->load($params) && $this->validate())) {
return $dataProvider;
}
// Here is list of searchable fields of your model.
$query->andFilterWhere(['like', 'username', $this->username])
->andFilterWhere(['like', 'auth_key', $this->auth_key])
return $dataProvider;
So, basically, you need to add additional Where you your query and force to join relation table. You can do that using joinWith method to join additional relation and andFilterWhere using table.field notation for adding filter parameters. For example:
$query = Ressource::find();
$query->joinWith(['historique', 'type']);
$query->andFilterWhere(['like', 'type.type', $this->type]);
$query->andFilterWhere(['like', 'historique.historique_field', $this->historique_field]);
Also do not forget to add rules for additional filters in your search model. For example above, you should add to your rules() array something like that:
public function rules()
{
return [
// here add attributes rules from Ressource model
[['historique_field', 'type'], 'safe'],
];
}
You can use any additional validation rules for that fields