Is there a way to get fully qualified interface name similar to MyClass::class?
For example:
namespace Example\Tests;
use Example\Interfaces\InputInterface;
...
class CommandTest ...
...
public function createInputMock()
{
// I want to replace next string with something similar to MyClass::class
$this->getMockBuilder('Example\Interfaces\InputInterface')
...
Thank you.
The ::class name resolution can work with any imported namespaces: classes, interfaces, functions, ...
namespace A\B\C {
interface Interface_Bar {}
function Function_Foo() {}
function Function_Foo_Bar() {}
const Const_BARFOO = 123;
}
namespace {
use A\B\C\Interface_Bar;
use A\B\C;
use Undefined\Classes\UndefinedClass;
use function A\B\C\Function_Foo_Bar;
use const A\B\C\Const_BARFOO;
echo Interface_Bar::class, "\n"; // print A\B\C\Interface_Bar
echo C\Function_Foo::class, "\n"; // print A\B\C\Function_Foo
echo C\Const_BARFOO::class, "\n"; // print A\B\C\Const_BARFOO
echo UndefinedClass::class, "\n"; // print Undefined\Classes\UndefinedClass
echo Function_Foo_Bar::class, "\n"; // print Function_Foo_Bar <- warning
echo Const_BARFOO::class, "\n"; // print Const_BARFOO <- warning
}
If I got you right, you can't move to PHP 5.5 with ::class notation, so you want to have something similar in your 5.4 or earlier vesrion.
So the short answer is — no, there is no way.
The lack of this functionality in the previous versions of PHP is what made core developers to add ::class to PHP 5.5.
You can make a weird dirty hack if it's a class name: using get_class on new instance, but don't do it.
Related
example
namespace Foo;
use Test\One;
use Test\Two;
use Test\Three;
class Sample
{}
How can I get the aliases (USE) as an array?
example of what I am looking to get
$test = [Test\One, Test\Two, Test\Tree];
Does anybody have any suggestions without scanning the file?
or is there a PHP function that will return the list aliases as an array?
Any help will be very appreciated.
Assuming I have the following class and the file is located and named as following file name and location src/Foo.php
namespace Foo;
use Test\One;
use Test\Two;
use Test\Three;
class Sample
{}
now I can scan this file
with this function, I can scan that class and get the result expected.
<?php
use \SplFileObject;
class Scanner
{
public static function getUseAliases()
{
$className = new SplFileObject("src/Foo.php");
$use = [];
while (!$className->eof())
{
$alias = explode("use ", $className->fgets());
if(!empty($alias[1]))
{
$use[] = trim($alias[1]);
}
}
$className = null; //Unset the file to prevent memory leaks
print_r($use);//will print my expected output [Test\One, Test\Two, Test\Three]
}
}
I think there should be a better way to get the same results and this is why I posted my current solution. Please let me know your thoughts.
You can try to use this class:
https://gist.github.com/Zeronights/7b7d90fcf8d4daf9db0c
<?php
namespace Vendor\Package;
$test1 = new Foo\Bar(); // works as usual
$test2 = 'Foo\Bar';
$test2 = new $test2(); // does not work
$test3 = 'Vendor\Package\Foo\Bar';
$test3 = new $test3(); // but this works
I was looking to use $test2 but it doesn't work even though it looks like it should as it's pretty much the same as $test3 which worked.
Is this expected or is there some syntax I need to use for test2 to work?
When you use a dynamic class name, it has to be fully qualified. The documentation says:
One must use the fully qualified name (class name with namespace prefix). Note that because there is no difference between a qualified and a fully qualified Name inside a dynamic class name, function name, or constant name, the leading backslash is not necessary.
Foo\Bar is not fully qualified, it's relative to Vendor\Package that you selected with the earlier namespace statement.
You can prefix your strign with __NAMESPACE__
Vendor\Package\Foo\Bar::__construct
Vendor\Package\Foo\Bar::__construct
Vendor\Package\Foo\Bar::__construct
Repl.it : https://repl.it/repls/BuzzingFairSuperuser
namespace Vendor\Package\Foo;
class Bar
{
function __construct()
{
echo __METHOD__,"\n";
}
}
namespace Vendor\Package;
$test1 = new Foo\Bar(); // works
$test2 = __NAMESPACE__.'\Foo\Bar';
$test2 = new $test2(); // works
$test3 = 'Vendor\Package\Foo\Bar';
$test3 = new $test3(); // works
So I'll see if I can explain this simply. In your first instance "$test1 = new Foo\Bar();", the path to the model is mapped during compile/load time. In the case where "$test2 = 'Foo\Bar'; $test2 = new $test2();", you're trying to call this model during runtime... Unfortunately, at runtime, the linking has already been done, and is not revisited. What this means it that "$test2 = '\Vendor\Package\Foo\Bar'" should work, but a shortened version of the name can't work, as the linking step is not revisited during runtime.
I'm trying to use class_alias on a facade \Facades\Security.
I tried this:
class_alias("\\Facades\\Security", "Security");
echo Security::Unique();
But i got an error (Class 'Security' not found in...).
The weird thing is that when i try this:
$facade = "Security";
class_alias("\\Facades\\" . $facade, $facade);
echo $facade::Unique();
It does work and i get an output from the function 'Unique'.
So somehow storing the name of the facade in a variable and accessing it from there, fixes the problem...
Can someone tell me why?
Thanks :)
Suppose you are using namespace of class name.., so no need escape (\), try this code
class_alias("\Facades\Security", "Security");
echo Security::Unique();
Update
You will also need to add namespace in alias class B, see sample code
<?php
namespace Facades;
class Security {
public static function Unique(){
return "Test return";
}
}
class_alias("\Facades\Security", "\Facades\B");
echo B::Unique();
?>
DEMO
Here is an example of the CFML code I am using as a baseline (also on github # getFunctionCalledName.cfm):
function f(){
echo("#getFunctionCalledName()#() called<br>");
}
f();
echo("<hr>");
g = f;
g();
This outputs:
F() called
G() called
Note that getFunctionCalledName() returns the name of the reference used to call the function, not simply the name of the function.
I'm trying to see if there's an equivalent in PHP. Here's my test of that (testFunction.php on GitHub):
I know there's the __FUNCTION__ magic constant:
function f()
{
echo sprintf("Using __FUNCTION__: %s() called<br>", __FUNCTION__);
}
f();
echo "<hr>";
$g = "f"; // as someone points out below, this is perhaps not analogous to the g = f in the CFML code above. I dunno how to simply make a new reference to a function (other than via using function expressions instead, which is not the same situation
$g();
However this returns f in both cases.
I've written similar code trying debug_backtrace() (see testDebugBackTrace.php), but that also references the function as f.
This is fine, and I understand why they both do that. However I'm wondering if there's any PHP equivalent of getFunctionCalledName(). I hasten to add this is just for an exploratory exercise: I am currently migrating myself from CFML to PHP and this just came up when I was demonstrating something on my blog.
Your code $g = "f"; isn't really copying the function to another variable, it's just creating a string reference to the same function. The following would be more analogous to the CFML you provide:
$x = function() {
echo __FUNCTION__;
};
$v = $x;
$v();
The above code just outputs {closure}, since PHP doesn't assign a formal name to anonymous functions. So, the answer is, no, it isn't possible in PHP.
I don't think what you're after is possible in PHP without something like the runkit extension. That has the functionality to create a copy of a function under a new name. I haven't tried this out myself as I couldn't find a Windows version of the extension.
http://php.net/manual/en/function.runkit-function-copy.php
<?php
function f() {
echo sprintf("Using __FUNCTION__: %s() called<br>", __FUNCTION__);
}
runkit_function_copy('f', 'g');
f();
g();
?>
In Drupal, there are many functions that are hook_functionname1, hook_functionname2. When writing a module, you have to replace the text 'hook' with your module name, so Drupal loads your module "my_drupal_module" and runs hooks like "my_drupal_module_functionname1" and "my_drupal_module_functionname2".
Is it possible in PHP to use DEFINE to simply define the word "hook" and set it to a string? If it is possible, then you should be able to copy and paste word-for-word hook_anything and not have to change it. And, if you ever wanted to change the name of your module, you would merely change the single constant, rather than find/replace all the function names.
So can you use DEFINE or some other setting to meta-program in PHP?
You want something like:
$moduleFunctionName = 'hook';
$functionNameOne = $moduleFunctionName . '_functionname1';
$functionNameTwo = $moduleFunctionName . '_functionname2';
$functionNameOne = function($var) {
// blah
}
..//
Function $functionNameOne is defined through anonymous function. It becames available in php from php 5.3.0
Maybe you want something like this
<?
define('PREFIX', 'myprefix');
//like this time you deside that this will me the second part
$somevar = '_this_function_name';
// now we combine prefix and name
$function_name = PREFIX . $somevar;
// now we check if we can run this function
if(!function_exists($function_name)){
echo "no function $funcion_name exist";
}
else{
$function_name();
}
function myprefix_this_function_name(){
echo 'running function';
}
?>
this will output
running function
This actually works:
define('FN_NAMESPACE', 'hook_');
${FN_NAMESPACE . 'functionNameOne'} = function($var) {
echo "Hi, I got $var\n";
};
$hook_functionNameOne('test');
Will output
Hi, I got test