Laravel IOC not calling the constructor - laravel

I have binding in the service provider
$this->app->singleton(
'App\Models\Subscription\Interfaces\IInvoiceService',
'App\Models\Subscription\Impl\InvoiceService'
);
class InvoiceService implements IInvoiceService
{
protected $repo;
public function _construct(){
$this->app = App::getFacadeRoot();
$this->repo = $this->app['repo'];
}
public function Create()
{
}
}
In one of the classes in Injected the IInovoice Service.
I am getting the concrete implementation of IInovoice . but the Constructor of the InvoiceService is never getting called

Try the following
class InvoiceService implements IInvoiceService
{
protected $app;
protected $repo;
public function _construct($app, $repo) {
$this->app = $app;
$this->repo = $repo;
}
public function Create() {
}
}
App\Providers\AppServiceProvider
public function register() {
$this->app->singleton(
'App\Models\Subscription\Interfaces\IInvoiceService',
'App\Models\Subscription\Impl\InvoiceService'
);
$this->app->when('App\Models\Subscription\Impl\InvoiceService')
->needs('$app')
->give($this->app->getFacadeRoot());
$this->app->when('App\Models\Subscription\Impl\InvoiceService')
->needs('$repo')
->give($this->app['repo']);
}
public function boot(ResponseFactory $response) {
//uncomment this line to debug InvoiceService Resolving event
//$this->app->resolving(App\Models\Subscription\Impl\InvoiceService::class, function ($invoiceService, $app) {
//dump('resolves InvoiceService', $invoiceService);
//});
}
Then run
php artisan clear-compiled
php artisan config:clear

Related

Resource Api laravel 9 return null

I have this project that uses Laravel 9 framework and I'm using resource Api method. It worked fine for index and store function but it returns null when it comes update, show ,delete methods. I have my code down below:
My Model:
class Re14 extends Model
{
use HasFactory;
protected $fillable=['re14002'];
}
My Migration:
return new class extends Migration
{
public function up()
{
Schema::create('re14s', function (Blueprint $table) {
$table->id();
$table->string('re14002');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('re14s');
}
};
MY Controller:
class Re14Controller extends Controller
{
public function index()
{
return Re14Resource::collection(Re14::all());
}
public function store(Re14Request $request)
{
$re14=Re14::create($request->validated());
return new Re14Resource($re14);
}
public function show(Re14 $re14)
{
return new Re14Resource($re14);
}
public function update(Re14Request $request, Re14 $re14)
{
$re14->update($request->validated());
return new Re14Resource($re14);
}
public function destroy(Re14 $re14)
{
$re14->delete();
return response("Deleted Successfully!");
}
}
MY Resource
public function toArray($request)
{
return [
'id'=>$this->id,
're14002'=>$this->re14002
];
}
}
My Request
class Re14Request extends FormRequest
{
public function authorize()
{
return true;
}
public function rules()
{
return [
're14002'=>['required','string','unique:re14s,re14002']
];
}
}
MY Route
Route::apiResource('level',Re14Controller::class);
I use Postman to test my Api. It worked fine for index and store but got stack when it comes update, show, delete
{
"data": {
"id": null,
"re14002": null
}
}

How to share $request variable between other function from other url in same controller on laravel

I want to share $request variable between other function from other url in same controller on laravel like below but how ?
Controller
class ABCController extends Controller
{
public function validation(Request $request)
{
---------------
}
public function save()
{
Log::debug($request)
}
api.php
Route::post('/abc',[ABCController::class,'validation']);
Route::get('/save',[ABCController::class,'save']);
What I tried
class ABCController extends Controller
{
public function validation(Request $request)
{
Session::put('data', $request)
session(['data' => $request]);
Log::debug(Session::get('data'));
Log::debug(session('data'));
}
public function save()
{
Log::debug(Session::get('data'));
Log::debug(session('data'));
}
I tried above but Log::debug in save function show me null in log.
Please give me advice.
Create a global variable
class ABCController extends Controller
{
private $data;
public function validation(Request $request)
{
$this->data =$request;
}
public function save()
{
echo $this->data;
}
}

PHPUnit test for Laravel Artisan command without calling external API in inner instance (dependency injection)

I am trying to write a phpunit test with laravel 5.2 for a console command.
Few resources seems promising, but so far I failed making it work. I am trying to follow info given here:
stackoverflow - PHPUnit test for Laravel Artisan command that calls an external API without calling that API physically?
Laravel binding
The test is calling a command that 'binds' ExternalAPI class in its constructor.
In the test, I mock the ExternalAPI.
The ExternalAPI class:
Class ExternalAPI {
protected $lang;
public function __construct($lang)
{
$this->lang = $lang;
}
public function call_api($myparam){
//do the api stuff here
}
}
The command:
class MyCommand extends Command
{
protected $signature = 'check:mycommand';
protected $externalAPI ;
public function __construct(ExternalAPI $externalAPI)
{
$this->externalAPI = $externalAPI;
parent::__construct();
}
public function handle()
{
$res = $this->externalAPI->call_api('test');
}
}
The test:
class MyCommandTest extends TestCase
{
public function setUp()
{
parent::setUp();
$methods_to_stub = ['call_api'];
$mock = $this->getMockBuilder('\ExternalAPI')
->setConstructorArgs(array('param_value'))
->setMethods($methods_to_stub)
->getMock();
$mock->method('call_api')->willReturn(44.44);
$this->app->instance(ExternalAPI::class, $mock);
}
public function test1()
{
$output = new BufferedOutput;
Artisan::call('check:mycommand', [],$output);
echo "output:$output\n\n";
}
}
The error is:
Illuminate\Contracts\Container\BindingResolutionException:
Unresolvable dependency resolving [Parameter #0 [
$myparam]] in class App\MyLibrary\ExternalAPI
I managed to get it to work using mockery
This is the corrected code that works for me:
The ExternalAPI class (I removed the param from the constructor because right now I didn't check if and how it can be done):
Class ExternalAPI {
protected $lang;
public function __construct()
{
}
public function init($lang)
{
$this->lang = $lang;
}
public function call_api($myparam){
//do the api stuff here
}
}
The command:
class MyCommand extends Command
{
protected $signature = 'check:mycommand';
protected $externalAPI ;
public function __construct()
{
$this->externalAPI = app(ExternalAPI::class);
parent::__construct();
}
public function handle()
{
$this->externalAPI->init('whatever')
$res = $this->externalAPI->call_api('test');
}
}
The AppServiceProvider:
class AppServiceProvider extends ServiceProvider{
public function boot()
{
$this->app->bind('App\MyLibrary\ExternalAPI',function(){
return new \App\MyLibrary\ExternalAPI();
});
}
}
The test:
class MyCommandTest extends TestCase
{
public function setUp()
{
parent::setUp();
$mock = Mockery::mock('ExternalAPI');
$mock->shouldReceive('call_api')->with(Mockery::any())->andReturn(44.44);
$mock->shouldReceive('init')->with(Mockery::any());
$this->app->instance(ExternalAPI::class, $mock);
}
public function test1()
{
$output = new BufferedOutput;
Artisan::call('check:mycommand', [],$output);
echo "output:$output\n\n";
}
}

How can I solve Target [App\Repositories\NewsRepository] is not instantiable while building [App\Http\Controllers\Member\NewsController].?

My controller like this :
...
use App\Repositories\NewsRepository;
class NewsController extends Controller
{
protected $repository;
public function __construct(NewsRepository $repository)
{
$this->repository = $repository;
}
public function store(NewsCreateRequest $request)
{
...
$news = $this->repository->create($input);
...
}
}
My interface like this :
namespace App\Repositories;
use Prettus\Repository\Contracts\RepositoryInterface;
interface NewsRepository extends RepositoryInterface
{
//
}
My class like this :
...
use App\Repositories\NewsRepository;
class NewsRepositoryEloquent extends BaseRepository implements NewsRepository
{
public function model()
{
return News::class;
}
public function boot()
{
$this->pushCriteria(app(RequestCriteria::class));
}
}
My repository service provider like this :
...
class RepositoryServiceProvider extends ServiceProvider
{
...
public function register()
{
...
$this->app->bind(\App\Repositories\NewsRepository::class, \App\Repositories\NewsRepositoryEloquent::class);
}
}
If the method store on the controller executed, there exist error :
(1/1) BindingResolutionException Target
[App\Repositories\NewsRepository] is not instantiable while building
[App\Http\Controllers\Member\NewsRepository].
How can I solve the error?
You have to add constructor to your repository and call parent constructor for setup model like this:
public function __construct(Permission $model)
{
parent::__construct($model);
}

laravel can't retrieve session when redirect

in laravel 5.4
class AdminController extends Controller
{
public function checkLogin(Request $request)
{
Session::put('admin','yes');
return redirect('mobiles');
}
}
class MobilesController extends Controller
{
public function __construct()
{
if( ( Session::has('admin') ) )
{ dd('admin');}
else
{ dd('not admin'); }
}
}
it prints 'not admin' so what happen to the session , if i prints the admin session in class checkLogin it prints normally
Since L5.3, you cannot a access to the session in the controller's constructor. You have to use a closure :
public function __construct()
{
$this->middleware(function ($request, $next) {
echo Session::has('admin') ? 'admin' : 'not admin';
return $next($request);
});
}
https://laravel.com/docs/5.3/upgrade#5.3-session-in-constructors
you have to use laravel flashed-session-data
https://laravel.com/docs/5.4/redirects#redirecting-with-flashed-session-data
return redirect('mtest2')->with('admin','yes');
so modify your code like this
class AdminController extends Controller {
public function checkLogin(Request $request){
return redirect('mobiles')->with('admin',true);
}
}
class MobilesController extends Controller {
public function __construct() {
if( session()->has('admin') ){
dd('admin');
}else{
dd('not admin');
}
}
}
Here is updated code if you do not want to use Flashed data
class AdminController extends Controller {
public function checkLogin(Request $request){
$request->session()->put('admin',true);
return redirect('mobiles');
}
}
it should work.

Resources