Laravel Livewire error when I add a constructor to call a service class - laravel

I've got a piece of code I want to reuse. I've read this Laravel cleaner code article and this other Laravel Services Pattern article, where I have realized I can reuse code in several places of the application by using services classes.
In this case, I created a new MyService class, inside a new folder app/Services/MyService.
namespace App\Services;
class MyService
{
public function reuse_code($param){
return void;
}
}
The problem comes when I want to call the class through the constructor inside a Livewire class component, as follows:
<?php
namespace App\Http\Livewire;
use App\Services\MyService;
use Livewire\Component;
use Livewire\WithPagination;
class LivewireTable extends Component
{
use WithPagination;
private $myClassService;
public function __construct(MyService $myService)
{
$this->myClassService = $myService;
}
public function render()
{
$foo = $this->myClassService->reuse_code($param);
return view('my.view',compact('foo'));
}
}
The error displayed is the following:
Argument 1 passed to App\Http\Livewire\LivewireTable::__construct()
must be an instance of App\Services\MyService, string given
(However, If I use a trait, there are no problems. But I am afraid then my traits collide as previous experiences)
How do I fix it? What am I missing?

Livewire's boot method Runs on every request, immediately after the component is instantiated, but before any other lifecycle methods are called
Here's the solution worked for me.

Solved
Just like #IGP said, reading in the livewire docs it says:
In Livewire components, you use mount() instead of a class constructor
__construct() like you may be used to.
So, my working code is as follows:
<?php
namespace App\Http\Livewire;
use App\Services\MyService;
use Livewire\Component;
use Livewire\WithPagination;
class LivewireTable extends Component
{
use WithPagination;
private $myClassService;
public function mount(MyService $myService)
{
$this->myClassService = $myService;
}
public function render()
{
$foo = $this->myClassService->reuse_code($param);
return view('my.view',compact('foo'));
}
}

Related

Override vendor model in laravel 6.X

I want to override the model inside of vendor. I tried bellow code. But not working.
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function register()
{
//
}
public function boot()
{
$this->app->bind('VendorName\Models\User', 'App\Models\User');
}
}
Extending model is not an option, as i have to override all controller change model path and write all methods again, its not worth it.
Binding a class in the container like this isn't going to override direct references to the class you're trying to override if the object isn't being resolved using the service container.
So for example, something like $user = new \VendorName\Models\User; isn't going to be affected because it's simply not using the container.
I think the only sensible solution is to refactor your code so you're using a class that extends the base User class.

Laravel 5.8 dependecy injection - how to inject model to service

I have BooksService class which should be injected by Book model object. Then I want to inject BooksService to BookController. But I dont know ho to do it.
I am getting an error Class App\Model\BookService does not exist. Is it neccesary to register it somewhere? Also I am not sure if I am doing it right. Is it in this code?
BookService
namespace App\Model;
class BookService
{
/** #var Book */
public $books;
// I am not sure if this is ok
public function construct(Book $books)
{
$this->books = $books;
}
public function test()
{
dd($this->books);
}
}
BookController
namespace App\Http\Controllers;
use App\Http\Requests\StoreBook;
use App\Model\Book;
use App\Model\BookService;
use Illuminate\Http\Request;
class BookController extends Controller
{
....
// This throws me an error BookService does not exists
public function create(BookService $bookService)
{
$bookService->test();
return view('book.create');
}
....
}
So the problem is that __contruct() method expects Book facade instance but Laravel does not know what is it. Also Book facade is available from inside the service class so no need to be injected to it.

Dependency resolving with App::make not working when bind is done by a provider in Laravel

I'm using Laravel 5.2. I tried to resolve a dependency in Laravel out of the IOCContainer as follows.(with App::make method)
App/FooController.php:-
<?php
namespace App\Http\Controllers;
use App\Bind\FooInterface;
use Illuminate\Support\Facades\App;
class FooController extends Controller
{
public function outOfContainer(){
dd(App::make('\App\bind\FooInterface')); // Focus: program dies here!!
}
}
Bindings for the FooInterface done in the AppServiceProvider as follows
App/Providers/AppServiceProvider.php:-
<?php
namespace App\Providers;
use App\Bind\Foo;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind('\App\Bind\FooInterface', function() {
return new Foo();
});
}
}
Structure of the Foo class as follows.
App/Bind/Foo.php:-
<?php
namespace App\Bind;
class Foo implements FooInterface {
}
Structure of the FooInterface interface as follows:-
<?php
namespace App\Bind;
interface FooInterface {
}
Then I created a route as follows.
Route::get('/outofcontainer', 'FooController#outOfContainer');
But when I navigate to this route it throws an exception with the error text:
BindingResolutionException in Container.php line 748:
Target [App\bind\FooInterface] is not instantiable.
What is going wrong with this?
How to use App:make() with the AppServiceProvider?
In your service provider, you're binding the string '\App\Bind\FooInterface'. In your controller, you're attempting to make the string '\App\bind\FooInterface'. These strings are not the same, as they have differing cases (Bind vs bind). Since the strings are not the same, Laravel cannot find the binding in the container.
Correct the casing in your make statement and it should work:
dd(App::make('\App\Bind\FooInterface'));

Repository pattern Laravel 5

I am starting to learn about Laravel 5 repository pattern, and I can't get anything right! I probably used wrong namespace or 'use'; This is the error i am getting: Class App\Http\Controllers\ServiceController does not exist
This is my Controller:
namespace App\Http\Controllers;
namespace Repo;
use App\Http\Controllers\Controller;
use Repo\ServiceRepository;
class ServiceController extends Controller {
public function __construct(ServiceRepository $service){
$this->service = $service;
}
public function showServices()
{
$services = $this->service->getAllServices();
return view('services', compact('services'));
}
}
Here's the repository:
class ServiceRepository {
public function getAllServices(){
return \App\Service::all();
}
}
And here's my route:
Route::get('/services', 'ServiceController#showServices');
I've tried to change some namespaces but i end up with more errors :/
You have to read a bit about namespaces in PHP.
If your ServiceController is located in app/Http/Controllers directory, then the code has to be like follows:
<?php
namespace App\Http\Controllers;
use Repo\ServiceRepository;
class ServiceController extends Controller
{
public function __construct(ServiceRepository $service)
{
$this->service = $service;
}
public function showServices()
{
$services = $this->service->getAllServices();
return view('services', compact('services'));
}
}
Note that I removed namespace Repo and the first use statement.
A class has to have only a single namespace, so I removed the second Repo namespace.
Namespaces are really simple. In most cases namespace of a class just reflects a path to that class. In your case, it's App\Http\Controllers because your controller is probably located in app/Http/Controllers directory.
I've removed use App\Http\Controllers\Controller because your ServiceController and App\Http\Controllers\Controller are in the same directory, so they are in the same namespace. When two classes are in the same namespace, a full path with a namespace is not necessary for them to be able to access each other.
Hope that this helps.

How to "import" namespaces in Laravel?

I've built an API in Laravel, versioned as follows:
/controllers/api/v1/CommentController.php
/controllers/api/v2/CommentController.php
In my routes I call the correct controllers like so:
Route::resource('notification', 'api\v2\CommentController');
This works, but since I'm using namespaces in my controllers, I have to use the \ approach in order to find classes like \Response in the root namespace?
namespace api\v1;
class NotificationController extends \BaseController {
public function index()()
{
return \Response::json({});
}
}
Is there a way to avoid that backslash notation and using the right namespace?
I tried using use \App; but without result
U need to add "use Response;" to your code.
<?php namespace api\v1;
use Response;
class CommentController extends \BaseController {
public function index()
{
return Response::json('hello');
}
}

Resources