Laravel 5.1: Calling a function from string - php

Currently I'm trying to call a function from a string.
This is the function, that I'll call later:
<?php
namespace App\Validation\Options;
class FacebookOptionValidation
{
static public function validate()
{
echo: 'example';
die();
}
}
Here is my controller:
<?php
namespace App\Http\Controllers\Profile;
use App\Validation\Options;
class ProfileUserEditController extends Controller {
public function updateUserOption()
{
$class = 'Options\FacebookOptionValidation';
$class::validate();
}
}
In this case Laravel shows an error:
Class 'Options\FacebookOptionValidation' not found
But when I call my function like this, everything works fine:
use App\Validation\Options;
class ProfileUserEditController extends Controller {
public function updateUserOption()
{
Options\FacebookOptionValidation::validate();
}
}
As mentioned here, it's possible to call a class/function from a string. But in my case it's not possible - neither in the static or non-static variant.
Is that a 'laravel-thing'?

Try call with full namespace
class ProfileUserEditController extends Controller {
public function updateUserOption()
{
$class = 'App\Validation\Options\FacebookOptionValidation';
$class::validate();
}
}

With PHP7 you can even do this:
(App\Validation\Options\FacebookOptionValidation::class)::validate();
One line of code and without using a string

Related

How to Invoke Object that's a Public Property

Take the following example of two classes:
class Yolo {
public function __invoke() {
echo 'YOLO';
}
}
class Swag {
public $yolo;
public function __construct() {
$this->yolo = new Yolo();
}
}
Is it possible to invoke the Yolo object via an instance of Swag?
(new Swag())->yolo(); throws a warning and doesn't call __invoke:
PHP Warning: Uncaught Error: Call to undefined method Swag::yolo()
In PHP 7 you can directly call it (just need extra braces):
((new Swag())->yolo)();
In PHP 5 you need a temp variable:
$y=(new Swag())->yolo;
$y();
The problem is that you try to call the function yolo() on the Swag class. In your case you have to use the public class variable and call the subclass over that.
var_dump((new Swag())->yolo);
that is your object. When you use () you try to call the class not the class variable.
You do not even have to make it a public method.
But you might have to reroute the call manually since the callable method is created at runtime:
class Yolo {
public function __invoke() {
echo 'YOLO';
}
}
class Swag {
private $yolo;
public function __construct() {
$this->yolo = new Yolo();
}
function __call($method, $args) {
if(is_callable($this->$method))
{
return call_user_func_array($this->$method, $args);
}
}
}
(new Swag())->yolo();
It would probably a good idea to check first, if the called method exists and if it is actually callable.
But the example works as a proof of concept.

Can't extend abstract PHP class

I want a base class to be extended, but I have some errors coming out:
Fatal error: Class 'Api\Services\Base' not found in
/var/www/html/Api/Services/Example.php on line 7
I searched for typos, tried to use the fully qualified name, made the abstract class empty or just defined it as a simple class; none of these helped.
Using "require" instead of "use" worked, but still...
Any idea (the two files are in the same directory: /var/www/html/Api/Services)?
Thanks in advance...
<?php
// Base.php
namespace Api\Services;
use Api\Classes\ErrorHandler;
use Api\Classes\ErrorMessage;
abstract class Base
{
public $data = null;
public function getData()
{
return $this->data;
}
public function setData($data = null)
{
$this->data = $data;
}
}
?>
<?php
// Example.php
namespace Api\Services;
use Api\Services\Base;
class Example extends Base
{
public $request = array();
public function __construct($request = array())
{
$this->request = $request;
}
}
?>
use Base
instead of
use Api\Services\Base;
because you are already inside the namespace Api\Services
Actually, you don't even have to write the use statement, you are inside the namespace, you can just call the classes inside the same namespace without including them (use)

CHtml::resolveName() cannot pass parameter 2 by reference

I got this error message when working with CHtml::resolveName: cannot pass parameter 2 by reference.
here is my simple test code:
<?php
class TestController extends CController {
public function test() {
var_dump(CHtml::resolveName($myModels, 'someAttribute');
exit;
}
}
when I route to this action, it always throws an error. However when I changed the code like this
<?php
class TestController extends CController {
public function valid($model, $attribute) {
return CHtml::resolveName($model, $attribute);
}
public function test() {
var_dump($this->valid);
exit;
}
}
It works!
I have read the documentation for the CHtml::resoveName() method in Yii framework, and it uses argument reference. But I don't know why it throws an error when using the first code, it's actually the same as the second one.
Could you help me understand this situation?
Thank you!
I think you are missing one closing bracket for var_dump function.
<?php
class TestController extends CController {
public function test() {
var_dump(CHtml::resolveName($myModels, 'someAttribute'));
exit;
}
}
?>
One more thing,
You did not use the function CHtml::resolveName correctly. It does not passes variable name, passes its reference.
Check Here
<?php
class TestController extends CController {
public function test() {
$attribute = 'someAttribute';
var_dump(CHtml::resolveName($myModels, &$attribute));
exit;
}
}
?>
Just rewrite like this:
CHtml::resolveName($myModels, $dummy='someAttribute')
This is because the attribute name passed to function call as variable reference. $dummy='someAttribute' creates temporary variable $dummy to pass it.

PHP 'non-object' error [duplicate]

This question already has answers here:
Call to a member function on a non-object [duplicate]
(8 answers)
Closed 10 years ago.
I'm working on a small MVC framework in PHP for an exercise. PHP, however, doesn't seem to like my Controller class. The class contains an instance of a loader that loads views:
abstract class Controller
{
public $load;
function __construct($load)
{
$this->load = $load;
}
abstract public function index();
}
From there, I can override Controller for all my controllers. For instace, my index controller:
class Index extends Controller
{
public function index()
{
$this->load->view("hello_world");
}
}
But when I create it:
require 'Controller.php';
require 'Load.php'
require 'controllers/Index.php';
$i = new Index(new Load());
$i->index();
I get this error:
PHP Fatal error: Call to a member function view() on a non-object in /var/www/controllers/Index.php on line 7
Can you guys help me out? I know I set the load in the constructor, and the load class does have a method called view, so why is it giving me this error?
Also: Load class, just for good measure
class Load
{
public function view($filename, $data = null)
{
if(is_array($data)) extract($data);
include ROOT.DS.'views'.DS.$filename.'.php';
}
}
The problem is with this code, and it's not always obvious:
class Index extends Controller
^^^^^
{
public function index()
^^^^^
{
$this->load->view("hello_world");
}
}
This is the same name and therefore a PHP 4 backwards compatible constructor. The parent's constructor then is not called, $load not set and the function not defined.
Knowing this, there are many solutions, including:
namespace DelishusCake;
Introduce a Namespace
This automatically fixes your issue. You need to place this on top of the file.
class Index extends Controller
{
public function index($load = NULL)
{
isset($load) && $this->load = $load;
$this->load->view("hello_world");
}
}
Make the PHP4 backwards compatible constructor work
Or:
class MyIndex extends Controller
{
public function index()
{
$this->load->view("hello_world");
}
}
Rename the class
Or:
class Index extends Controller
{
public function __construct($load) {
parent::__construct($load);
}
public function index()
{
$this->load->view("hello_world");
}
}
Add a PHP 5 constructor, call the parent's constructor
Keep in mind that you only need this because it's the same name. The in depth description you can find as well in the PHP Manual on the Constructors and Destructors page.
You need to instantiate the parent class.
class Index extends Controller
{
public function __construct($load) {
parent::__construct($load);
}
public function index() {
$this->load->view("hello_world");
}
}

How to call static func by passing $_GET params?

i have got a static function> which is called
regenerateThumbnailsCron()
And I would like to execute this function by GET params, for example>
if($_GET["pass"]=="password")
self::regenerateThumbnailsCron();
But if I tryied to call this function in constructor>
class AdminImages extends AdminTab
...
public function __construct()
{
if($_GET["pass"]=="password")
self::regenerateThumbnailsCron();
}
I cannot execute this function.
Is any way, how to call this function before __construct to correctly execute?
Thanks very much for any advice.
EDIT>
I tried also with public function>
<?php
include 'AdminImages.php';
$images = new AdminImages();
$images->regenerateThumbnailsCron();
?>
But i got error>
Fatal error: Class 'AdminTab' not found
You need to do a include 'AdminTab.php'; as well, since your class extends that
Not completely sure I understand your question, are you saying that you have static class "B" which extends class "A", "A" having your regenerateThumbnailsCron() method which you want to call before anything else?
If so then try this:
<?php
class A {
private function regenerate() {
.... do something ....
}
}
class B extends A {
function __construct() {
if ($_GET["pass"] == "password") {
parent::regenerate();
}
}
function regenerateThunbnailsCron() {
.... do somethinig ....
}
}
$images = new B();
$images->regenerateThumbnailsCron();
?>
This way, your parent's "regenerate()" function would get called during the constructor. You can switch this around to be a static class if you want, which if your goal is to compartmentalise any variables and functions away from the global scope would be a better way.

Categories