Problem with Route::apiResource() Laravel Framework 8.64.0 - laravel

I'm using laravel 8 (Laravel Framework 8.64.0) to create an API. But when make a call to an endpoint, which i define with Route::apiResource it doesn't return the result from a query, returns nothing.
routes\api.php
<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\Api\TodoController;
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
return $request->user();
});
//Route::get('/todos', [TodoController::class, 'index']);
Route::apiResources([
'todos' => TodoController::class,
]);
Models\Todo.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Todo extends Model
{
use HasFactory;
protected $fillable = [
'user_id',
'name',
'is_done',
'due_at',
'completed_at',
];
}
Controllers\TodoController.php
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Todo;
class TodoController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
return Todo::all();
}
If I add another route:
Route::get('/todos', [TodoController::class, 'index']);
and I call it, it works.
What could possible be the problem?

You may want to try create TodoResource class extend JsonResource by running
php artisan make:resource TodoResource
then inside Todo Controller index function, replace return Todo::all(); with
return TodoResource::collection(Todo::all());

Solution why not work, remove line from
routes\api.php:
use App\Http\Controllers\Api\TodoController;

Related

Laravel 8 : Trying to test a controller method thanks to JSON Get Testing but the route is not found

I'm getting this error:
Expected status code 200 but received 404.
Failed asserting that 200 is identical to 404.
When I try to call it from my Unit Test:
<?php
namespace Tests\Unit;
use App\Models\Project;
use Tests\TestCase;
class ExampleTest extends TestCase
{
public function testTakePlace()
{
$project = Project::factory()->make();
$response = $this->getJson('controllerUserProject_takePlace', [
'project_id' => $project->id,
]);
$response
->assertStatus(200)
->assertJsonPath([
'project.status' => Project::STATES['TO_BE_REPLIED'],
]);
}
}
However, controllerUserProject_takePlace is correctly the name I gave to the route. Indeed, here is /routing/web.php:
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\TestConnections;
use App\Http\Controllers\ControllerUserProject;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('/controllerUserProject_takePlace/projects/{project_id}', [ControllerUserProject::class, 'takePlace'])->name('controllerUserProject_takePlace');
The controller ControllerUserProject is correctly defined:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class ControllerUserProject extends Controller
{
public function takePlace(Request $request, $project_id)
{
return [
'project_status' => Project::STATES['TO_BE_REPLIED']
];
}
}
Do you know why the use of the route returns 404 (not found)?
Your route url is '/controllerUserProject_takePlace/projects/{project_id}' while in the test you are using 'controllerUserProject_takePlace' hence the 404 error.
Also the second parameter in getJson() is array $headers so when you pass ['project_id' => $project->id] it becomes second parameter taken as $headers.
You need to supply complete url to getJson('/controllerUserProject_takePlace/projects/' . $project->id);
or
Since you have already named your route you can use the route() helper in getJson(route('controllerUserProject_takePlace', $project->id));
Change the url in your test
<?php
namespace Tests\Unit;
use App\Models\Project;
use Tests\TestCase;
class ExampleTest extends TestCase
{
public function testTakePlace()
{
$project = Project::factory()->make();
// $response = $this->getJson('/controllerUserProject_takePlace/projects/' . $project->id);
//Try using named route
$response = $this->getJson(route('controllerUserProject_takePlace', $project->id));
$response
->assertStatus(200)
->assertJsonPath([
'project.status' => Project::STATES['TO_BE_REPLIED'],
]);
}
}

How to share one method to all controllers in Laravel?

How to share one method to all controllers with different DI, view and parameters? I need something like this:
public function method(Model $model)
{
$baseData = [
'model' => $model,
'route' => route('$route', [$param => $model]),
];
return view($view);
}
All controllers extend App\Http\Controllers\Controller so you can just place it there
<?php
namespace App\Http\Controllers;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
public function method(Model $model, $route, $param, $view)
{
// Declared but not used
$baseData = [
'model' => $model,
'route' => route($route, [$param => $model]),
];
return view($view);
}
}
And use it with $this->method()
For example in HomeController
<?php
namespace App\Http\Controllers;
use App\User;
class HomeController extends Controller
{
/**
* Show the application dashboard.
*
* #return \Illuminate\Contracts\Support\Renderable
*/
public function index()
{
$user = User::first();
return $this->method($user, 'home', 'user', 'welcome');
}
}
Now accessing domain.tld/home will return the welcome view
If you want to share function to all controller best way will make service in service folder of app.
step to make service:-
1.create service using artisan command
php artisan make:service service_name and define function that to share to all controller in your project.
after making service your have to register this service with provider.make a provider using artisan command.
php artisan make provider:provider_name and you will see 2 function register and boot
register function is used to register your created service and boot for call already register service
register service like this
public function register()
{
$this->app->bind('App\Services\servicename', function( $app ){
return new serviceclassname;
});
}
3.Go config folder ,open app.php where you will get providers array. In this provider you have to define you provider like App\Providers\providerclassname::class,
call this service in controllers like use App\Services\serviceclassname;
public function functionname(serviceclassname serviceobject)
{
serviceobject->functionname();
}

laravel 5.4 login attempts don't work

I am trying to limit my login attempts but still not working
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
class LoginController extends Controller
{
use AuthenticatesUsers;
protected $redirectTo = '/home';
public function __construct()
{
$this->middleware('guest', ['except' => 'logout']);
}
}
and this is ThrottlesLogin.php
protected function hasTooManyLoginAttempts(Request $request)
{
return $this->limiter()->tooManyAttempts(
$this->throttleKey($request), 3, 2
);
}
and i know in laravel 5.4 the AuthenticatesUsers call by default thethrottlesLogin but still dont limit login attempts.
and thanks
You need to use ThrottlesLogins trait in LoginController

Laravel 5.1 Module with multiple controllers

I want to create module with number of controller like
Admin is Module name and have AdminController.
Admin module has another controller CategoryController, ProductController.
Now i wanted to use that controller as part of admin module How can i achive that using Artem-Schander/L5Modular
You have the wrong namespace in your CategoryController.php
It should be namespace App\Modules\Admin\Controllers
and not namespace App\Modules\Admin\Controllers\Category
working example:
routes.php:
Route::group(array('module' => 'Admin', 'namespace' => 'App\Modules\Admin\Controllers'), function() {
Route::resource('admin', 'AdminController');
Route::resource('category', 'CategoryController');
});
AdminController.php:
<?php namespace App\Modules\Admin\Controllers;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Modules\Admin\Models\Admin;
class AdminController extends Controller {
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index()
{
die('admin controller');
}
}
CategoryController.php:
<?php namespace App\Modules\Admin\Controllers;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
//use App\Modules\Admin\Models\Admin;
class CategoryController extends Controller {
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index()
{
die('category controller');
}
}
Here you said, you have a blank page. Check your .env file for the debug option and set it to true. Than you should have a detailed debug output.

Laravel5 won't match route edit_user/{id}

please, could you help me a bit?
I have this route in Laravel5:
Route::get('edit_user/{userId}', [
'as' => 'editUser',
'uses' => 'Auth\UserController#editUser'
]);
But when I try to go onto url .../edit_user/19 it wont match and redirect me into /home url...
Anyway, when I use this:
Route::get('edit_user/{userId}', [
'as' => 'editUser',
function($userId) {
die($userId);
}
]);
It returns 19.
Here is also my function:
public function editUser($userId) {
die($userId);
}
Here is also part of my controller:
<?php namespace App\Http\Controllers\Auth;
use App\Models\User;
use Auth;
use Hash;
use Mail;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Session;
class UserController extends Controller {
/**
*
* #return void
*/
public function __construct()
{
$this->middleware('guest', ['except' => 'logout']);
}
/**
*
* show edit user form
*
* #param $id
*/
public function editUser($userId) {
die($userId);
}
Do you know any idea, where might be problem?
Thank you very much for your opinions.
EDIT:
I find out solution -> need to edit exception to auth in __construct.
This should work with the code provided.
Check the following items:
1. Do you have this code in the __construct of your UsersController?
public function __construct()
{
$this->middleware('auth');
}
If so, you need to be lagged in to edit the user.
2. Is there any route listed before edit_user/{userId} that would override this route.
Try moving it to be the very first route.
3. Is you UserController namespaced properly?
<?php
namespace App\Http\Controllers\Auth;

Resources