Unable to compare magic constant __METHOD__ - php

Ok, I think I have something here...
Inside a class, im trying to condition a private function based on the used method's name.
So the code looks something like:
<?php
class my_class{
public function my_method($arg1) {
$this->private_function($arg1);
}
private function private_function($arg2){
if (__METHOD__ == "my_class::my_method"){
#THIS FAILS
}else{
#THIS WORKS
}
return;
}
}
(new my_class())->my_method($something);
If I do a var_dump() on __METHOD__ at the same level im trying to use it I'll get a nice string(19)"my_class::my_method". So I'm comparing a string to another one.
The following will also fail:
Cast both vars to string and compare them.
Copy __METHOD__ to a (string) $var and compare them.
Upper both strings and compare them.
Using single quotes for the text.
I might be wrong but I think I hit a bug here :(
PHP Version 5.6.1 - Win

__METHOD__ returns the current class method name. In your case this is my_class::private_function.
If you want to know the caller method, the cleanest way is to pass it as argument.
class my_class {
public function my_method($arg1) {
$this->private_function($arg1, __METHOD__);
}
private function private_function($arg2, $caller) {
if ($caller == "my_class::my_method") {
} else {
}
return;
}
}

You should try the __FUNCTION__
I guess __METHOD__ will return class name along with the function name.

Related

php call static function of class dynamically(function name is unknown)

Here is my Class:
class ProcessUploadedExcel {
public static function test1($a,$b)
{
dd('hi');
}
public static function test2($a,$b)
{
dd('hi');
}
}
in another file I want to call one of the functions. So I included the file:
use App\Library\ProcessUploadedExcel;
the function is stored in a variable and when I use call_user_func_array I get an error:
ProcessUploadedExcel::test1(1,2);//works fine.
$func_name = 'test1';
call_user_func_array("ProcessUploadedExcel::" . $func_name, [1,2]);//gets error
error:
call_user_func_array() expects parameter 1 to be a valid callback,
class 'ProcessUploadedExcel' not found
You can do this:
class ProcessUploadedExcel {
public static function test1($a,$b)
{
//dd('hi');
var_dump($a,$b);
}
public static function test2($a,$b)
{
dd('hi');
}
}
$func_name = 'test1';
ProcessUploadedExcel::$func_name(1,2);
Output:
int(1) int(2)
or if you want to use call_user_func_array()
call_user_func_array([ProcessUploadedExcel::class,$func_name],[1,2]);
Both solutions work properly with use and namespaces.
call_user_func_array ignores the use and you have to provide the full path:
$func_name = 'test1';
call_user_func_array("App\Library\ProcessUploadedExcel::" . $func_name, [1,2]);
You can try this way:
class ProcessUploadedExcel {
public static function test1($a,$b)
{
echo ('hi');
}
public static function test2($a,$b)
{
echo ('hi');
}
}
$func_name = 'test1';
call_user_func_array([ ProcessUploadedExcel::class, $func_name ] , [1,2]);
First misconception is that you "included the file: use App\Library\ProcessUploadedExcel;". No, you just told PHP that whenever it encounters ProcessUploadedExcel, you actually mean App\Library\ProcessUploadedExcel. This doesn't include anything. Including something is a different mechanism using require or require_once. Actually including the file is done by the autoloader in most projects.
Now, you pass a string to call_user_func_array(). PHP doesn't look inside that string, so it can't tell that you mean something different than what you write there. Inside the called function, where the string is used, the above use ... is not effective, so the function fails since it can't find the according callback.
Remedies:
You could provide the fully qualified name "App\\Library\\ProcessUploadedExcel::test1" as parameter.
You could make PHP look up the fully qualified name for you using ProcessUploadedExcel::class . "::test1".
I'm not sure that either of these works though, but check the documentation which way to specify a callback exist. Maybe you need to specify class and function separately like [ProcessUploadedExcel::class, "test1"].

Make a variable behave like a function

I'm making a PHP script which works with polynomials and monomials (an example of monomial is 42xk^2c^3d). The Monomial class is defined as follows:
class Monomial {
public $coefficient; // i.e. 42
public $letters; // an array of Letter objects
public $literal; // i.e. xk^2c^3d
/* Code */
}
Now, in my applications I use both the array of letters and the literal variable. I don't want to update "by hand" the literal variable whenever I update the monomial (e.g. when adding something to it): instead, I want it to be dynamical, so that accessing it calls a function to "build" it. Any ideas?
Write a function setLetters (or even updateMonomial) which updates both your variables and use that instead of accessing the variable directly. It's generally a good idea to not expose class members.
Use the __get method. An example:
class Monomial {
public $coefficient;
public $letters;
public $literal;
function __get($var) {
if ($var != "literal") {
return $this->data[$var];
} else {
foreach ($this->letters as $letter) {
$return.=$letter->literal;
}
return $return;
}
}
There would be a similar __get method in the Letter object which would generate the literal string on request.

How to Pass a function to a class in php

I have a class that generates data based on a few things. I would like to format that data from the outside. So I am trying to pass a function into the class so that it would format that data. I have looked at many examples, but it seems this is unique.
Can anybody give an idea of how to do this? The following code gives an error.
<?php
class someClass {
var $outsideFunc; // placeholder for function to be defined from outside
var $somevar='Me'; // generated text
function echoarg($abc){
$outsideFunc=$this->outsideFunc; // bring the outside function in
call_user_func($outsideFunc,$abc); // execute outside function on text
echo $abc;
}
}
function outsidefunc($param){ // define custom function
$param='I am '.$param;
}
$someClass=new someClass();
$someClass -> outsideFunc = 'outsideFunc'; // send custom function into Class
$someClass -> echoarg($someClass->somevar);
$someClass -> outsidefunc = 'outsidefunc';
In PHP, function names are not case sensitive, yet object property names are. You need $someClass->outsideFunc, not $someClass->outsidefunc.
Note that good OOP design practice calls for the use of getter and setter methods rather than just accessing properties directly from outside code. Also note that PHP 5.3 introduced support for anonymous functions.
Yeah. You are right. Now there is no error. But it does not work either.
By default, PHP does not pass arguments by reference; outsidefunc() does not actually do anything useful. If you want it to set $param in the caller to something else, and do not want to just return the new value, you could change the function signature to look like this:
function outsidefunc(&$param) {
You would also need to change the way you call the function, as call_user_func() does not allow you to pass arguments by reference. Either of these ways should work:
$outsideFunc($abc);
call_user_func_array($outsideFunc, array(&$abc));
Why not pass your function as an argument?
<?php
class someClass {
public $somevar="Me";
public function echoarg($abc,$cb=null) {
if( $cb) $cb($abc);
echo $abc;
}
}
$someClass = new someClass();
$someClass->echoarg($someClass->somevar,function(&$a) {$a = "I am ".$a;});
i am not sure what exactly you are looking for, but what i get is, you want to pass object in a function which can be acheive by
Type Hinting in PHP.
class MyClass {
public $var = 'Hello World';
}
function myFunction(MyClass $foo) {
echo $foo->var;
}
$myclass = new MyClass;
myFunction($myclass);
OP, perhaps closures are what you're looking for?
It doesn't do EXACTLY what you're looking for (actually add function to class), but can be added to a class variable and executed like any normal anonymous function.
$myClass->addFunc(function($arg) { return 'test: ' . $arg });
$myClass->execFunc(0);
class myClass {
protected $funcs;
public function addFunc(closure $func) {
$this->funcs[] = $func;
}
public function execFunc($index) { $this->funcs[$index](); } // obviously, do some checking here first.
}

Fatal error: Can't use method return value in write context in <filename> on line <ifconditioin statement>

I get the error for the following code
class Myclass {
//...variables
public function getName() {
return $this->strName;
}
public function checkDup() {
if(empty($this->getName())) { //HERE IS THE ERROR
$strMessage = 'Please Enter First Name';
return $strMessage;
}
}
}
$a = new Myclass (); //assume constructor is present and variables are set in class
$a->checkDup();
What could be the solution?
My getName() function returns the name of the variable
I figured out what was going wrong here.
I should be referring to the class member variable using $this and not call the getName() function again inside the class. This changes the function to :
public function checkDup() {
if(empty($this->strName)) { //HERE IS THE SOLUTION
$strMessage = 'Please Enter First Name';
return $strMessage;
}
}
change:
if(empty($this->getName())) {
to
$name = $this->getName();
if( empty($name) ) {
...
empty() only checks variables as anything else will result in a parse error
the empty construct is a bit silly that way. see the manual:
Note:
Prior to PHP 5.5, empty() only supports variables; anything else will
result in a parse error. In other words, the following will not work:
empty(trim($name)). Instead, use trim($name) == false.
I don't like any of the answers here. Yes you can reference $this->strName directly. But what if you can't? What if getName() has some important functionality?
Then the only option is to create another variable? $var = $this->getName();.
That also sucks.
Generically whenever I access a class property or function dynamically I enclose it in braces {} so:
I'll know it's dynamic.
I'll get meaningful errors if there are any.
Examples:
$this->{$variable};
$this->{$class->property};
$this->{$class->method()};
$this->{function()};
$this->{$array['index']};

Assigning a function's result to a variable within a PHP class? OOP Weirdness

I know you can assign a function's return value to a variable and use it, like this:
function standardModel()
{
return "Higgs Boson";
}
$nextBigThing = standardModel();
echo $nextBigThing;
So someone please tell me why the following doesn't work? Or is it just not implemented yet? Am I missing something?
class standardModel
{
private function nextBigThing()
{
return "Higgs Boson";
}
public $nextBigThing = $this->nextBigThing();
}
$standardModel = new standardModel;
echo $standardModel->nextBigThing; // get var, not the function directly
I know I could do this:
class standardModel
{
// Public instead of private
public function nextBigThing()
{
return "Higgs Boson";
}
}
$standardModel = new standardModel;
echo $standardModel->nextBigThing(); // Call to the function itself
But in my project's case, all of the information stored in the class are predefined public vars, except one of them, which needs to compute the value at runtime.
I want it consistent so I nor any other developer using this project has to remember that one value has to be function call rather then a var call.
But don't worry about my project, I'm mainly just wondering why the inconsistency within PHP's interpreter?
Obviously, the examples are made up to simplify things. Please don't question "why" I need to put said function in the class. I don't need a lesson on proper OOP and this is just a proof of concept. Thanks!
public $nextBigThing = $this->nextBigThing();
You can only initialize class members with constant values. I.e. you can't use functions or any sort of expression at this point. Furthermore, the class isn't even fully loaded at this point, so even if it was allowed you probably couldn't call its own functions on itself while it's still being constructed.
Do this:
class standardModel {
public $nextBigThing = null;
public function __construct() {
$this->nextBigThing = $this->nextBigThing();
}
private function nextBigThing() {
return "Higgs Boson";
}
}
You can't assign default values to properties like that unless that value is of a constant data type (such as string, int...etc). Anything that essentially processes code (such as a function, even $_SESSION values) can't be assigned as a default value to a property. What you can do though is assign the property whatever value you want inside of a constructor.
class test {
private $test_priv_prop;
public function __construct(){
$this->test_priv_prop = $this->test_method();
}
public function test_method(){
return "some value";
}
}
class standardModel
{
// Public instead of private
public function nextBigThing()
{
return "Higgs Boson";
}
}
$standardModel = new standardModel(); // corection
echo $standardModel->nextBigThing();

Categories