I have code - working correct (I do not have to inculde class ReflectionClass):
class Test
{
const TYPE_ONE = "Number one";
const TYPE_TWO = "Number two";
static function getConstants() {
$oClass = new ReflectionClass(__CLASS__);
return $oClass->getConstants();
}
}
foreach (Test::getConstants() as $kay => $val):
echo "$kay -- $val <br/>";
endforeach;
But, when i try use ReflectionClass in code Yii2 i gets the message
PHP Fatal Error – yii\base\ErrorException
Class 'common\models\ReflectionClass' not found
If there are any Reflection classes in the framework or a way to declare ReflectionClass in Yii2
Because yii2 use namespaces, when you call new ReflectionClass() php looking for this class in the namespace that you declare at the beginnig of a file, in your case its namespace common\models; To load php's classes you need to prepend their names with \. So to instantiate ReflectionClass you need to write new \ReflectionClass(__CLASS__). More in documentation
Related
I am new to PHP. I am just trying to understand PHP namespace and stuck at following point of changing the class name, I am referring this article titled How to use PHP namespace. And was referring following code on that page.
<?php
namespace App\Lib1;
class MyClass {
public function WhoAmI() {
return __METHOD__;
}
}
$c = __NAMESPACE__ . '\\MyClass';
$m = new $c;
echo $m->WhoAmI(); // outputs: App\Lib1\MyClass::WhoAmI
?>
In the above code, I guess, they have created Object like,
$c = __NAMESPACE__ . '\\MyClass';
$m = new $c;
I guess object can be created simple in above case as,
$m = new MyClass();
And on the same page, in other code the object has been created using code,
$m = new namespace\MyClass;
Now, if I compare all three above, I am finding two method of creating class name 1. $m = new MyClass(); and 2. $m = namespace\MyClass;. I am wondering what is the difference and purpose of using $m = namespace\MyClass;? Very thank in Advance.
The biggest advantage of using namespaces in PHP is for when you have multiple classes with the same name. Without namespacing, a developer would need to worry that by creating a class MyClass, there are thousands of other third-party libraries that could also have a MyClass.
Let's say you wanted to create a class called DateTime. If you just wrote the function without a namespace, it would conflict with PHP's DateTime class. By declaring a namespace, you segragate your code.
<?php
$myObject = DateTime(); // This statement creates an object using PHP's implementation of DateTime
namespace Foo\DateTime;
use Foo\DateTime as DateTime;
$myObject = DateTime(); // This statement will use the custom class from the Foo\DateTime namespace
$myObject = PHP\DateTime(); // This statement will use PHP's class even though you're using the Foo\DateTime namespace
?>
The second advantage is for code conciseness. If you use the Foo\DateTime namespace shown above, you don't have to use the fully qualified name when you create custom objects from your class. This is useful when you have to create a large number of instances of your custom class.
When you use the namespace like so, you can write it as an alias instead of a fully qualified name:
use Foo\DateTime as DateTime;
$myObject = new DateTime();
Without using namespaces, you would need to create the object like so, if you wanted to use your DateTime class instead of PHP's DateTime class:
$myObject = Foo\DateTime();
I suppose there are no any essential differences between:
$m = new MyClass(); and $m = new namespace\MyClass;
It can help you to explicitly indicate which one of two classes with the same name you use:
<?php
namespace Foo;
class MyClass {
public function WhoAmI() {
return __METHOD__;
}
}
?>
<?php
namespace Bar;
class MyClass {
public function WhoAmI() {
return __METHOD__;
}
}
?>
<?php
namespace Bar;
use Foo;
$obj1 = new MyClass;
var_dump($obj1->WhoAmI()); //Bar\MyClass::WhoAmI
$obj2 = new namespace\MyClass;
var_dump($obj2->WhoAmI()); //Bar\MyClass::WhoAmI
$obj3 = new Foo\MyClass;
var_dump($obj3->WhoAmI()); //Foo\MyClass::WhoAmI
I think it is better to use aliasing in this case.
I used to have several library classes with the exact same methods. Figured I'd learn a bit more about two important aspects of coding; Traits and DRY.
I have the following trait:
<?php
namespace App\Berry;
trait Lib
{
public function getIDs()
{
$oClass = new \ReflectionClass(get_called_class());
$aConstants = $oClass->getConstants();
foreach($aConstants as $sKey => $mValue)
{
if(!is_int($mValue))
{
unset($aConstants[$sKey]);
}
}
return array_values($aConstants);
}
}
The following class:
namespace App\Berry;
use Lib;
class postType
{
const POST_TYPE_BLOG_ID = 1;
const POST_TYPE_BLOG_LABEL = __('blog', 'lib');
const POST_TYPE_PAGE_ID = 2;
const POST_TYPE_PAGE_LABEL = __('page', 'lib');
const POST_TYPE_NEWS_ID = 3;
const POST_TYPE_NEWS_LABEL = __('news', 'lib');
}
And am calling it like this in my PicturesController class:
$cPostTypesLibrary = new postType();
$this->set('aPostTypes', $cPostTypesLibrary->getIDs());
Now to me, this seems almost exactly like the tell me to do in the docs example #4 (About using multiple traits)
The only difference I have is I have the use outside of my class due to getting cannot use class because it is not a trait
What am I missing here?
Your class is not using the trait, you are instead using the other use of the use keyword and trying to import the Lib class from the same namespace into, well, the same namespace.
To use traits correctly, go back to the documentation, and look at where they are placed. The use statement is placed inside of the class definition. In your case, it would look like this:
namespace App\Berry;
class postType
{
use Lib;
// ...
}
You have to declare the trait inside the class
class postType
{
use Lib;
}
I have learned that I need to use name space in php like I have used in my following code but I'm getting Fatal error: Trait 'SuperClosure\Serializer' not found
I have used it like this:
use SuperClosure\Serializer;
public function set( $key, $value )
{
$key = strtolower( $key );
$serializer = new Serializer();
$serialized = $serializer->serialize($value);
$_SESSION["HA::STORE"][$key] = $serialized;
}
where I am wrong ? please tell me the correct way to use it?
You need to use namespaces before declaring class because word use point to Trait mechanism (PHP: Traits). Example of namespaces and traits in class:
<?php namespace Foo\Bar;
/* I am telling to PHP compiler that class
* Serializer has different path than class Baz.
*/
use SuperClosure\Serializer;
use SuperClosure\Shortcuts;
class Baz {
/* Now I used Trait. That should include
* methods defined in trait Shortcuts
*/
use Shortcuts;
}
Also I recommend read more about namespaces and importing them.
I'm creating a factory class in my project, where this class gets a Report Type as a string. This string has the name of the concrete class that implements a Report Interface.
The issue I'm having is that when I'm instantiating this class, I get a Class not found error.
Here follows the factory code.
namespace App\Term\Reports;
class Factory
{
public static function build($type)
{
$obj = new CableBySensor(); // Works!
// $type == 'CableBySensor'
$obj2 = new $type; // Class not found :(
// ... validates if the class exists ...
// ... and if it implements the Report Interface ...
// ... throw exception if class doesn't exist or doesn't implements interface
// ... then returns the corresponding object.
}
}
Both methods are virtually the same thing.
First: Why do I have to specify the full qualified name of the class in the string to make it work? The class CableBySensor resides in the same namespace as Factory.
This started giving me trouble because I also want to validate that the class being instantiated implements a ReportsInterface.
Second: How do I overcome this? Should I call the factory like this $myReport = Factory::build('App\Term\Reports\' . $className); or should I use the __NAMESPACE__ constant inside the Factory class such as this: $obj = new __NAMESPACE__ . '\' . $className?
Thank you.
Indifferently whether the factory approach is useful here or not,
the problem is with trying to instantiate from a dynamic variable.
Or as akhoondi at php.net pointed out:
One must note that when using a dynamic class name [...] the "current namespace" [...] is global namespace.
There are possibly 3 solutions:
pass the fully qualified class name to your factory method (arghh...)
$instance = Factory::build('Acme\CableBySensor');
Or, do a check in your build method and prefix the namespace if necessary (as suggested here) (sounds not so fool proof to me)
public static function build($type)
{
if ($type[0] !== '\\') {
$type = '\\' . __NAMESPACE__ . '\\' . $type;
}
$obj = new $type;
...
}
Or, if you have PHP 5.5+ why not use class name resolution via ::class?
Personally, I would go for that one whenever possible:
$instance = Factory::build(CableBySensor::class);
I'm trying to run this code on the same file:
namespace Foo1\Bar\SubBar;
class SubBarClass {
public function __construct() {
echo 'From Foo1';
}
}
namespace Foo2\Bar\SubBar;
class SubBarClass {
public function __construct() {
echo 'From Foo2';
}
}
use Foo1\Bar\SubBar;
$foo1 = new SubBarClass;
use Foo2\Bar\SubBar;
$foo2 = new SubBarClass;
The ideia is to change namespaces and echo the related value.
But it's returning the following error:
( ! ) Fatal error: Cannot use Foo2\Bar\SubBar as SubBar because the name is already in use in C:\wamp\www\xxx\namespaces.php on line 30
Line 30: use Foo2\Bar\SubBar;
How can I interchange namespaces on the same file?
Thks!
use keyword is used to import that namespace to be accessed in your current file scope. It does not act as a namespace "instance constructor".
You're current under Foo2\Bar\SubBar namespace. Like a directory of classes, while you're here, you should access other namespaces from the root (\):
$foo2 = new SubBarClass;
$foo1 = new \Foo1\Bar\SubBar\SubBarClass;
There is no need to use use for those namespaces (although you can, specially when they share parent namespaces), they are already declared in the same file you're using them.
For more information about this, consider reading the manual, where it describes using multiple namespaces in the same file.
This happens because the last defined namespace is the one currently active.
So, when I type:
use Foo1\Bar\SubBar;
I'm still on the last defined namespace: Foo2\Bar\SubBar.
Hence, when I type:
use Foo2\Bar\SubBar;
I'm trying to use the currently active namespace. That's why the Fatal error is returned.
On possible solution is:
namespace Foo1\Bar\SubBar;
class SubBarClass {
public function __construct() {
echo 'From Foo1';
}
}
namespace Foo2\Bar\SubBar;
class SubBarClass {
public function __construct() {
echo 'From Foo2';
}
}
use Foo1\Bar\SubBar;
$foo1 = new SubBar\SubBarClass;
echo '<br>';
$foo2 = new SubBarClass;
Cheers!