How to get the namespace where a function is called? - php

Is there a way to make this to work?
<?php
namespace Bar {
class test {
public function test($action) {
call_user_func($action); // must call \Foo\Action
}
}
}
namespace Foo {
$test = new \Bar\Test;
function action () {
echo 'it works!';
}
$test->test('action');
}
For a more detailed description: If I have a function that call user defined functions with de call_user_func, and uses that function in a Foo namespace to call a Foo namespaced function, how can I know that this passed function is on Foo namespace?

If you pass a function around by name in a string, you always need to use the fully qualified name including namespace. 'action' refers to the function \action. Even within the same namespace this won't work correctly. You need to use 'Foo\action' under all circumstances.
If you don't like hardcoding the namespace name, use __NAMESPACE__ . '\\action'.

You could use the constant __NAMESPACE__ and pass it as argument, e.g.
$test->test("\\" . __NAMESPACE__ . '\\action');

Related

PHP Dynamically determine fully qualified class name

I've found that by using ::class, I can get the fully qualified class name of a namespaced class:
namespace NameSpace {
class Foo { }
echo Foo::class;
}
// echoes 'NameSpace\Foo'
But I can't figure out a way to do this with a variable class name. Trying to treat the class keyword like a static property doesn't seem to work:
namespace NameSpace {
class Foo { }
$className = 'Foo';
echo $className::class;
}
// Parse error: syntax error, unexpected 'class'
Does anyone know if its possible to get the fully qualified class name dynamically like I'm trying to?
I want to be able to do this with classes from outside the current namespace:
namespace ReallyLongHardToWriteNameSpace {
class Foo { }
}
namespace NameSpace {
use ReallyLongHardToWriteNameSpace\Foo;
class Bar { }
echo Foo::class; // echoes 'ReallyLongHardToWriteNameSpace\Foo'
echo Bar::class; // echoes 'NameSpace\Bar'
foreach (['Foo', 'Bar'] as $className) {
echo $className::class; // Parse error: syntax error, unexpected 'class'
}
}
You can use get_class with an instance of that class:
<?php
namespace NS {
class Foo { }
$className = "\\NS\\Foo";
echo get_class(new $className);
}
// prints NS\Foo
Do note that to create an instance of the class I had to use the FQN in the string, so it might not be useful at all.
Ok, I came up with another solution. Even tho this is somewhat different.
namespace NameSpace;
class Foo {
public static function getFullName() {
return __CLASS__;
}
}
print Foo::getFullName(); // Prints NameSpace\Foo
Just create a abstract class which has getFullName() as method and inherit from it on all classes you want to be able to return full name.
Simplest approch (I almost forgot) is the use of get_class()
$className = get_class($yourClassObject); // returns NameSpace\Foo
You can also try using eval() for this.
$className = 'NameSpace\Foo::class';
eval('$fullName = ' . $className);
print $fullName; // returns NameSpace\Foo
Even tho, this might not be exactly what you want, but you should look at the Reflection library. Its very handy to use for such things.
// Lets say you have an object of your class
$object = new ReflectionObject($yourObject);
$name = $object->getName(); // will return NameSpace\Foo
// You can also give the class name to it
$class = new ReflectionClass('Foo');
$name = $class->getName(); // also returns NameSpace\Foo
Look here for more information
There are also classes for methods, properties, etc.
You can use __NAMESPACE__ to get the current namespace, then just prepend that to the string that contains the class name.
namespace NS {
class Foo {
}
$className = 'Foo';
echo __NAMESPACE__ . '\\' . $className;
}

Laravel 5.1 - How to use Model in Global function file

I created a common.php for my all the global function. When I run my first function {{Common::test()}}
It's working fine But I can not use model in it.
namespace App\library;
{
class Common {
public static function test()
{
echo "Yes";
return "This comes from Common File";
}
public static function getCmsBlocks()
{
$model = Modelname::all();
if($model){
echo "asdad";
}else
{
echo "sadasd";
}
}
}
}
I don't get my output when I run {{Common::getCmsBlocks()}}
If your model is in different namespace than App\library you will need to prefix the model class name with its namespace, otherwise PHP will try to load App\library\Modelname which might not be what you need.
Replace
$model = Modelname::all();
with
$model = \Your\Model\Namespace\Modelname::all();
If you use your Modelname class in multiple place in declared namespace, you can import/alias that using use statement so that you can refer to that class by classname in your code:
namespace App\library;
use Your\Model\Namespace\Modelname;
{
class Common {
public static function getCmsBlocks()
{
$model = Modelname::all(); //this will work now
}
}
}
There is no way to define global use to bused by all namespaces in your file, as use always refers to the namespace being declared.
As above the answer is perfect but just a few addition if you don't want to include namespace everytime on at start of each file
Use this :
\App\ModelName::all();
\App\ModelName1::update(item);
\App\ModelName2::find(1);
give path like above and there will be no need to use namespace everytime .
Note: above is path to model which is inside App directory . So change accordingly if you are keeping them at separate place .

Accessing class method without calling the class into a variable php

Is it possible to use a classes methods without actually calling the class into a variable. I am sure i have seen this somewhere but i'm not sure if i was dreaming.
Take this example:
<?php
namespace proj;
class beer{
public function whichIsBest(){
return 'Not cheap stuff';
}
}
Include the file start the class but then how can i get to the whishIsBest method without calling the class into a variable first.
<?php
include 'beerClass.php';
new \proj\beer();
echo \proj\beer()->whichIsBest
Or is this just not possible and I was actually dreaming?
http://www.php.net/manual/en/language.oop5.static.php
class beer {
public static function whichIsBest() {
do //
}
}
..
echo beer::whichIsBest();

Get PHP class namespace dynamically

How can I retrieve a class namespace automatically?
The magic var __NAMESPACE__ is unreliable since in subclasses it's not correctly defined.
Example:
class Foo\bar\A -> __NAMESPACE__ === Foo\bar
class Ping\pong\B extends Foo\bar\A -> __NAMESPACE__ === Foo\bar (it should be Ping\pong)
ps: I noticed the same wrong behavior using __CLASS__, but I solved using get_called_class()... is there something like get_called_class_namespace()? How can I implement such function?
UPDATE:
I think the solution is in my own question, since I realized get_called_class() returns the fully qualified class name and thus I can extract the namespace from it :D
...Anyway if there is a more effective approach let me know ;)
The namespace of class Foo\Bar\A is Foo\Bar, so the __NAMESPACE__ is working very well. What you are looking for is probably namespaced classname that you could easily get by joining echo __NAMESPACE__ . '\\' . __CLASS__;.
Consider next example:
namespace Foo\Bar\FooBar;
use Ping\Pong\HongKong;
class A extends HongKong\B {
function __construct() {
echo __NAMESPACE__;
}
}
new A;
Will print out Foo\Bar\FooBar which is very correct...
And even if you then do
namespace Ping\Pong\HongKong;
use Foo\Bar\FooBar;
class B extends FooBar\A {
function __construct() {
new A;
}
}
it will echo Foo\Bar\FooBar, which again is very correct...
EDIT: If you need to get the namespace of the nested class within the main that is nesting it, simply use:
namespace Ping\Pong\HongKong;
use Foo\Bar\FooBar;
class B extends FooBar\A {
function __construct() {
$a = new A;
echo $a_ns = substr(get_class($a), 0, strrpos(get_class($a), '\\'));
}
}
In PHP 5.5, ::class is available which makes things 10X easier. E.g.
A::class
Use Reflection class.
$class_name = get_class($this);
$reflection_class = new \ReflectionClass($class_name);
$namespace = $reflection_class->getNamespaceName();

Cannot find Class with PHP Namespace

I posted some questions previously regarding the use of Namespaces in PHP and from what I got, this example code I have below should be working.
However I am getting errors when I try to use Namespace in PHP like this. Here is the first error when running the code below as is...
Fatal error: Class 'Controller' not found in E:\Controllers\testing.php on line 6
E:\Controller\testing.php File
<?php
use \Controller;
include('testcontroller.php');
$controller = new Controller;
$controller->show();
?>
E:\Controller\testcontroller.php File
<?php
use \Library\Registry;
namespace Controller
{
class Controller
{
public $registry;
function __construct()
{
include('E:\Library\Registry.class.php');
$this->registry = new Registry;
}
function show()
{
echo $this->registry;
echo '<br>Registry was ran inside testcontroller.php<br>';
}
}
}
?>
E:\Library\Registry.class.php File
<?php
namespace Library\Registry
{
class Registry
{
function __construct()
{
return 'Registry.class.php Constructor was ran';
}
}
}
?>
As you can see I tried to make it as simple as possible just to get the Namespace part working. I have tried different variations and cannot seem to figure it out.
Even when using use statement, you need to specify the namespace of the class you are trying to instantiate. There are a lot of examples here: http://www.php.net/manual/en/language.namespaces.importing.php
To understand it better, I will describe to you how it works. In your case, when you do use \Controller, the whole Controller namespace becomes available to you, but not the classes that are in this namespace. So, for example:
<?php
include('testcontroller.php');
use \Controller;
// Desired class is in namespace!
$controller = new Controller\Controller();
// Error, because in current scope there is no such class
$controller = new Controller();
$controller->show();
?>
Another example:
testcontoller.php:
<?php
namespace Some\Path\To\Controller;
class Controller
{
function __construct()
{
}
function show()
{
echo '<br>Was run inside testcontroller.php<br>';
}
}
?>
testing.php:
<?php
include('testcontroller.php');
use \Some\Path\To\Controller;
// We now can access Controller using only Controller namespace,
// not Some\Path\To\Controller
$controller = new Controller\Controller();
// Error, because, again, in current scope there is no such class
$controller = new Controller();
$controller->show();
?>
If you wish to import exactly the Controller class, you need to do use Controller\Controller - then this class will be accessible in your current scope.
Its not that good idea to name the namespace, like the class, because it is confusing (and I think this is what happens here). There moment you define the alias via use Controller this referenes to either a class \Controller, or the namespace \Controller, but your class, because it is within the namespace, is named \Controller\Controller 1
use Controller;
$class = new Controller\Controller;
or
$class = new \Controller\Controller;
or
use Controller\Controller;
$class = new Controller;
The idea is, that the moment you try to access a class with its relative name it tries to map the "first part" against any alias defined using use (remeber use MyClass is the same as use MyClass as MyClass. The thing after as is the alias).
namespace MyNamespace\MyPackage\SomeComponent\And\So\On {
class MyClass {}
}
namespace Another {
use MyNamespace\MyPackage\SomeComponent; // as SomeComponent
$class = new SomeComponent\An\So\On\MyClass;
}
As you can see PHP finds SomeComponent as the first part and maps it against the SomeComponent-alias the line above.
You can read more about it in the manual about namespaces.
1 Its called "Full-qualified classname", if you name a class with its complete name.
When you put a class Controller in the namespace Controller, then you have to reference it that way:
$controller = new Controller\Controller();
\Controller would be a class in the global (default) namespace, i.e. as if you used no namespace at all.
Strangely I have found that in my example code from the Question above, if I change all the Namespace's that are defined to something like MyLibrary so it would be like this code below...
E:\Library\Registry.class.php File
<?php
namespace MyLibrary
{
class Registry
{
function __construct()
{
echo 'Registry.class.php Constructor was ran';
}
}
}
?>
Then when I use use MyLibrary\Registry; in another file, I am able to access it how I had planned...
$this->registry = new Registry;
The reason this is very strange to me is this now makes a class name appear to be a Namespace as well. So I would not need to set a Namespace to 'MyLibrary\Library' to access the Registry instead I would do it like I showed in this answer to be able to access it with just calling the name of the class.
I hope this makes sense and helps someone else. I will not accept this as the answer as I am hoping someone with more know-how will come in and post a better Answer with explanation
try
<?php
use \Library\Registry;
namespace Controller;
class Controller
{
public $registry;
function __construct()
{
include('E:\Library\Registry.class.php');
$this->registry = new Registry;
}
function show()
{
echo $this->registry;
echo '<br>Registry was ran inside testcontroller.php<br>';
}
}
?>
and
<?php
namespace Library\Registry;
class Registry
{
function __construct()
{
return 'Registry.class.php Constructor was ran';
}
}
?>
First off, I believe you are using composer or composer is initialised in your project. If so, check composer.json file for your autoload, psr-4 definition. For example, if the root of your application is "App", then in your psr-4, you should be doing "autoload": { "psr-4": { "App\\": "./" } },
Furthermore, remember to clear composer cache and dump-autoload from the terminal as follows:
composer clear-cache
composer dump-autoload

Categories