Laravel Controller: Override parent request validation - laravel

I have a structure that has base controller called BaseController that all controllers extend it, and it has implementation of index() to view resources, base controller use default Request validation and I need to override this in a child.
When I run the below code I receive the following error:
Declaration of ...PostController::index(...PostRequest $request) should be compatible with ...BaseController::index(...Request $request)
Parent:
/* BaseController.php */
namespace App\Http\Controllers;
use Illuminate\Http\Request;
abstract class BaseController extends Controller
{
public function index(Request $request)
{
// logic
}
}
Child:
/* PostController.php */
namespace App\Http\Controllers\App;
use Illuminate\Http\PostRequest;
class PostController extends BaseController
{
public function index(PostRequest $request)
{
// logic
}
}

Related

Testing Custom Route Model Binding

I'm trying to test a custom class that implements \Illuminate\Contracts\Routing\UrlRoutable and can't get the resolveRouteBinding method invoked.
<?php
namespace Tests\Unit;
use Illuminate\Support\Facades\Route;
use Tests\TestCase;
class BindingExampleClassTest extends TestCase
{
function test_invoke_resolve_route_binding_method()
{
Route::get('/invoke-route-binding/{binding}', function (BindingExampleClass $binding) {
dd($binding);
});
$this->get('/invoke-route-binding/1');
}
}
class BindingExampleClass implements \Illuminate\Contracts\Routing\UrlRoutable
{
public $id;
public function resolveRouteBinding($value, $field = null)
{
$this->id = $value;
}
public function getRouteKey()
{
// TODO: Implement getRouteKey() method.
}
public function getRouteKeyName()
{
// TODO: Implement getRouteKeyName() method.
}
public function resolveChildRouteBinding($childType, $value, $field)
{
// TODO: Implement resolveChildRouteBinding() method.
}
}
The dd response is BindingExampleClass with id still null.
Registering route inside a test function will not include any middleware. When working with route model binding in Laravel, \Illuminate\Routing\Middleware\SubstituteBindings::class middleware must be defined in the router instance.
Route::get('/invoke-route-binding/{binding}', function (BindingExampleClass $binding) {
dd($binding);
})->middleware(\Illuminate\Routing\Middleware\SubstituteBindings::class);

Laravel extends class with constructor using DI

I have created a small CRUD controller, I need to inject FormBuilder in the __construct() of this CRUD controller
class CrudController extends Controller
{
private $formBuilder;
/**
* CrudController constructor.
* #param FormBuilder $formBuilder
*/
public function __construct(FormBuilder $formBuilder)
{
$this->middleware('auth');
$this->formBuilder = $formBuilder;
// ....
My question is : can I extends this class without injecting FormBuilder to each child ? For now I have :
class LevelsCrudController extends CrudController
{
public function __construct(FormBuilder $formBuilder)
{
parent::__construct($formBuilder);
// .....
Which is really redondant, any workaround ?
If you do not want to have a FormBuilder $formBuilder in your child controller's construct, you could pass it as a param only when you call the parent's construct like this:
parent::__construct(resolve(FormBuilder::class));
Otherwise, you could remove it completely from the parent's constructor and resolve it inside the parent constructor like this:
class CrudController extends Controller
{
public function __construct()
{
$this->middleware('auth');
$this->formBuilder = resolve(FormBuilder::class);
// ...
}
}
And then in your child, you can simple call:
public function __construct()
{
parent::__construct();
// ...
}

Update the plugin will be something wrong

When I update the Laravel plugin, if I use some static method e.g. User::find($id) it will show a warning: "Non-static method User::find() should not be called statically", this very bad!
Example:
namespace App\Http\Controllers\Web;
use App\Model\User;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use EasyWeChat\Foundation\Application;
class TestController extends Controller
{
public function __construct(Application $wechat)
{
parent::__construct($wechat);
}
public function index(Request $request)
{
$user = User::find(12);
dd($user);
}
}
public function index(Request $request)
{
$user = User::all()->find(12);
dd($user);
}

Singleton created twice

In Laravel 5.4 I have registered a Service Provider that creates a singleton to my Context class which holds application context.
ContextServiceProvider
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App;
class ContextServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* #return void
*/
public function boot()
{
// Set-up application context
$context = app('context');
}
/**
* Register the application services.
*
* #return void
*/
public function register()
{
$this->app->singleton('context', function ($app) {
return new App\Context();
});
}
}
Then I create a Eloquent model with a global scope.
Model Media
namespace App\Models;
use App\Scopes\SchoolScope;
use Illuminate\Database\Eloquent\Model;
class Media extends Model
{
public static function boot()
{
parent::boot();
static::addGlobalScope(new SchoolScope());
}
}
Now when I access the Context singleton in the scope SchoolScope, the singleton is created twice!
SchoolScope
namespace App\Scopes;
use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use App\Models\School;
class SchoolScope implements Scope
{
protected $school;
public function __construct()
{
$this->school = app('context')->school;
}
public function apply(Builder $builder, Model $model)
{
$builder->where('school_id', '=', $this->school->id);
}
}
Does anyone know why the singleton is created twice?

Type hinting parent::__construct() arguments in controllers

I've got a BaseController in a Laravel Framework based App with the following code:
class BaseController extends Controller {
public function __construct(Credentials $credentials) {
$this->credentials = $credentials;
}
Then, all my other controllers will Extend the BaseController:
class PostController extends BaseController {
public function __construct(PostRepository $post)
{
$this->post = $post;
parent::__construct();
}
However, I'd need to type hint the Credentials Class in the parent::__construct(); of all my controllers. Is there any way to avoid that?
Thanks in advance
I can solve it using the following code:
class BaseController extends Controller {
public function __construct()
{
$this->credentials = App::make('Credentials'); // make sure to use the fully qualified namespace of Credentials if need be
}
}

Resources