How to inject class in laravel - php

I am new to laravel and I have two of these classes
namespace Kharota\Libraries;
class Input {
public function input($input)
{
echo "inèut";
}
}
and Form Class
namespace Kharota\Libraries;
class Forms
{
public static function form($params, $callback)
{
if(is_callable( $callback)) {
call_user_func( $callback);
}
}
}
I am trying to call like this
use Kharota\Libraries\Forms;
use Kharota\Libraries\Input;
...
Forms::form( [], function(Input $input) {
$input->input( [] );
});
But I am getting error
(1/1) ErrorException
Argument 1 passed to Illuminate\Support\ServiceProvider::{closure}() must be an instance of Kharota\Libraries\Input, none given
How I can fix it?

You should write use Kharota\Lib... between <?php and class OtherClass.

Related

cant use laravel facase inside the package

i am trying to write a package for laravel . i want to use facade and call some dynamic class with :: like this :
Zaya::test();
so , my structure is /packages/company/zaya and here is my composer for package :
"extra": {
"laravel": {
"providers": [
"Company\\Zaya\\ZayaServiceProvider"
],
"aliases": {
"Zaya": "Company\\Zaya\\ZayaFacade"
}
}
this is my fadace :
protected static function getFacadeAccessor()
{
return 'zaya';
}
and this is my service provider :
// Register the main class to use with the facade
$this->app->singleton('zaya', function () {
return new Zaya;
});
and finally this is my class :
<?php
namespace company\Zaya;
class Zaya
{
public function test()
{
return 123;
}
}
now in my controller when i call :
dd(Zaya::test());
i get this error :
"message": "Non-static method Company\\Zaya\\Zaya::test() should not be called statically",
You can use the app helper to resolve the class:
class MyFacade
{
public static function __callStatic($method, $arguments)
{
$class = app(MyClass::class);
return $class->$method(...$arguments);
}
}
To use it:
MyFacade::foo();
MyFacade::bar();
MyFacade::baz();
// or in your case
Zaya::test();

Laravel: Test not Using Mocked Method

I want getNumber to return 200 in the test case, but when I run the test and inspect the result with $response->dump() I can see that the mock is not overriding the method as it is showing array:1 [0 => 100]. What am I missing?
Controller:
class ServiceController extends Controller
{
public function fetch(Request $request)
{
$service = new Service();
return [$service->getNumber()];
}
}
Model:
class Service extends Model
{
public function getNumber(): int
{
return 100;
}
}
Test:
class ControllerTest extends TestCase
{
public function testFetchGetsNumber()
{
$mock = $this->partialMock(Service::class, function (MockInterface $mock) {
$mock->shouldReceive('getNumber')->andReturn(200);
});
$response = $this->post('/api/controller');
$response->dump(); // returns 100 but should return 200...
}
}
I am using Laravel 8 and referencing this documentation: https://laravel.com/docs/8.x/mocking#mocking-objects
In Laravel you have to use the container to mock classes.
$service = resolve(Service::class);
In constructors or handle methods, if you inject your classes there it will automatically use the container. If put into constructors or classes, remember the resolution of the class with the constructor, have to use the container.
class Job
{
public function handle(Service $service)
{
// will use the mocked service.
}
}

Laravel 5.6 passing eloquent model as parameter to a function

I have a selection control on a blade form that is to be refreshed via ajax through this function:
function getOpciones(tbName) {
$.get('/ajax/read-data/' + tbName, function(data){
return (data);
});
}
The function takes a string variable 'tbName' whith the name of the table the control is related to, and passes it on as a parameter to the route:
Route::get('/ajax/read-data/{modelo}', 'AjaxController#readData');
Then the controller should get the parameter {modelo}, and retrieve the records in that table:
use App\RegFiscal;
public function readData($modelo) {
$arreglo = $modelo::all();
return response($arreglo);
}
But even though I am referencing the model with 'use App\RegFiscal', all I get is this error in laravel log:
2018-03-23 18:52:08] local.ERROR: exception
'Symfony\Component\Debug\Exception\FatalErrorException' with message
'Class 'RegFiscal' not found' in
C:\wamp64\www\laravel\cte\app\Http\Controllers\AjaxController.php:32
I´m new to Laravel, so needless to say I am lost and any help would be greatly appreciated. Thanks!
Just because you use App\RegFiscal doesn't mean $modelo is associated with it.
What you can do, though, is use app("App\\$modelo") to load in your model based on the parameter you get from the router. You would no longer need to use App\RegFiscal either.
$arreglo = app("App\\$modelo");
return response($arreglo::all());
This is assuming your model is stored in the default app directory within your Laravel project. If not you can change "App\" to where ever it is stored. If for example your model is in app\models\modelname.php it would be "App\Models\\$modelo".
You can do this as the following:
public function readData($modelo) {
$modelName = '\App' . '\\' . $modelo;
$class = new $modelName();
arreglo = $class::all();
return response($arreglo);
}
To those like me who wanted to inject it on a constructor, here's how to do it:
~$ php artisan make:provider MyProvider
Then override the register function like so:
class MyProvider implements ServiceProvider {
/** #override */
public function register() {
$this->app->bind(ShapeInterface::class, function ($app) {
return new Square($app->make(MyModel::class));
});
}
}
The ShapeInterface is a simple interface and Square is a simple class that implements the shape interface with a constructor parameter of the eloquent model.
class Square implements ShapeInterface {
private MyModel $model;
function __construct(MyModel $model) {
$this->model = $model;
}
...
}

Laravel ::__construct() must implement interface

I'm using Laravel 5.4 And I'm trying to inject a $order class into a trait that's going to implemented by a model. Like this:
class Forum extends Model
{
use Orderable;
The constructor of the trait looks like this:
trait Orderable
{
public $orderInfo;
public function __construct(OrderInterface $orderInfo)
{
$this->orderInfo = $orderInfo;
}
My service provider looks like this:
public function register()
{
$this->app->bind(OrderInterface::class, function () {
return new Order(new OrderRepository());
});
$this->app->bind(OrderRepositoryInterface::class, function () {
return new OrderRepository();
});
}
The constructor of my Order class looks like this:
public function __construct(OrderRepositoryInterface $orderInfo)
{
$this->orderInfo = $orderInfo;
}
But I receive the error:
Type error: Argument 1 passed to App\Forum::__construct() must implement interface Project\name\OrderInterface, array given, called in /home/vagrant/Code/Package/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php on line 268
The OrderRepository class is implementing the OrderRepositoryInterface. The Order class is implementing the OrderInterface interface.
App\Forum is the model that uses the Orderable trait.
What could I be doing wrong here?
You are extending Model. This class already has a __construct that you need to use. This __construct expects array $attributes = [] as the first argument.
So in your __construct you also need to have this as the first argument and pass this to the parent class:
public function __construct(array $attributes = [], OrderRepositoryInterface $orderInfo)
{
$this->orderInfo = $orderInfo;
parent::__construct($attributes);
}
However you can work around using __construct in laravel using boot.
For example in a Model:
class Forum extends Model
{
protected static function boot()
{
parent::boot();
// Do something
}
}
Or in a Trait:
trait Orderable
{
public static function bootOrderableTrait()
{
static::created(function($item){
// Do something
});
}
}
In PHP it's not possible to have multiple constructors. If you will look to Model:
public function __construct(array $attributes = [])
it expect array. That's why I assume that somewhere in Model array passed to constructor instead of 'OrderInterface'.

Unable to pass class instance to constructor

I have installed this package https://github.com/Intervention/image with composer. I have added
'IntImage' => 'Intervention\Image\Facades\Image'
to config/app under aliases
I get the following error and cant figure out what I am doing incorrectly I am sure it has something to do with namespacing /autoloading but app/acme is in the psr-o section of composer.json
'Argument 1 passed to
Acme\Services\Images\InterventionImageEditor::__construct() must be an
instance of IntImage, none given, called in
/var/www/app/ACme/Providers/ImageEditorServiceProvider.php on line 14
and defined' in
/var/www/app/Acme/Services/Images/InterventionImageEditor.php:11
I have the following directory structure
app
acme
Providers
ImageEditorServiceProvider.php
Services
Images
ImageEditorInterface.php
InterventionImageEditor.php
and the content of the files
ImageEditorServiceProvider.php
<?php namespace Acme\Providers;
use Illuminate\Support\ServiceProvider;
use Acme\Services\Images\InterventionImageEditor;
/**
*
*/
class ImageEditorServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind('Acme\Services\Images\ImageEditorInterface', function () {
return new InterventionImageEditor();
});
}
}
ImageEditorInterface.php
<?php namespace Acme\Services\Images;
interface ImageEditorInterface
{
public function hello();
}
InterventionImageEditor.php
<?php namespace Acme\Services\Images;
use IntImage;
/**
*
*/
class InterventionImageEditor implements ImageEditorInterface
{
protected $imageeditor;
public function __construct(IntImage $imageeditor)
{
$this->imageeditor = $imageeditor;
}
public function hello()
{
$hello = 'hello';
return $hello;
}
}
Can I
Use IntImage;
in this way because it is a facade or am I missing something?
edit to include solution;
changing the service provider to the following resolved the problem
<?php namespace Acme\Providers;
use Illuminate\Support\ServiceProvider;
use Acme\Services\Images\InterventionImageEditor;
use IntImage;
/**
*
*/
class ImageEditorServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind('Acme\Services\Images\ImageEditorInterface', function () {
$intimage = new IntImage;
return new InterventionImageEditor($intimage);
});
}
}
The error is coming from ImageEditorServiceProder.php:
$this->app->bind('Acme\Services\Images\ImageEditorInterface', function () {
return new InterventionImageEditor();
});
Here you are instantiating the InterventionImageEditor without any parameters. You InterventionImageEditor requires one parameter of type IntImage.
If there are places where you won't have IntImage when instantiating InterventionImageEditor then you need to update your InterventionImageEditor::__construct so that it accepts null(possibly).
function __construct(IntImage $imageeditor = null)
{
if (is_null($imageeditor)) {
// Construct a default imageeditor
// $imageeditor = new ...;
}
$this->imageeditor = $imageeditor;
}
i am not sure you can using IntImage because this file is Facades.
if you want to extending the intervention class. you should add Intervention\Image\Image to your ImageEditorServiceProvider.
use Intervention\Image\Image;
class ImageEditorServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind('Acme\Services\Images\ImageEditorInterface', function () {
return new InterventionImageEditor(new Image);
});
}
}

Categories