Using pingpong/widget in Laravel throws an error - php

I'm using the laravel's package
"pingpong/widget": "~2.1",
I've set the configuration in config\app.php
Added
Pingpong\Widget\WidgetServiceProvider::class,
and
'Widget' => Pingpong\Widget\WidgetFacade::class,
And as in the documentation, i'm using this code to create a widget:
use Pingpong\Widget\Widget;
Widget::register('small', function($contents)
{
return "<small>{$contents}</small>";
});
But I got this error:
Non-static method Pingpong\Widget\Widget::register() should not be called statically, assuming $this from incompatible context
In the Pingpong\Widget\Widget class, there are no static functions, so of course this error is expected. But... how we can create a widget then, when all sample codes in the documentation are using static classes and in the Widget class, there are no static methods? Am I missing something?
Creating a widget object and calling the ->register() on it also throw an error, because creating a widget expects BladeCompiler $blade, Container $container in the _construct method and I have no idea what to pass here.
Any ideas on what could be wrong with this implementation?

Change use Pingpong\Widget\Widget; to just use Widget;
Laravel, and some packages, include Facades to facilitate easy usage of some components. While everything looks like a static call, the static call on the facade actually maps to a non-static call on a concrete object that is masked by the facade. So, when you're attempting Widget::register(), the facade looks up the concrete instance it has of the Widget class, and then calls the register() method on that instance non-statically.
In your config/app.php file, you've added the Widget alias which points to the WidgetFacade. This alias is created in the base namespace. If you would like to use this alias to the facade, you need to just reference the Widget alias in the base namespace (i.e. use Widget;).
By stating use Pingpong\Widget\Widget;, your Widget::register() call is trying to call a static register() method on the Pingpong\Widget\Widget class, instead of the method on the facade.

Related

Pass class by config using ::class and retrieve in Laravel

I have a config file with such array:
'ppr' => [
'validate' => TestRequest::class
];
Now, I want to retrive this class in other part of the system and use it to validate form (outside of the controller).
While using config('main.ppr.validate') all I receive is namespaced name of the class instead of the class object.
As I already accepted that it won't be that easy to just use reuqests as in controllers, I still do wonder how to pass a class by config.
While passing eloquent models it works like a charm (or i.e. config arrays with middlewares etc.), so I suppose there is some magic binding to the IoC to achive that, is it true?
My question is, how to use class passed as in example above without initializing it like:
$obj = new $className;
Laravel (and many other applications) use Dependency Injection to achieve this magic -- your words, not mine! :D
It seems that the Service Container is what handles this in Laravel and should be of help to you.
Directly from the Laravel docs (linked above):
Within a service provider, you always have access to the container via the $this->app property. We can register a binding using the bind method, passing the class or interface name that we wish to register along with a Closure that returns an instance of the class:
$this->app->bind('HelpSpot\API', function ($app) {
return new HelpSpot\API($app->make('HttpClient'));
});
Also:
You may use the make method to resolve a class instance out of the container. The make method accepts the name of the class or interface you wish to resolve:
$api = $this->app->make('HelpSpot\API');
And:
If some of your class' dependencies are not resolvable via the container, you may inject them by passing them as an associative array into the makeWith method:
$api = $this->app->makeWith('HelpSpot\API', ['id' => 1]);
IMHO, I would look up where/how this is implemented in the native Laravel code (usually the Illuminate vendor) and see how it is used / meant to be implemented.
Furthermore, ClassName::class will return the namespace + class of that class. This is why you only see the class name and are not actually receiving an object/instance of that class.
I'm not sure what/where/why/how you're implementing your class and why you need this functionality somewhere that it doesn't already exist. Laravel is pretty good about already having things set up where you need them, so think twice before breaking out of the box and make sure there isn't a default solution for your situation!

Function uses method from different class than it should

I have TestController, hich doesn't have its own model. I use various model inside it, among them Trunk Model. I have my function "call", that wants to use method "singlePckgCall" from Trunk Model. Until here everything goes okay.
This method, which I'm trying to use, uses another method, placed below - "callSingleNumber".
And then it stops, and sends me an error page:
Unknown Method – yii\base\UnknownMethodException
Calling unknown method:
frontend\controllers\TestController::callSingleNumber()
I have no idea why it wants to call a method from TestController, instead on Trunk Model, as I want it to do. In result, it doesn't see such a method, because it exists in another class. I tried to rewrite this part manually once more, but it didn't help.
You are calling singlePckgCall statically, so inside singlePckgCall method $this instance is not available.
To solve your problem, you can
1) call callSingleNumber statically in singlePckgCall :
$action_id_array[$key] = self::callSingleNumber($numery[$i], TRUE);
at row 52
2) create an instance of Trunk class, so $this is available in singlePckgCall:
$instance = new Trunk();
$instance->singlePckgCall($numery);

How to use javascript in Yii2 model class?

In a custom validation function in my model class. I need to use javascript code. for that i used registerJs function but i am getting error:-
Calling to undefined function registerJs()
I also tried calling it by including View class i.e., View::registerJs() but it is also giving error called
Non-static method yii\web\View::registerJs() should not be called statically, assuming $this from incompatible context
How can i user Javascript in Yii2 model class.
Edit:
I have created a custom function for mobile number validation and calling that function from rules section of model. Now i want to use javascript code in that function. is there any other way to achive it?
Thanks in advance
That method is not static. If you open the view.php of the framework you can check out the implementation.
public function registerJs($js, $position = self::POS_READY, $key = null){..
}
Exception clearly mentions that should not be called statically because it is not declared static.
I have seen few of the implementations which call this method as:
$view->registerJs($js, $view::POS_END);
Basically loading a particular JS file in one of the functions.
It is not a good idea using Javascript with a model. If you go that way then probably after some time you will find you heading into big problems with the architecture of the app.
The best way is to call the model inside a controller and then interact with the controller through the Javascript code.

Laravel 5.1 Documentation for Mail - confusing?

I am still new to Laravel 5.1, but I found the documentation very strange and confusing.
For example - according to the Laravel docs I can use send() method from the Mail facade to send email.
So far, so good. When I go to Laravel API and find Illuminate Support Facades Mail such method doesn't exist? https://laravel.com/api/5.1/Illuminate/Support/Facades/Mail.html
How can I understand what parameters this method takes and what it is returning on success/failure?
That's because it is using the Facade pattern.
In your app.php config file there is a section called 'aliases'. There is a line in that section: 'Mail' => Illuminate\Support\Facades\Mail::class, which points to the Facade, which returns the key of the bind in the service container (IoC) which returns the class/object to work with.
So you need to find the place where the bind is created. Binds are created by the methods App::bind('foo', .. ), App::singleton('foo', .. )or App::instance('foo', .. ).
I search for 'mailer' and found the file lluminate\Mail\MailServiceProvider where the bind is created:
$this->app->singleton('mailer', function($app) {
...
// this is the class resolved by the IoC.
$mailer = new Mailer(
$app['view'], $app['swift.mailer'], $app['events']
);
...
return $mailer;
});
As you can see, the class \Illuminate\Mail\Mailer is returned in the service provider and that is the class used when you use the Facade called Mail.
Quick way to discover the class behind the Facade:
You can also find the name of the class quickly by dumping the class name: dd( get_class( Mail::getFacadeRoot() ) );
More information
More information about the service container: Click!
More information about Facades in Laravel 5: Click!
More information about the Facade pattern: Click!
The Facade classes are basically helper classes to provide quick, easy access to the real classes that do the work. There's plenty of debate on the merits of facades, but that is not for this question.
If you call the getFacadeRoot() method on the facade, it will give you the instance of the object to which the facade points (e.g. Mail::getFacadeRoot() == \Illuminate\Mail\Mailer).
Now that you know the actual object being used, you can look up the methods on that object. Any methods you call on the Facade are passed through to the object that is returned by getFacadeRoot(). So, when you are calling Mail::send(), you are actually calling \Illuminate\Mail\Mailer::send() (though, non statically).

Statically calling methods causes not being able to reference $this within called class?

I don't usually call methods statically but since working with the Yii framework I have started to more.
I'm experiencing an issue which I haven't come across before, I am doing this from a SignupForm class:
$send = mail::sendMail($email_data);
..inside the sendMail method which is obviously inside the mail class I have this line:
$email_data['message'] = $this->sanitizeMsg($email_data['message']);
The sanitizeMsg is a method of the mail class and hence that's why I thought referencing it via $this should work.
However I am getting the error:
Calling unknown method: app\models\SignupForm::sanitizeMsg()
Why is it looking for it in the SignupForm class? Does this have something to do with me calling it statically? Do I need to revert to using self:: instead or should I stop calling it statically?
Using $this only works for member methods. I.e. you can only use it from an instance of the class and I believe also only to access instance members.
To access static members, you should use self::.
Not familiar with the Yii framework, but what someone does is to use static methods as factory methods. Maybe that's what you're confused by. The static method then creates a new instance of itself and returns it, and inside that instance you can of course use $this, but not in the static method. Static methods have no $this.

Categories