I laravel 9 app I use EmailingServiceProvider with conditional binding of EmailingService depending
on configuration :
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class EmailingServiceProvider extends ServiceProvider
{
public function register()
{
$emailingSupport = config('app.emailing_support');
if($emailingSupport === 'MailerLiteApi') {
$this->app->bind('App\Library\Services\EmailingServiceInterface', 'App\Library\Services\EmailingService');
}
}
}
class EmailingService is called in controller ok, except cases when I want to comment binding code above :
// $this->app->bind
I tried to use example at https://www.php.net/manual/en/reflectionclass.isinstantiable.php as :
...
use App\Library\Services\EmailingServiceInterface;
class AuthorController extends Controller
{
private AuthorMethodsServiceInterface $authorMethodsService;
private EmailingServiceInterface $emailingService;
public function __construct(AuthorMethodsServiceInterface $authorMethodsService /*, EmailingServiceInterface $emailingService*/ )
{
parent::__construct();
$this->authorMethodsService = $authorMethodsService;
// $this->emailingService = $emailingService; // I had to comment this and declarations above
}
// I expected that $reflectionClass->isInstantiable() would have false value below
$reflectionClass = new \ReflectionClass('EmailingService'); // Line points at this line
if $reflectionClass->isInstantiable()) {
$this->emailingService = new EmailingService();
$assignedAuthor = $this->emailingService->method();
But I ggot error":
"message": "Class \"EmailingService\" does not exist",
"exception": "ReflectionException",
How that can be done ?
MODIFIED BLOCK :
That does not work. With lines :
use App\Library\Services\EmailingServiceInterface;
...
$yourService=new EmailingService(); // Error pointing at this line
if ($author instanceof \Illuminate\Http\JsonResponse and $yourService instanceof EmailingServiceInterface) {
...
I got error:
"message": "Class \"App\\Http\\Controllers\\EmailingService\" not found",
"exception": "Error",
?
Thanks!
you can use instanceof
use App\Library\Services\EmailingServiceInterface;
if ($yourService instanceof EmailingServiceInterface) {
//
}
Related
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();
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.
I don't understand Why I can't create custom services. I get errors with the both technic. I don't find anything about that in your doc.
# app/config/services.yml
services:
jdf.utils.phphelper:
class: JDF\Utils\PhpHelper
// src/JDF/Utils/PhpHelper.php
namespace JDF\Utils;
class PhpHelper
{
/**
* [pdebug description]
* #param string $var The string to beautiful show
* #param string $msg Description of the $var
* #param integer $displayNone
* #return echo pre print_r $var string
*/
public function pdebug ($var, $msg = '', $displayNone = 0) {
}
}
Case 1 : (Pass PhpHelper in the __construct function)
// src/JDF/CsvTreatmentBundle\Controller/ImportController
namespace JDF\CsvTreatmentBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use JDF\Utils\PhpHelper;
use Psr\Log\LoggerInterface;
/**
*
*/
class ImportController extends Controller {
function __construct(
PhpHelper $PhpHelper
) {
}
public function indexAction() {
//$test = $this->container->get('jdf.utils.phphelper');
return new Response('<hr>');
}
} /*End of class*/
Error 1 :
Catchable Fatal Error: Argument 1 passed to JDF\CsvTreatmentBundle\Controller\ImportController::__construct() must be an instance of JDF\Utils\PhpHelper, none given, called in C:\kitutilitaire\vendor\symfony\symfony\src\Symfony\Component\HttpKernel\Controller\ControllerResolver.php on line 202 and defined
500 Internal Server Error - ContextErrorException
Case 2 (just use get() controller method) :
// src/JDF/CsvTreatmentBundle\Controller/ImportController
namespace JDF\CsvTreatmentBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use JDF\Utils\PhpHelper;
use Psr\Log\LoggerInterface;
/**
*
*/
class ImportController extends Controller {
function __construct(
//PhpHelper $PhpHelper
// LoggerInterface $logger
) {
}
public function indexAction() {
$test = $this->container->get('jdf.utils.phphelper');
// $logger = $this->container->get('logger');
return new Response('<hr>');
}
} /*End of class*/
Error 2 :
Attempted to load class "PhpHelper" from namespace "JDF\Utils".
Did you forget a "use" statement for another namespace?
Stack Trace
in var\cache\dev\appDevDebugProjectContainer.php at line 3555 -
*/
protected function getJdf_Utils_PhphelperService()
{
return $this->services['jdf.utils.phphelper'] = new \JDF\Utils\PhpHelper();
}
/**
EDIT : composer.json autoload
"autoload": {
"psr-4": {
"AppBundle\\": "src/AppBundle/",
"JDF\\CsvTreatmentBundle\\": "src/JDF/CsvTreatmentBundle/",
"JDF\\Utils\\": "src/JDF/Utils/PhpHelper"
},
"classmap": ["app/AppKernel.php", "app/AppCache.php"]
},
Thank in advence for your help.
Controllers do not get any injection by default. They have $this->container always available to get to all your services.
So nothing more to do than:
class ImportController extends Controller {
public function indexAction() {
$test = $this->container->get('jdf.utils.phphelper');
// $logger = $this->container->get('logger');
return new Response('<hr>');
}
}
FYI: The cache file appDevDebugProjectContainer is auto generated and of no significance to your problem.
I've solved the problem with change my composer.json.
For can use $this->container->get('jdf.utils.phphelper'); the all good code is :
# app/config/services.yml
services:
jdf.utils.phphelper:
class: JDF\Utils\PhpHelper
// src/JDF/Utils/PhpHelper.php
namespace JDF\Utils;
class PhpHelper {}
// src/JDF/CsvTreatmentBundle\Controller/ImportController
namespace JDF\CsvTreatmentBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use JDF\Utils\PhpHelper;
/**
*
*/
class ImportController extends Controller {
public function indexAction() {
$test = $this->container->get('jdf.utils.phphelper');
return new Response('<hr>');
}
} /*End of class*/
AND IMPORTANT : The composer.json :
"autoload": {
"psr-4": {
"JDF\\CsvTreatmentBundle\\": "src/JDF/CsvTreatmentBundle/",
"JDF\\Utils\\": "src/JDF/Utils/"
},
"classmap": ["app/AppKernel.php", "app/AppCache.php"]
},
And the CLI command : php composer.phar dump-autoload
Thank to colburton for this time and interest at my issue.
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);
});
}
}
namespace etc...
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Bundle\TwigBundle\Controller\ExceptionController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernel;
use Symfony\Component\HttpKernel\Exception\FlattenException;
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
use Symfony\Component\HttpFoundation\Response;
class MyExceptionController extends ExceptionController
{
public function showAction(Request $request, FlattenException $exception, DebugLoggerInterface $logger = null, $format = 'html')
{
}
}
Doing nothing inside the controller returns a "Uncaught exception 'Symfony\Component\Routing\Exception\ResourceNotFoundException' in..." error. Not sure if that's right, or if that's another problem. I'd expect it to just do the usual action.
I just need to do it so it shows a specified route exactly as it would if I went to domain.com/page.
I've tried this:
$httpKernel = $this->container->get('kernel');
$response = $httpKernel->forward('AcmeMyBundle:Default:pageAction');
$this->setResponse(new Response($response));
...but get this error:
Call to a member function get() on a non-object in...
Your code looks similar to something I did yesterday. I wanted to get all NotFoundHttpException Exception and try to forward them to a default controller. I achieved this with an exception listener like this:
<?php
namespace Acme\MyBundle\Listener;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
class NotFoundHttpExceptionListener
{
protected $container;
public function setContainer($container)
{
$this->container = $container;
}
public function onKernelException(GetResponseForExceptionEvent $event)
{
$exception = $event->getException();
if ($exception instanceof NotFoundHttpException) {
$httpKernel = $this->container->get('http_kernel');
$response = $httpKernel->forward(
'AcmeMyBundle:Controller:action',
array(
'uri' => $_SERVER['REQUEST_URI'],
)
);
$response->headers->set('X-Status-Code', '200');
$event->setResponse($response);
$event->stopPropagation();
}
}
}
Note that X-Status-Code is necessary if you want to return another status code than 404 because the handleException method in HttpKernel will use this to set the final status code and removes it from the header section.
My services.yml looks something like this:
notfoundhttp.exception.listener:
class: Acme\MyBundle\Listener\NotFoundHttpExceptionListener
calls:
- [ setContainer, [#service_container] ]
tags:
- { name: kernel.event_listener, event: kernel.exception, method: onKernelException }