I am getting a "404 | Not Found" error when i try to access a specific item from my database. The items with the specific ID's do exist in the database, but i am not even sure if that even has any influence on the problem.
My routing looks likes this:
Route::prefix('departments')->group(function() {
Route::get('/{id}', [DepartmentController::class, 'showDepartment']);
});
And the related controller looks like this:
public function showDepartment() {
return '';
}
}
I haven't yet finished the function. I just wanted to check if the routing even worked by returning an empty string.
So what am i doing wrong? Is it the routing or the controller?
According to the Laravel documentation, you have to define the parameter in the route then use it in the controller as a parameter.
in your controller:
public function showDepartment($id) {
return 'Hello';
}
The id is not bound to any model to fetch from the database to do that you can use Laravel route model binding
for example when you have a model named Department you write your route like this:
Route::get('/{department}', [DepartmentController::class, 'showDepartment']);
and in the controller:
public function showDepartment(Department $department) {
return 'Hello from depratment';
}
When your department exists it returns the response otherwise return 404.
You may need a Department model class. Then you can find the item from database by id $department = Department::findOrFail($id);
you are send parameter in route and this function without any parameter
route :
Route::prefix('departments')->group(function() {
Route::get('/{id}', [DepartmentController::class, 'showDepartment']);
});
your function in controller should be
public function showDepartment($id) {
$department = Department::findOrFail($id);
}
}
Related
I'm having an issue where the store method in my UserCountries API controller is returning data that seems to be one step behind and I'm not sure why. My app has two models: Country and User, which have a many-to-many relationship with a pivot table. In my app a particular user should be able to 'like' and 'unlike' a country.
This mostly works as expected, however my issue is that the data returned on each request is one step behind - e.g., if I send a POST request to like a particular country, I get a 200 response but I am returned a UserCountriesResource which does not include that country that should have just been added. If I then immeditaely send a GET request, it returns a UserCountriesResource which does include that country. Can anyone help me figure out why?
Here are my routes:
Route::group(["prefix" => "me/countries"], function(){
Route::get("", [UserCountries::class, "index"]); // see all countries liked by user
Route::post("", [UserCountries::class, "store"]); // add or remove country from user
});
My index method in the UserCountries controller is below:
public function index()
{
return CountryResource::collection(auth()->user()->countries);
}
My store method in the UserCountries controller is below:
public function store(UserCountriesRequest $request)
{
$user = auth()->user();
$user->setCountries($request->get("countries"));
return new UserCountriesResource($user);
}
The store method calls the setCountries method in the User model:
public function setCountries(array $strings) : User
{
$countries = Country::fromStrings($strings);
$countries->map(function($country) use($countries){
if($this->countries->contains($country)){
Country::find($country->id)->users()->detach($this->id);
} else {
$this->countries()->syncWithoutDetaching($country->id);
}
});
return $this;
}
The setCountries method above in turn calls the fromStrings method in the Country model:
public static function fromStrings(array $strings) : Collection
{
return collect($strings)->map(fn($str) => trim($str))
->unique()
->map(fn($str) => Country::firstOrCreate(["NAME"=>$str]));
}
Do let me know if there's anything else I can add to make this more helpful!
You are loading the relationship before you are adding/removing any of the related records. That loaded relationship, Collection, won't include these changes. You will need to reload the relationship to get the new list of related records.
I don't know the rest of your code but you would add a call like this, if this was the case:
$user->load('countries');
This is loading the relationship (if it wasn't already loaded):
if($this->countries->contains($country))
I have a project on Laravel 5.8. It's internet-market with categories, brands and products. I used in my controllers a variable from model:
route:
Route::prefix('categories')->get('/{category}', 'ProductsController#openCategory')->name('openCategory');
model:
class Category extends Model
{
public function products()
{
return $this->hasMany(Product::class);
}
public function getRouteKeyName()
{
return 'category_alias';
}
}
controller-method:
public function openCategory(Category $category = null)
{
$allInfo = $this->getAllInfo();
$categories = $this->getCategories();
$brands = $this->getBrands();
return view("pages.category", compact('allInfo','category', 'categories', 'brands'));
}
I don't use relation by ID, I use relation by 'category_alias'. But if I write category name with error, I get message - OPPS! We Couldn’t Find this Page
Uh... So it looks like you brock something. The page you are looking for has up and Vanished. Why? But if I use relation by ID, I get page 404 - it's success for me.
By defining the route with ->get('/{category}' and typehinting on the controller, Category $category you are telling Laravel that you want it to resolve the category for you.
This is handled by the service container as described at https://laravel.com/docs/master/container#introduction
If you provide a value which doesn't resolve to the id for a category in the database, the service container will be be unable to load anything. Laravel responds to those scenarios by returning the 404.
I have this route:
Route::get('subscribers/{subscriber}', 'SubscriberController#show');
In my controller's show method, I want it to use the email as a lookup to my table instead of the default id. Is this possible?
public function show(Subscriber $subscriber)
{
// I need this to do like
// $subscriber = Subscriber::findOrFail(<email>);
//
// instead of the default
// $subscriber = Subscriber::finaOrFail(<id>);
return $subscriber;
}
I tried to look for an answer here in StackOverflow but my limited knowledge about Laravel does not seem to allow me to use the right keywords.
Add the following method to your Subscriber Model.
public function getRouteKeyName()
{
return 'email';
}
You can read more about Route Model Binding in the Laravel Documentation.
In my web.php file, I specify the following route:
Route::get('/{project}', 'ProjectsController#index');
In my ProjectsController, I define the public function index as follows:
use App\Project;
// ... Here is the class declaration etc.
public function index(Project $project) {
dd($project->name);
}
Currently, I have one entry in my projects table, which I can call without any problems over my eloquent model. This is my entry:
Name: sampleproject
Description: This is a test.
ID: 1
// And the timestamps...
When calling /sampleproject, it returns a 404 error page.
[...]
UPDATE: When calling /1, which is the project id, everything works as expected. How can I modify my code so I can call my Controller over the project name, not the id?
in your model:
public function getRouteKeyName()
{
return 'yourcolumn';
}
Suppose I have these routes :
$api->group(['prefix' => 'Course'], function ($api) {
$api->group(['prefix' => '/{course}'], function ($api) {
$api->post('/', ['uses' => 'CourseController#course_details']);
$api->post('Register', ['uses' => 'CourseController#course_register']);
$api->post('Lessons', ['uses' => 'CourseController#course_lessons']);
});
});
As you can see all / , Register and Lessons route prefixed by a course required parameter.
course parameter is a ID of a Course model that I want to use for route model binding.
But In the other hand when I want use course parameter for example in course_details function, it returns null. like this :
public function course_details (\App\Course $course)
{
dd($course);
}
But if I use below, all things worked fine :
public function course_details ($course)
{
$course = Course::findOrFail($course);
return $course;
}
Seems that it can not bind model properly.
What is Problem ?
Update :
In fact I'm using dingo-api laravel package to create an API. all routes defined based it's configuration.
But there is an issue about route model binding where to support route model binding we must to add a middleware named binding to each route that need model binding. HERE is described it.
A bigger problem that exists is when I want to add binding middleware to a route group, it does not work and I must add it to each of routes.
In this case I do not know how can I solve the problem.
Solution:
After many Googling I found that :
I found that must to add bindings middleware in the same route group that added auth.api middleware instead adding it to each sub routes separately.
means like this :
$api->group(['middleware' => 'api.auth|bindings'], function ($api) {
});
add in kernel.php
use Illuminate\Routing\Middleware\SubstituteBindings;
protected $routeMiddleware = [
...
'bindings' => SubstituteBindings::class,
];
and in your group route:
Route::middleware(['auth:sanctum', 'bindings'])->group(function(){
... you routes here ...
});
this worked for me. thanks
As you said
course parameter is a ID of a Course
You can use Request to get id, try like this
public function course_details (Request $request)
{
return dd($request->course);
}
I came across a similar issue. I think you need to use the 'bindings' middleware on your routes.
See my answer here:
https://stackoverflow.com/a/55949930/2867894
Take a close look on:
// Here $course is the id of the Course
public function course_details ($course)
{
$course = Course::findOrFail($course);
return $course;
}
But here:
// Here $course is the object of the model \App\Course
public function course_details (\App\Course $course)
{
dd($course);
}
that should be
public function course_details ($course, \App\Course $_course)
{
// add your model here with object $_course
// now $course return the id in your route
dd($course);
}
After searching for 2 hours I got the issue details
For route binding to work, your type-hinted variable name must match the route placeholder name
For example my edit method
Here is my route URI for the edit
user/role/{role}/edit
As you can see there is {role} placeholder in the route definition, so the corresponding variable must be called $role.
public function edit(Role $role)
{
return view('role.edit',compact('role'));
}