I would like to be able to do something like this:
class ThingIDs
{
const Something = 1;
const AnotherThing = 2;
}
$thing = 'Something';
$id = ThingIDs::$thing;
This doesn't work. Is there a straightforward way of doing something equivalent? Note that I'm stuck with the class; it's in a library I can't rewrite. I'm writing code that takes arguments on the command line, and I would really like it to take symbolic names instead of id numbers.
Use the constant() function:
$id = constant("ThingIDs::$thing");
Use Reflection
$r = new ReflectionClass('ThingIDs');
$id = $r->getConstant($thing);
If you are using namespaces, you should include the namespace with the class.
echo constant('My\Application\ThingClass::ThingConstant');
Helper function
You can use a function like this:
function class_constant($class, $constant)
{
if ( ! is_string($class)) {
$class = get_class($class);
}
return constant($class . '::' . $constant);
}
It takes two arguments:
Class name or object instance
Class constant name
If an object instance is passed, its class name is inferred. If you use PHP 7, you can use ::class to pass appropriate class name without having to think about namespaces.
Examples
class MyClass
{
const MY_CONSTANT = 'value';
}
class_constant('MyClass', 'MY_CONSTANT'); # 'value'
class_constant(MyClass::class, 'MY_CONSTANT'); # 'value' (PHP 7 only)
$myInstance = new MyClass;
class_constant($myInstance, 'MY_CONSTANT'); # 'value'
<?php
class Dude {
const TEST = 'howdy';
}
function symbol_to_value($symbol, $class){
$refl = new ReflectionClass($class);
$enum = $refl->getConstants();
return isset($enum[$symbol])?$enum[$symbol]:false;
}
// print 'howdy'
echo symbol_to_value('TEST', 'Dude');
If you have a reference to the class itself then you can do the following:
if (defined(get_class($course). '::COURSES_PER_INSTANCE')) {
// class constant is defined
}
My problem was similiar to this subject. When you have the object, but not the class name, you could use:
$class_name = get_class($class_object);
$class_const = 'My_Constant';
$constant_value = constant($class_name.'::'.$class_const);
I know I'm a bit late, but I hope this can help anyway.
Based on Phil's answer, I created a default enumerator class that can be extended.
class DefaultEnum
{
static public function getConstantText(string $constant)
{
try {
// Get child class name that called this method
$child_class = get_called_class();
$reflection = new ReflectionClass($child_class);
$const = $reflection->getConstant($constant);
return $const;
} catch (\ReflectionException $e) {
// ...
}
}
}
class CustomEnum extends DefaultEnum
{
const something = 'abcd';
const something2 = 'ABCD';
}
You can call this method like this
CustomEnum::getConstantText('something');
It will return 'abcd'.
The function get_called_class() is a function that returns the class name that called this method and it works specifically for static methods.
In this case $child_class value will be CustomEnum::class. ReflectionClass accepts strings and object as parameter.
Related
I would like to be able to do something like this:
class ThingIDs
{
const Something = 1;
const AnotherThing = 2;
}
$thing = 'Something';
$id = ThingIDs::$thing;
This doesn't work. Is there a straightforward way of doing something equivalent? Note that I'm stuck with the class; it's in a library I can't rewrite. I'm writing code that takes arguments on the command line, and I would really like it to take symbolic names instead of id numbers.
Use the constant() function:
$id = constant("ThingIDs::$thing");
Use Reflection
$r = new ReflectionClass('ThingIDs');
$id = $r->getConstant($thing);
If you are using namespaces, you should include the namespace with the class.
echo constant('My\Application\ThingClass::ThingConstant');
Helper function
You can use a function like this:
function class_constant($class, $constant)
{
if ( ! is_string($class)) {
$class = get_class($class);
}
return constant($class . '::' . $constant);
}
It takes two arguments:
Class name or object instance
Class constant name
If an object instance is passed, its class name is inferred. If you use PHP 7, you can use ::class to pass appropriate class name without having to think about namespaces.
Examples
class MyClass
{
const MY_CONSTANT = 'value';
}
class_constant('MyClass', 'MY_CONSTANT'); # 'value'
class_constant(MyClass::class, 'MY_CONSTANT'); # 'value' (PHP 7 only)
$myInstance = new MyClass;
class_constant($myInstance, 'MY_CONSTANT'); # 'value'
<?php
class Dude {
const TEST = 'howdy';
}
function symbol_to_value($symbol, $class){
$refl = new ReflectionClass($class);
$enum = $refl->getConstants();
return isset($enum[$symbol])?$enum[$symbol]:false;
}
// print 'howdy'
echo symbol_to_value('TEST', 'Dude');
If you have a reference to the class itself then you can do the following:
if (defined(get_class($course). '::COURSES_PER_INSTANCE')) {
// class constant is defined
}
My problem was similiar to this subject. When you have the object, but not the class name, you could use:
$class_name = get_class($class_object);
$class_const = 'My_Constant';
$constant_value = constant($class_name.'::'.$class_const);
I know I'm a bit late, but I hope this can help anyway.
Based on Phil's answer, I created a default enumerator class that can be extended.
class DefaultEnum
{
static public function getConstantText(string $constant)
{
try {
// Get child class name that called this method
$child_class = get_called_class();
$reflection = new ReflectionClass($child_class);
$const = $reflection->getConstant($constant);
return $const;
} catch (\ReflectionException $e) {
// ...
}
}
}
class CustomEnum extends DefaultEnum
{
const something = 'abcd';
const something2 = 'ABCD';
}
You can call this method like this
CustomEnum::getConstantText('something');
It will return 'abcd'.
The function get_called_class() is a function that returns the class name that called this method and it works specifically for static methods.
In this case $child_class value will be CustomEnum::class. ReflectionClass accepts strings and object as parameter.
I would like to be able to do something like this:
class ThingIDs
{
const Something = 1;
const AnotherThing = 2;
}
$thing = 'Something';
$id = ThingIDs::$thing;
This doesn't work. Is there a straightforward way of doing something equivalent? Note that I'm stuck with the class; it's in a library I can't rewrite. I'm writing code that takes arguments on the command line, and I would really like it to take symbolic names instead of id numbers.
Use the constant() function:
$id = constant("ThingIDs::$thing");
Use Reflection
$r = new ReflectionClass('ThingIDs');
$id = $r->getConstant($thing);
If you are using namespaces, you should include the namespace with the class.
echo constant('My\Application\ThingClass::ThingConstant');
Helper function
You can use a function like this:
function class_constant($class, $constant)
{
if ( ! is_string($class)) {
$class = get_class($class);
}
return constant($class . '::' . $constant);
}
It takes two arguments:
Class name or object instance
Class constant name
If an object instance is passed, its class name is inferred. If you use PHP 7, you can use ::class to pass appropriate class name without having to think about namespaces.
Examples
class MyClass
{
const MY_CONSTANT = 'value';
}
class_constant('MyClass', 'MY_CONSTANT'); # 'value'
class_constant(MyClass::class, 'MY_CONSTANT'); # 'value' (PHP 7 only)
$myInstance = new MyClass;
class_constant($myInstance, 'MY_CONSTANT'); # 'value'
<?php
class Dude {
const TEST = 'howdy';
}
function symbol_to_value($symbol, $class){
$refl = new ReflectionClass($class);
$enum = $refl->getConstants();
return isset($enum[$symbol])?$enum[$symbol]:false;
}
// print 'howdy'
echo symbol_to_value('TEST', 'Dude');
If you have a reference to the class itself then you can do the following:
if (defined(get_class($course). '::COURSES_PER_INSTANCE')) {
// class constant is defined
}
My problem was similiar to this subject. When you have the object, but not the class name, you could use:
$class_name = get_class($class_object);
$class_const = 'My_Constant';
$constant_value = constant($class_name.'::'.$class_const);
I know I'm a bit late, but I hope this can help anyway.
Based on Phil's answer, I created a default enumerator class that can be extended.
class DefaultEnum
{
static public function getConstantText(string $constant)
{
try {
// Get child class name that called this method
$child_class = get_called_class();
$reflection = new ReflectionClass($child_class);
$const = $reflection->getConstant($constant);
return $const;
} catch (\ReflectionException $e) {
// ...
}
}
}
class CustomEnum extends DefaultEnum
{
const something = 'abcd';
const something2 = 'ABCD';
}
You can call this method like this
CustomEnum::getConstantText('something');
It will return 'abcd'.
The function get_called_class() is a function that returns the class name that called this method and it works specifically for static methods.
In this case $child_class value will be CustomEnum::class. ReflectionClass accepts strings and object as parameter.
I'm trying to do something like this:
function doSomething($param, Class) {
Class::someFunction();
}
$someVar = doSomething($param, Class);
Is it possible?
To explain better what I'm trying to do. I have a helper function in Laravel to generate unique slugs, so I have to query different tables depending on where the slug is going to be saved.
Actual code I'm trying to write:
$newcat->slug = $helper->uniqueSlug($appname, Apk);
public function uniqueSlug($str, Apk)
{
$slug = Str::slug($str);
$count = Apk::whereRaw("slug RLIKE '^{$slug}(-[0-9]+)?$'")->count();
return $count ? "{$slug}-{$count}" : $slug;
}
Thanks!
You can use the magic ::class constant:
public function uniqueSlug($str, $model)
{
$slug = Str::slug($str);
$count = $model::whereRaw("slug RLIKE '^{$slug}(-[0-9]+)?$'")->count();
return $count ? "{$slug}-{$count}" : $slug;
}
$newcat->slug = $helper->uniqueSlug($appname, Apk::class);
In PHP, classes (or class names) are handled as strings. Since PHP 5.5, you can use YourClass::class to get a fully qualified class name.
If you want to get it in an earlier version of php, you can (if you have already an object of the calss) either do the following:
<?php
$obj = new YourClass();
// some code
$clazz = get_class($obj);
?>
or, you can implement a static method in your class, like this:
<?php
class YourClass {
// some code
public static function getClassName() {
return get_called_class();
}
?>
If you want to pass a class to a function, you can do it like this:
<?php
function do_somthing($arg1, $clazz) {
$clazz::someStaticMethod($arg1);
}
?>
or
<?php
function do_somthing($arg1, $clazz) {
call_user_func(array($clazz, 'someStaticMethod')), $arg1);
}
?>
If you need to call a non-static method of that class, you need to instanciate it:
<?php
function do_somthing($arg1, $clazz) {
$obj = new $clazz();
$obj->someNonStaticMethod();
}
?>
Note: You can use PHP type hinting with passed class names:
<?php
function do_somthing($arg1, MyInterface $clazz) {
$obj = new $clazz();
$obj->someInterfaceMethod();
}
?>
I think you can.
Send the class name as string parameter then use it like below.
$classtr = "yourparam";// param comes from the function call.
$obj = new $classtr;
$obj->method();
Send the class name as string parameter you need use the namespace. For example:
function defineClass()
{
$class = "App\MyClass"; // mention the namespace too
}
function reciveClass($class)
{
$class:: // what do you need,
}
I wold like to get the following variable name:
class ClassA
{
public $my_name_is = "";
function __construct($tag,$cont = null)
{
$this->my_name_is = ???;
}
}
$OBJ = new ClassA();
echo($OBJ->my_name_is);
This should output
OBJ
Is it possible?
I make tag HTML generator and the id of the tag should be the object name so I must not write it twice:
$input_pwd = new tag("td>input TYPE=PASSWORD.box_lg#input_pwd"); //old way
$input_pwd = new tag("td>input TYPE=PASSWORD.box_lg"); //upgraded way
should generate:
<td><input TYPE=PASSWORD ID='input_pwd' CLASS='box_lg'></td>
No, it's not. An object doesn't know the names of variables that refer to it.
"Needing" this is usually a design flaw.
You can use the magic constant __CLASS__ for retrieving the name of the current class, but there is no way for a class to get the name of the variable which stores the class. You may want to extend your class and still use __CLASS__:
class OBJ extends ClassA {
public function getName() {
return __CLASS__;
}
}
$OBJ = new OBJ();
$OBJ->getName();
See also: http://php.net/manual/en/language.constants.predefined.php
If you simply want to ensure that each reference to the object has a unique ID, you can do that with a static variable.
class ClassA {
public function getUniqueName() {
static $count = 0;
++$count;
return __CLASS__ . '.' . $count;
}
}
$OBJ = new ClassA();
echo($OBJ->getUniqueName();
Every time that method is called, it will give you a different result. If you call it only once on each variable, you should be fine.
Assuming you have a constant defined in a class:
class Foo {
const ERR_SOME_CONST = 6001;
function bar() {
$x = 6001;
// need to get 'ERR_SOME_CONST'
}
}
Is it possible with PHP?
You can get them with the reflection API
I'm assuming you would like to get the name of the constant based on the value of your variable (value of variable == value of constant). Get all the constants defined in the class, loop over them and compare the values of those constants with the value of your variable.
Note that with this approach you might get some other constant that the one you want, if there are two constants with the same value.
example:
class Foo {
const ERR_SOME_CONST = 6001;
const ERR_SOME_OTHER_CONST = 5001;
function bar() {
$x = 6001;
$fooClass = new ReflectionClass ( 'Foo' );
$constants = $fooClass->getConstants();
$constName = null;
foreach ( $constants as $name => $value )
{
if ( $value == $x )
{
$constName = $name;
break;
}
}
echo $constName;
}
}
ps: do you mind telling why you need this, as it seems very unusual ...
Here's what I did to achieve it. Inspired by Jan Hancic.
class ErrorCode
{
const COMMENT_NEWCOMMENT_DISABLED = -4;
const COMMENT_TIMEBETWEENPOST_ERROR = -3;
/**
* Get error message of a value. It's actually the constant's name
* #param integer $value
*
* #return string
*/
public static function getErrorMessage($value)
{
$class = new ReflectionClass(__CLASS__);
$constants = array_flip($class->getConstants());
return $constants[$value];
}
}
With Reflection:
$class = new ReflectionClass("Foo");
$constants = $class->getConstants();
$constants is an array which holds all the names and values of the constants defined in class Foo.
All the other answers cover the essential points. But, if crazy one liners is your thing, then:
function getConstantName($class, $value)
{
return array_flip((new \ReflectionClass($class))->getConstants())[$value];
}
If you need to handle the case where the value might not actually be one of the constants, then you can give up an extra line:
function getConstantName($class, $value)
{
$map = array_flip((new \ReflectionClass($class))->getConstants());
return (array_key_exists($value, $map) ? $map[$value] : null);
}
I know this is an old question and all, but I still feel that I have some useful input. I implemented this using an abstract class that all my enums extend. The abstract class contains a generic toString() method;
abstract class BaseEnum{
private final function __construct(){ }
public static function toString($val){
$tmp = new ReflectionClass(get_called_class());
$a = $tmp->getConstants();
$b = array_flip($a);
return ucfirst(strtolower($b[$val]));
}
}
//actual enum
final class UserType extends BaseEnum {
const ADMIN = 10;
const USER = 5;
const VIEWER = 0;
}
This way you can get a human readable string to use in output, on every enum that extends the base enum. Furthermore, your implementation of the enum, being final, cannot be extended and because the constructor in the BaseEnum is private it can never be instantiated.
So for instance, if you show a list of all usernames with their types you can do something like
foreach($users as $user){
echo "<li>{$user->name}, ".UserType::toString($user->usertype)."</li>";
}
All constant can be assigned to an array using this function.
$const = get_defined_constants();
then using following function you can print the array structure
echo "<pre>";
print_r($const);
and you can see more explanation here www.sugunan.com
Warning: This way you should NOT program... ( if youre not sure what youre doing :) )
I wrote 1 row which echos constants and their numeric values by your choice of CATEGORY_
so here is the list of CATEGORY_ ERR_
foreach(get_defined_constants() as $key => $value) if(strlen($key)>5) if(substr($key, 0,5)=="ERR_") echo"<br>Found an php ERR_ constant! : ".$key."=>".$value;
And if you want just the one youre looking for by number => I created 1row function:
//input parameters: CATEGORYNAME_ , #constantNumber
function getConstantName($category,$constantNumber){foreach(get_defined_constants() as $key => $value) if(strlen($key)>strlen($category)) if(substr($key, 0,strlen($category))==$category) if($value==$constantNumber) return $key; return "No constant found.";}
So for example some info constant with number 64:
echo "NameOfConstant: ".getConstantName("INFO_",64);
will output something like: NameOfConstant: INFO_LICENSE
OK, OK, I know everything is already covered :)
But Jan Hančič asked for use case, so I'll share mine.
Aside: everyone seems to use array_flip(). Why not array_search()?
I needed it in a class that extends \Exception and is base class of small set of my concrete exceptions. Each of those concrete exception classes covers a broad exception domain and has defined several precise exception causes. Reason? I don't want to have a horde of exceptions to maintain and remember of. Also, there is exception handler set that dumps exception's guts into log file - and it's here I need to get the constant name as trying to decipher exception cause from status in quite painful.
Examples from my CLI scripts:
class AbstractException extends Exception {
public function getName() {
return array_search($this->getCode(), (new ReflectionClass($this))->getConstants());
}
}
class SyntaxException extends AbstractException {
const BAD_SYNTAX = 90;
const REQUIRED_PARAM = 91;
const REQUIRED_VALUE = 92;
const VALUE_TYPE = 93;
const VALUE_OUT_OF_BOUNDS = 94;
public function __construct ($message = "", $code = self::BAD_SYNTAX, Exception $previous = NULL) {
$script = basename($GLOBALS['argv'][0]);
echo "Invalid syntax: $message \nSee: `$script --help` for more information\n";
parent::__construct($message, $code, $previous);
}
}
// in autoload include
set_exception_handler(function(Exception $e) {
error_log(basename($GLOBALS['argv'][0]) . ';'. date('Y-m-d H:i:s') .';'. $e->getName() .';'. $e->getMessage() .';'. $e->getFile() .';'. $e->getLine() ."\n", 3, 'error.log');
exit ($e->getCode());
});
class OrderStatus
{
public const PENDING = 1;
public const PROCESSED = 2;
public static function getStatusCode($value)
{
$class = new ReflectionClass(__CLASS__);
$constants = array_flip($class->getConstants());
return $constants[$value] ?? null;
}
// OrderStatus::getStatusCode(1); // 'PENDING'
}
if you need to get the constant value on a method of the same class, you just need to use the self operator. You could use reflection if you want to use the constants on another class
class Foo {
const ERR_SOME_CONST = 6001;
function bar() {
self::ERR_SOME_CONST;
}
}