Laravel 5.8 dependecy injection - how to inject model to service - laravel-5

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.

Related

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

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'));
}
}

bind abstract class service in provider laravel

Gives an error:
Target [MyVendor\ProductList\ProductServiceInterface] is not instantiable.
ProductServiceInterface
namespace MyVendor\ProductList;
interface ProductServiceInterface
{
public function productList();
public function getProductSpeed();
}
ProductColorService
namespace MyVendor\ProductList\Service;
abstract class ProductColorService implements \MyVendor\ProductList\ProductServiceInterface
{
public function productList()
{
$color = "black";
return $color;
}
}
** ProductSpeedService **
namespace MyVendor\ProductList\Service;
abstract class ProductSpeedService implements \MyVendor\ProductList\ProductServiceInterface {
public function getProductSpeed() {
$speed = 200;
return $speed;
}
}
Provider :
namespace MyVendor\ProductList;
use Illuminate\Support\ServiceProvider;
use MyVendor\ProductList\ProductServiceInterface;
use MyVendor\ProductList\Service\ProductColorService;
class ProductColorServiceProvider extends ServiceProvider
{
public function boot()
{
$this->loadRoutesFrom(__DIR__ . '/routes/color.php');
}
public function register()
{
$this->app->bind('MyVendor\ProductList\ProductServiceInterface','MyVendor\ProductList\Service\ProductColorService');
$this->app->bind('MyVendor\ProductList\ProductServiceInterface','MyVendor\ProductList\Service\ProductSpeedService');
}
}
Whats wrong in this code? Actually I need to override some functions in interface using service. ie each service should override one method.
namespace MyVendor\ProductList\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use MyVendor\ProductList\Models\Product;
use MyVendor\ProductList\ProductServiceInterface;
class ProductListController extends Controller
{
public function index(ProductServiceInterface $product_service)
{
$color = $product_service->productList();
$speed = $product_service->getProductSpeed();
dd($color," = ",$speed);
$product = Product::get();
return view('ProductList::product',compact('product'));
}
}
here productList() in one service and productSpeed() from another service
You can't instantiate abstract classes. The whole point of them is there can never be an instance of them, so if you bind your interface to your abstract class with a method, it simply can never be abstract. Abstract is for classes in inheritance structures you do not want to have the users to create new ones.
So there is no reason for the abstract, abstract is for something like this.
abstract class Vehicle {
protected $wheels;
public function getWheels() {
return $this->wheels;
}
}
class Car extends Vehicle {
protected $wheels = 4;
}
class Bike extends Vehicle {
protected $wheels = 2;
}
You can not make a vehicle as it is not a concrete implementation, as it is a parent class to help with methods shared across two classes. So short version, just remove the abstract keyword. If you don't know why you add it, it is not needed.

Laravel abstract class auto injection

Laravel auto injects abstract class , but when there is another parameter with abstract class, Laravel ignore it and hence, getting error.
public interface PostRepository {
public function getPostById($id)
}
class EloquentPost implements PostRepository{
public function getPostById($id){
return Post::find($id);
} }
Its working fine when I use it like:
class Controller PostController {
private $post;
public function __construct(PostRepository $post)
$this->post = $post;
}
But when I use it like
class Controller PostController {
private $post;
public function __construct($someOtherParam, PostRepository $post)
$this->post = $post;
}
then Laravel show error.
Laravel is unable to determine what should be injected as the first parameter to the controller's constructor as you have no type hint for that parameter.
If that $someOtherParam is something that should come in the URL, you will be able to have that injected in controller's action method to which given route points, but not in the constructor.

how to access to laravel global Classes in packages

I am developing a Laravel package . In the packeges I need to File::delete for delete files, but The following error message is displayed :
Class 'Chee\Image\File' not found
Can you help me?
You have to declare it in the top of your class:
namespace Chee\Image;
use File;
class Whatever()
{
}
Instead of using the File Facade, you can also get it directly from the Laravel IoC container:
$app = app();
$app['files']->delete($path)
In a service provider, you can inject it as a dependency your package class:
class Provider extends ServiceProvider {
public function register()
{
$this->app['myclass'] = $this->app->share(function($app)
{
return new MyClass($app['files']);
});
}
}
And receive it in your class:
class MyClass {
private $fileSystem;
public function __construcy($fileSystem)
{
$this->fileSystem = $fileSystem;
}
public function doWhatever($file)
{
$this->fileSystem->delete($file)
}
}
You should be able to just use:
\File
Namespaces are relative to the namespace you declare for the class you are writing. Adding a "\" in front of a call to a class is saying that we want to look for this class in the root namespace which is just "\". The Laravel File class can be accessed this way because it is an alias that has an declared in the root namespace.
Assuming you have file something like that:
<?php
namespace Chee\Image;
class YourClass
{
public function method() {
File::delete('path');
}
}
you should add use directive:
<?php
namespace Chee\Image;
use Illuminate\Support\Facades\File;
class YourClass
{
public function method() {
File::delete('path');
}
}
Otherwise if you don't use PHP is looking for File class in your current namespace so it is looking for Chee\Image\File. You could look at How to use objects from other namespaces and how to import namespaces in PHP if you want

how to call model in laravel from controller

How to call a model in laravel.
My code is:
use Jacopo\Authentication\Models\Guide;
class SampleController extends BaseController
{
public function index()
{
$model='Guide';
$guide=$model::where('guide_link','=',"guide")->get();
print_r($guide);
}
}
This will produce Class 'Guide' not found error.
If you added your class you should run in terminal
composer dump-autoload
to update your class map. Otherwise autoloader may not "see" your class and you are getting this error.
You need to add the namespace to your string:
class SampleController extends BaseController
{
public function index()
{
$model='Jacopo\Authentication\Models\Guide';
$guide=$model::where('guide_link','=',"guide")->get();
print_r($guide);
}
}
You could also resolve it from the IoC container, but you need to register it first:
App::bind('Guide', 'Jacopo\Authentication\Models\Guide');
And then you should be able to:
$model = App::make('Guide');
$guide = $model::where('guide_link','=',"guide")->get();
But this is not a very good option

Resources