PHP Cast to my class - php

why this is not possible:
$user = (User) $u[0];
but this is possible
$bool = (boolean) $res['success'];
I use PHP 7.0.

As I know, in PHP you can only cast to some types:
(int), (integer) - cast to integer
(bool), (boolean) - cast to boolean
(float), (double), (real) - cast to float (real deprecated in PHP 8.0)
(string) - cast to string
(binary) - cast to binary string (PHP 6)
(array) - cast to array
(object) - cast to object
(unset) - cast to NULL (PHP 5) (depracted in PHP 7.2) (removed in 8.0)
(see Type Casting)
Instead you could use instanceof to check of specific type:
if($yourvar instanceof YourClass) {
//DO something
} else {
throw new Exception('Var is not of type YourClass');
}
EDIT
As mentioned by Szabolcs Páll in his answer, it is also possible to declare a return type or parameter type, but in that cases an exception (TypeError) will be throwen, if the type does not match.
function test(): string
{
return 'test';
}
function test(string $test){
return "test" . $test;
}
Since PHP 7.2 it is also possible to make the types nullable by adding ? in front of them:
function test(): ?string
{
return null;
}

You can use PHPDoc
/** #var User $user */
$user = $u[0];

If you just want to ensure a variable is instance of YourClass and let exception handling to the typesystem you can use the following function:
function implicitFakeCast($myClass): YourClass
{
return $myClass;
}
Note: this will not actually do any casting, rather it throws exceptions in case of class mismatch and lets intellisense treat it as an instance of the target class.

For people that do want to be able to cast to a class type. I've found a gist by #borzilleri that uses serialize and unserialize to achieve this: https://gist.github.com/borzilleri/960035.
TL;DR:
// make sure to include the namespace when casting
$className = "Some\\NameSpace\\SomeClassName";
$classNameLength = strlen( $className );
$castedItem = unserialize(
preg_replace(
'/^O:\d+:"[^"]++"/',
"O:$classNameLength:\"$className\"",
serialize( $item )
)
)

It's really simple in php8:
$item = (fn($item):YourClass=>$item)($item);

Objects and primitive types are different. Since it's called as primitive types, they are really simple, maybe only 1 byte, 2 bytes, or 4 bytes, and at most 8 bytes.
When we are talking about object, this object can have different attributes with the others. Then the question from PHP will be is, "is this object really from my Class?" "How to convert this object to my Class?". Thus, you can't parse right away the object using
$myObject = (ClassName) $variable
Then how to cast it? Dunno, but usually the approach is like this:
Create constructor for the class
In the class, make a method that specifically accept certain parameters, maybe array
here is sample:
public class MyAwesomeClass{
function __construct($thisIsArray){
$this->attributeA = $thisIsArray["A"];
$this->attributeB = $thisIsArray["B"];
......
}
static function fromArray($thisIsArray){
return MyAwesomeClass($thisIsArray);
}
}
$obj = MyAwesomeClass::fromArray($attributes);

In addition to the answer on why this is not possible, I would suggest that you write a builder function that creates an object, based on your input. so it would look something like
$user = User::buildFromSomeArrayInput($u[0]);
And then have a builder create a new User object, assign the right properties, etc. You could just do all this in-place of course, but having a builder function makes sure you won't be doing this on several locations, AND you can set private properties as it is a class-member function. It is a bit more work then having it magically work, but not that much.
The only issue you might have is when you do have a different object that does not expose all the internals you might need. But this is for a reason, as internals might change -> you don't want to rely on that.
There are hacks out there that suggest doing this with serialization. I would suggest to steer away from them, as they are hackish and as far as i'm concerned, not very clear.

Related

How to permanently typecast class properties in PHP?

I have been reading the "Visibility" section of the PHP manual, and in the first comment, someone mentions:
OUTSIDE CODE can cast Item properties to any other PHP types (booleans, integers, floats, strings, arrays, and objects etc.) -- another huge mistake.
Consider this example:
class base {
public $foo = 1;
}
$first = new base();
(string)$first->foo; //I thought just this expression would typecast
var_dump($first->foo); //but I found it still is int
$first->foo = (string)$first->foo;
var_dump($first->foo); //ok so public props can be typecasted
Is it just with the protected and private properties that we cannot change their type from outside? Or does that apply to public properties, too?
What you are doing is overwriting the property with a new value, which happens to be a different type.
Type casting does not affect the original variable or value. It creates a new value of the typecasted type that you need to assign if you want to preserve.
What you are asking has nothing to do with object properties visibility, but with understanding that typecasting is an operation that does not affect its operand.
This does absolutely nothing to $string:
$string = "123";
(int)$string;
... and the type casted value is lost since we are not assigning the result of the operation
With the following we can overwrite the value of $class::$someInteger, if a couple of conditions are met:
$class->someInteger = (string) 123;
That the property is public. (You obviously can't access directly private or protected properties from outside the class. You can cheat around this by using reflection or weird stuff like having a getter that returns a reference to the property, but both are very bad ideas for production code).
You are not using PHP 7.4 typed properties, and have declared a type for it.
The "permanently" part of the question is particularly misguided, since in PHP generally variables do not have types.
You can assign values of any type to any variable. And when they do have types (PHP 7.4 typed properties) there is no practical way of changing the defined type (again, there might be a way using reflection... but I'm not going there).
Your question is based upon the misunderstanding of the meaning of the term typecasting. The PHP Manual's page on type casting and the whole manual in general, is inadequate and is not a self-contained canonical reference for learning the php language. Plus, it assumes you to have knowledge of other programming languages such as C.
Typecasting is not defined as the data-type conversion of a variable; it is the data-type conversion of an expression -- In general, that is in most programming languages. Wikipedea defines it as following:
In computer science, type conversion, type casting, type coercion, and type juggling are different ways of changing an expression from one data type to another.
The official manual uses three terms namely, type juggling, type conversion and type casting. It can be guessed from the first paragraph that type juggling and type conversion are one and the same things. In the first paragraph they say:
Note that this does not change the types of the operands themselves; the only change is in how the operands are evaluated...
It should be clear that type juggling definitely doesn't change the type of the variable. From the php manual it appears as type juggling and type casting are two different concepts. The question is, since The PHP manual never defines these terms, how can we make sure if those two terms are same and what they actually mean. In the Type Casting article the manual says:
Type casting in PHP works much as it does in C:...
So, the answer is, we can safely assume that the definition of type casting from the C language applies to the PHP language. In C language type casting is defined same as the Wikipedia definition, that is only the expression's data type is converted. The following excerpts are taken from the book The C Programming Language by K&R, 2nd edition, section 2.7, page 45:
In the construction (type-name) expression, the expression is converted to the named type... ...The precise meaning of cast is as if the expression were assigned to a variable of the specific type... ...we can use sqrt((double) n)... ...Note that cast produces the value of n in the proper type, n itself is not altered.
This concludes the fact that type casting in php works the same way as type juggling in that the data type of variables(operands) being acted upon is not changed. You can rather use the function settype() to convert the data type of a variable.
As pointed out in the first paragraph, php manual's page on types gives the following technically wrong comment in their last paragraph:
To forcibly convert a variable to a certain type, either cast the variable or use the settype() function on it.
Now, you know what type casting in php actually means and why you had that misconception, it would be better to rephrase your question as following:
Rephrased question: How to permanently convert the data type of class properties in PHP.
It should be obvious that public properties will be converted to different type easily by settype($myObj->myPubProp, required-type). The interesting thing is, contrary to the suggestion made in user yivi's original answer, privated and protected properties can be assessed and can have their type converted from outside the class[1][2].
Method 1: Using references:
class myClass {
private $prop = 786; //Could be protected too.
public function &assess_priv(){
return $this->prop;
}
public function display_prop() {
echo var_dump($this->prop);
}
}
$obj = new myClass;
$newObjProp = &$obj->assess_priv();
settype($newObjProp, "string");
$obj->display_prop(); //converted the data type of private property of a class
Method 2: Using PHP property overloading
error_reporting(E_ALL);
class myClass {
private $prop = 786; //Could be protected too.
public function __set($name, $value)
{
$this->$name = $value;
}
public function __get($name)
{
return $this->$name;
}
}
$obj = new myClass;
var_dump($obj->prop);
$obj->prop = (string)$obj->prop; //Interestingly, settype($obj->prop, "string"); can't be used
echo "</br>";
var_dump($obj->prop); //converted the data type of private property of a class
Type casting class properties is now available in php7.4.
<?php
class User {
public int $id;
public string $name;
}
$user = new User;
$user->id = 123; // this will work
$user->id = "hello world"; // throws fatal error
Fatal error: Uncaught TypeError: Typed property
User::$id must be int, string used in [...][...]:7 Stack trace:
#0 {main} thrown in [...][...] on line 7
You need to switch to php7.4. This feature is now available in 7.4 link to their official docs
This is the sandbox link to try online.

PHP strict type of variables [duplicate]

For example, is it possible to write code like this:
int $x = 6;
str $y = "hello world";
bool $z = false;
MyObject $foo = new MyObject();
And is it possible to define functions like this:
public int function getBalance()
{
return 555; //Or any numeric value
}
In PHP 7 are implemented "Scalar Type Declarations", e.g.:
public function getBalance(): int {
return 555;
}
You need to declare, that you will use strict types:
<?php
declare(strict_types=1);
function sum(int $a, int $b): int {
return $a + $b;
}
sum(1, 2);
?>
More information: https://wiki.php.net/rfc/scalar_type_hints_v5
Edit: This answer applies to versions of PHP 5.6 and earlier. As noted in recent answers, PHP version 7.0 and later does have some support for this
Original answer:
No. There is only support for type hinting since php5, but "Type Hints can only be of the object and array (since PHP 5.1) type. Traditional type hinting with int and string isn't supported."
In PHP 7 are implemented "Scalar Type Declarations" see the answer below.
That is as far as php currently goes, and as far as it should go if you ask me.
PHP is not strictly typed, so no. That said, it does support limited type hinting on functions - that's as close as it gets.
Unfortunately NO! I am at the end of a big project now that involves a lot alogorithms (graph theory, circuits etc) and I wish I hadn't choose php.
I have been using php for about 10 years, and still believe it is a good language, however one have to decide! What is bad for me, lack of strict typing might be good for someone else.
In addition, I want to mention, that I often wrote extra code for supporting strict typing, just a plain example is this:
if (is_array($r) && count($r)===0)
and the errors and hidden situations etc that were revealed are beyond explanation.
There were mistakes and situations that I would never been able to think/detect apriori, writing all these extra code was not enjoying but at least it will save me from silly mistakes!
If I would go back, maybe I would chose php for the web part, you know getting and showing data to the user, php is just great for that, handling string, arrays, talking to the database etc etc, but for the main core, algorithms etc I would go for C++, maybe haskell.. don't know, at least something strictly typed.
Something you might try in order to simulate a poor man's strict type checking is using assert() to force the output to be of a particular type before you return it:
/**
* Get Balance
*
* #return int
*/
function getBalance()
{
/* blah blah blah */
$out = 555; //Or any numeric value
assert('is_int($out)');
return $out;
}
So you keep your assertions active all throughout development and testing, sort of like the checks the compiler does at compile-time.
Granted, the assert() page is keen to assert that you shouldn't use assertions to check input parameters, but rather use normal conditionals to check them.
This answer had what I thought was a good rule:
The rule of thumb which is applicable across most languages (all that I vaguely know) is that an assert is used to assert that a condition is always true whereas an if is appropriate if it is conceivable that it will sometimes fail.
If you're simulating strict type-checking (writing your code to viciously maintain types; not trying to validate input from the outside), then you ought to be certain what the type is unless you've made a mistake.
Update:
There's also this: http://hacklang.org/
Facebook's PHP-based language with static typing.
Perhaps you should try this PHP extension https://github.com/krakjoe/strict. Support for the following types is introduced:
string
integer, int
float, double
boolean, bool
resource
You could use h2tp transpiler to transpile HACK code to PHP:
You can do this thanks to Facebook Team and HACK Language.
Visit http://hacklang.org and http://hhvm.com for more info.
If you want to code directly in Hack + HHVM environment you can also use Facebook's internal IDE Nuclide
Since the answer is basically "no", an alternative: A PHP "linter", which should catch some of the things a compile-time check would catch in a staticly-typed language like C. Not the same, but should prevent some sillyness
"Is there a static code analyzer [like Lint] for PHP files" lists many of these.
PHP 7.0 introduced function return type hints, and PHP 7.4 added support for class property type hints. As of PHP 7.4, your code would be:
<?php declare(strict_types=1);
class MyObject
{
}
class TypedStuff
{
public static int $x;
public static string $y;
public static bool $z;
public static MyObject $foo;
}
function getBalance(): float
{
return 555; //Or any numeric value
}
TypedStuff::$x = 6;
TypedStuff::$y = "hello world";
TypedStuff::$z = false;
TypedStuff::$foo = new MyObject();
You can't type-hint one-off variables, but you can type-hint static class properties, which could be used in an almost identical manner. You can also type-hint the return type of stand-alone functions.
More commonly, you'd be defining typed values inside a class using a typed setter, and receiving typed values outside a class using a typed getter, like:
<?php declare(strict_types=1);
class Person {
private $age;
public function __construct(int $age)
{
$this->age = $age;
}
public function setAge(int $age): void { $this->age = $age; }
public function getAge(): int { return $this->age; }
}
$person = new Person(30);
echo sprintf(
'The person is %d years old.',
$person->getAge()
);
This works in PHP 7.0 because property type-hints are not required.
No. That syntax will not work.
You could, theoretically, come up with a system of objects that enforced their own sort of strict typing, but it wouldn't perform and ...why would you want to, anyway?
If you need strict typing, use a strictly typed language.

PHP type-hinting to primitive values?

I'd like to know whether one can type-hint a method to expect primitive types?
Something like this:
public function someMethod(string $str)
//^^^^^^
Or:
private function anotherMethod(int $num)
//^^^
the same way you would:
private function otherMethod(Person $rambo)
//^^^^^^
Is that possible in php?
In PHP 7 they added the following:
Type declarations allow functions to require that parameters are of a certain type at call time. If the given value is of the incorrect type, then an error is generated: in PHP 5, this will be a recoverable fatal error, while PHP 7 will throw a TypeError exception.
Reference:
http://php.net/manual/en/functions.arguments.php#functions.arguments.type-declaration
When this answer was asked, PHP 5 was the latest and said the following:
PHP 5 introduces type hinting. Functions are now able to force parameters to be objects (by specifying the name of the class in the function prototype), interfaces, arrays (since PHP 5.1) or callable (since PHP 5.4). However, if NULL is used as the default parameter value, it will be allowed as an argument for any later call.
If class or interface is specified as type hint then all its children or implementations are allowed too.
Type hints cannot be used with scalar types such as int or string. Resources and Traits are not allowed either.
Reference: http://php.net/manual/en/language.oop5.typehinting.php
Nope. You can't type hint for primitives because PHP has automatic conversions for primitives. See http://bugs.php.net/bug.php?id=29508. This will never change, unless the PHP team has a sudden change of heart (which is doubtful, they're pretty stubborn).
Yes, Now its possible,
After a long discussion, a proposal to implement type hinting for scalar function parameters and return values was just approved with the highest vote count so far, check for details :
Scalar type hinting consists of declaring the types of function parameters and return values that can be of the types int, float, string and bool.This allows the PHP runtime engine to check if the types of values passed to parameter functions and return values are of the expected types in order to detect eventual programming mistakes.
Type hinting for objects, arrays and callables was already allowed in past PHP versions.
The current implementation introduces five new reserved words: int, float, bool, string and numeric. These were not previously reserved, because casting is a special case in the lexer.
Example :
function test(float $a) {
var_dump($a);
}
test(1); // float(1)
test("1"); // float(1)
test(1.0); // float(1)
test("1a"); // E_RECOVERABLE_ERROR
test("a"); // E_RECOVERABLE_ERROR
test(""); // E_RECOVERABLE_ERROR
test(1.5); // float(1.5)
test(array()); // E_RECOVERABLE_ERROR
test(new StdClass); // E_RECOVERABLE_ERROR
You have also an option to declare into source file where you can allow Scaler type hinting.It must be 1st line of your config script and can’t be declared elsewhere in the same file.
Like : declare(strict_types=1);
At runtime, when the PHP engine tries to return a value, it will check if doesn’t match as declared it will throw a fatal error like,
Fatal error: Argument 1 passed to increment() must be of the type integer, string given
With this new features of declaration, you can write more robust applications by detecting early programming mistakes caused by passing values of the wrong types to functions.
Automatic changes of types may also happen. For example, int types can be change into float type parameters automatically,
function test(float $x){
var_dump($x);
}
test(10); // works fine
Declaring the Return Type
We can declare the return types adding a colon followed by the expected type between the last parenthesis and the first bracket in the function declaration.
For functions that do not return any value, nothing should be added in the return type declaration section.
function mustReturnInt(): int { ... }
function mustReturnString(): string { ... }
function mustReturnBool(): bool { ... }
function mustReturnFloat(): float { ... }
function doesNotReturnAnything() { ... }
A Little Bit more Complex Example
declare(strict_types=1);
class StrictTypesTestingClass {
public function returnSameInt(int $value): int { return $value; }
public function returnSameFloat(float $value): float { return $value; }
public function returnSameString(string $value): string { return $value; }
public function returnSameBool(bool $value): bool { return $value; } }
$check = new StrictTypesTestingClass(); // calls that work print $check->returnSameInt(10);
print $check->returnSameFloat(10.0);
print $check->returnSameString("test");
print $check->returnSameBool(true) ? 'true' : 'false'; // calls that throw exceptions
print $check->returnSameInt("10");
print $check->returnSameFloat("10.0");
print $check->returnSameString(10);
print $check->returnSameBool("true");
Behavior of Weak Type Checking and Type Conversion : The weak type checking mode can be used with the statement declare(strict_types=0); or the absence of the strict types declaration. There are a few of points to take into account:
Weak type checked calls to an extension or built-in PHP function have the same behaviour as in previous PHP versions
The weak type checking rules for new scalar type declarations are mostly the same as those of extension or built-in PHP functions.
NULL is a special case in order to be consistent with the current type declarations for classes, callables and arrays. NULL is not accepted by default, unless it is a parameter and is explicitly given a default value of NULL, for instance: function sample(int $a = NULL);
There are a lots of advantages to this approach. You get type safety. Which means that you can finally statically analyze code! You can detect bugs where you accidentally take a string from one function and pass it as an integer to another.For me, a developer that uses PHP on a daily basis and sees Java as a reference for OOP languages, this is great progress for PHP.
Everyone already said it, you can't do type hint for primitives because PHP doest not support it. The reason behind this is not only related to automatic conversions but also to community reaction.
So far, I can remember that in May of 2010 support for scalar type hinting was added to the PHP trunk. But because of community response this feature didn't make it into the 5.4 release.
There was a bit of controversy about this. Those who opposed the change argued that this support would go against the fundamental designs of PHP. PHP is considered to be a weak typed language. In essence, this means that PHP does not require you to declare data types. Variables still have data types associated with them but you can do radical things like adding a string to an integer without resulting in an error.
IMHO: Scalar type hinting should be added into PHP ASAP, it's a feature we all need, I really respect that PHP is weak typed language, but for high end development and production, specially on OO contexts, scalar type hinting is a must have. We can have both alternatives in PHP, just like procedural and OO.
Yes, it is possible.
http://ru2.php.net/manual/ru/language.oop5.typehinting.php#83442
Warning: there is a typo in original manual: resrouce instead of resource
People often ask about scalar/basic typehints. Here is a drop in class that I use in my MVC framework that will enable typehints through the use of a custom error handler.
Note: You should include this code above all other code in your include headers and if you are the using set_error_handler() function you should be aware that this uses it as well. You may need to chain your set_error_handlers()
Why?
Because people are sick of using the is_* functions to validate parameters.
Reduction of redundant coding for defensive coders.
Functions/Methods are self defining/documenting as to required input.
Also..
Follow the discussion for typehints in PHP 6.0 on the PHP Internals boards.
<?php
define('TYPEHINT_PCRE', '/^Argument (\d)+ passed to (?:(\w+)::)?(\w+)\(\) must be an instance of (\w+), (\w+) given/');
class Typehint
{
private static $Typehints = array(
'boolean' => 'is_bool',
'integer' => 'is_int',
'float' => 'is_float',
'string' => 'is_string',
'resource' => 'is_resource'
);
private function __Constrct() {}
public static function initializeHandler()
{
set_error_handler('Typehint::handleTypehint');
return TRUE;
}
private static function getTypehintedArgument($ThBackTrace, $ThFunction, $ThArgIndex, &$ThArgValue)
{
foreach ($ThBackTrace as $ThTrace)
{
// Match the function; Note we could do more defensive error checking.
if (isset($ThTrace['function']) && $ThTrace['function'] == $ThFunction)
{
$ThArgValue = $ThTrace['args'][$ThArgIndex - 1];
return TRUE;
}
}
return FALSE;
}
public static function handleTypehint($ErrLevel, $ErrMessage)
{
if ($ErrLevel == E_RECOVERABLE_ERROR)
{
if (preg_match(TYPEHINT_PCRE, $ErrMessage, $ErrMatches))
{
list($ErrMatch, $ThArgIndex, $ThClass, $ThFunction, $ThHint, $ThType) = $ErrMatches;
if (isset(self::$Typehints[$ThHint]))
{
$ThBacktrace = debug_backtrace();
$ThArgValue = NULL;
if (self::getTypehintedArgument($ThBacktrace, $ThFunction, $ThArgIndex, $ThArgValue))
{
if (call_user_func(self::$Typehints[$ThHint], $ThArgValue))
{
return TRUE;
}
}
}
}
}
return FALSE;
}
}
Typehint::initializeHandler();
?>
An are some examples of the class in use:
<?php
function teststring(string $string) { echo $string; }
function testinteger(integer $integer) { echo $integer; }
function testfloat(float $float) { echo $float; }
// This will work for class methods as well.
?>
You get the picture..
Accordind to PHP documentation type hinting is not supported for primitive types.
It's supported for classes and interfaces though.
Edit: I forgot to mention that's also supported for arrays.
Here is short syntax for forcing a boolean value out of a passed in parameter. If $state is true, then $this->is_active is set to true. For all other types of values it is set to false.
function set_active ( $state ) {
$this->is_active = true === $state;
}
I guess you don't need type hinting for PHP because you're given type checking functions such as is_bool(), is_string() etc etc, so you could check whatever your trying to put into an argument against these functions before actually making it an argument, although the method they use to check array and object types would be much cleaner.

Implicit Type Conversion for PHP Classes?

Is there a way to tell the php complier that I want a specific implicit conversion from one type to another?
A simple example:
class Integer
{
public $val;
}
function ExampleFunc(Interger $i){...}
ExamFunc(333); // 333 -> Integer object with $val == 333.
[edit]... someone asked for an example. Here's an example from c#. This is a boolean type that changes value after it has been accessed once.
/// <summary>
/// A Heisenberg style boolean that changes after it has been read. Defaults to false.
/// </summary>
public class hbool
{
private bool value;
private bool changed = false;
public hbool()
{
value = false;
}
public hbool(bool value)
{
this.value = value;
}
public static implicit operator bool(hbool item)
{
return item.Value;
}
public static implicit operator hbool(bool item)
{
return new hbool(item);
}
public bool Value
{
get
{
if (!changed)
{
value = !value;
changed = true;
return !value;
}
return value;
}
}
public void TouchValue()
{
bool value1 = Value;
}
public static hbool False
{
get { return new hbool(); }
}
public static hbool True
{
get { return new hbool(true); }
}
}
[Test]
public void hboolShouldChangeAfterRead()
{
hbool b = false;
Assert.IsFalse(b);
Assert.IsTrue(b);
Assert.IsTrue(b);
hbool b1 = false;
Assert.IsFalse(b1);
Assert.IsTrue(b1);
Assert.IsTrue(b1);
hbool b2 = true;
Assert.IsTrue(b2);
Assert.IsFalse(b2);
Assert.IsFalse(b2);
bool b3 = new hbool();
Assert.IsFalse(b3);
Assert.IsFalse(b3);
Assert.IsFalse(b3);
}
PHP5 has type hinting, with limitations:
http://ca2.php.net/manual/en/language.oop5.typehinting.php
Specified types must be objects or array, so built in types such as string and int are not allowed.
This is not a conversion, but will throw an error if an object of the specified type is not passed to the method or function, as in your example.
Long answer:
I think it is very difficult (read impossible) for PHP to do an implicit conversion in this case.
Remember: the fact that you call your class Integer is a hint to the human reader of the code, PHP does not understand that it actually is used to hold an integer. Also, the fact that it has an attribute called $val is a hint to a human reader that it should probably contain the value of your integer. Again PHP does not understand your code, it only executes it.
At some point in your code you should do an explicit conversion. It might be possible that PHP has some nice syntactig sugar for that, but a first attempt would be something like:
class Integer
{
public $val;
function __construct($val) { $this->val = $val; }
}
function ExampleFunc($i){
if (is_numeric($i)) { $iObj = new Integer($i); }
...
}
ExamFunc(333); // 333 -> Integer object with $val === 333.
This is not as cool as you would like it, but again, it is possible that PHP has some syntactic sugar that will hide the explicit conversion more or less.
Short version:
In one way or another, you will need an explicit conversion
Actually this possible with the SPL_Type extension. It defines classes for primitive types whose objects operate interchangeably with the PHP's primitive types (booleans, enums, ints, floats and strings).
You first example would work by simply inheriting from SplIt as follows:
class Integer extends extends \SplInt{}
function ExampleFunc(Interger $i){...}
ExamFunc(333); // 333 -> Integer object with $val == 333.
The problem is that the code of the SplTypes extension hasn't been maintained since 2012, and by the moment of this post, it hasn't ported to PHP 7, nor there is a plan for such.
UPDATE
I have found the following unnofficial port of SPL Types to PHP 7. Use at your own risk: https://github.com/esminis/php_pecl_spl_types
Basic installation instructions:
Clone code: https://github.com/esminis/php_pecl_spl_types.git
Generate the configure file. Inside the code directory type:phpize.
Generate make file: ./configure
Compile code and install: make && make install
Add the module to your PHP configuraiton. At Ubuntu, type echo "extension=spl_types.so" > /etc/php7/conf.d/spl_types.ini
Restart your PHP-FPM (if using it): service php7.0-fpm restart
No, PHP is not a strongly typed language.
Are you asking how to type cast? You can do:
$ php -r 'var_dump("333");'
string(3) "333"
$ php -r 'var_dump((int)"333");'
int(333)
Otherwise PHP is weakly typed, so in general you don't need to do it. It's implied by the language. Eg. if a function takes a numeric argument, then that number can be string, integer or float all the same; The value is converted if needed. That's why you can for example echo 33 without an error.
PHP is not strongly typed.
You want something like, whenever you pass an hbool instance into a function that expects a bool it would convert automatically using your implicit conversor.
What happens is that no function "expects" a bool, it's all dynamically typed.
You can force an explicit conversion by calling (int)$something but if that's the case you can then pass $something->to_otherthing() instead for non-automatic conversions.
PS: I'm sure im not being clear here. I will try to edit this answer after I eat something :)
This question is very old, but I would like to give a solution.
This behaviour is called boxing which can be done in PHP, but the inverse of this, unboxing see:
function a(int $a){...}
a(new Integer(1));
is not possible currently. If you want a framework which offers you this and even more, look at the BlazeFramework which has such wrapper classes.
Operation overloading does not work either in php. The implementation is maybe a bit too much to write, but I give you a hint! PHP calls the callback set with set_error_handler() with the error level E_RECOVERABLE_ERROR and debug_backtrace() delivers information about the function/method call.
If you don't get that, look at the implementation of the method blaze\lang\System#systemErrorHandler(), but possibly it is better to just use the framework if you want more of such features.

PHP equivalent of .NET/Java's toString()

How do I convert the value of a PHP variable to string?
I was looking for something better than concatenating with an empty string:
$myText = $myVar . '';
Like the ToString() method in Java or .NET.
You can use the casting operators:
$myText = (string)$myVar;
There are more details for string casting and conversion in the Strings section of the PHP manual, including special handling for booleans and nulls.
This is done with typecasting:
$strvar = (string) $var; // Casts to string
echo $var; // Will cast to string implicitly
var_dump($var); // Will show the true type of the variable
In a class you can define what is output by using the magical method __toString. An example is below:
class Bottles {
public function __toString()
{
return 'Ninety nine green bottles';
}
}
$ex = new Bottles;
var_dump($ex, (string) $ex);
// Returns: instance of Bottles and "Ninety nine green bottles"
Some more type casting examples:
$i = 1;
// int 1
var_dump((int) $i);
// bool true
var_dump((bool) $i);
// string "1"
var_dump((string) 1);
Use print_r:
$myText = print_r($myVar,true);
You can also use it like:
$myText = print_r($myVar,true)."foo bar";
This will set $myText to a string, like:
array (
0 => '11',
)foo bar
Use var_export to get a little bit more info (with types of variable,...):
$myText = var_export($myVar,true);
You can either use typecasting:
$var = (string)$varname;
or StringValue:
$var = strval($varname);
or SetType:
$success = settype($varname, 'string');
// $varname itself becomes a string
They all work for the same thing in terms of Type-Juggling.
How do I convert the value of a PHP
variable to string?
A value can be converted to a string using the (string) cast or the strval() function. (Edit: As Thomas also stated).
It also should be automatically casted for you when you use it as a string.
You are looking for strval:
string strval ( mixed $var )
Get the string value of a variable.
See the documentation on string for
more information on converting to
string.
This function performs no formatting
on the returned value. If you are
looking for a way to format a numeric
value as a string, please see
sprintf() or number_format().
For primitives just use (string)$var or print this variable straight away. PHP is dynamically typed language and variable will be casted to string on the fly.
If you want to convert objects to strings you will need to define __toString() method that returns string. This method is forbidden to throw exceptions.
Putting it in double quotes should work:
$myText = "$myVar";
I think it is worth mentioning that you can catch any output (like print_r, var_dump) in a variable by using output buffering:
<?php
ob_start();
var_dump($someVar);
$result = ob_get_clean();
?>
Thanks to:
How can I capture the result of var_dump to a string?
Another option is to use the built in settype function:
<?php
$foo = "5bar"; // string
$bar = true; // boolean
settype($foo, "integer"); // $foo is now 5 (integer)
settype($bar, "string"); // $bar is now "1" (string)
?>
This actually performs a conversion on the variable unlike typecasting and allows you to have a general way of converting to multiple types.
In addition to the answer given by Thomas G. Mayfield:
If you follow the link to the string casting manual, there is a special case which is quite important to understand:
(string) cast is preferable especially if your variable $a is an object, because PHP will follow the casting protocol according to its object model by calling __toString() magic method (if such is defined in the class of which $a is instantiated from).
PHP does something similar to
function castToString($instance)
{
if (is_object($instance) && method_exists($instance, '__toString')) {
return call_user_func_array(array($instance, '__toString'));
}
}
The (string) casting operation is a recommended technique for PHP5+ programming making code more Object-Oriented. IMO this is a nice example of design similarity (difference) to other OOP languages like Java/C#/etc., i.e. in its own special PHP way (whenever it's for the good or for the worth).
As others have mentioned, objects need a __toString method to be cast to a string. An object that doesn't define that method can still produce a string representation using the spl_object_hash function.
This function returns a unique identifier for the object. This id can be used as a hash key for storing objects, or for identifying an object, as long as the object is not destroyed. Once the object is destroyed, its hash may be reused for other objects.
I have a base Object class with a __toString method that defaults to calling md5(spl_object_hash($this)) to make the output clearly unique, since the output from spl_object_hash can look very similar between objects.
This is particularly helpful for debugging code where a variable initializes as an Object and later in the code it is suspected to have changed to a different Object. Simply echoing the variables to the log can reveal the change from the object hash (or not).
I think this question is a bit misleading since,
toString() in Java isn't just a way to cast something to a String. That is what casting via (string) does, and it works as well in PHP.
// Java
String myText = (string) myVar;
// PHP
$myText = (string) $myVar;
Note that this can be problematic as Java is type-safe (see here for more details).
But as I said, this is casting and therefore not the equivalent of Java's toString().
toString in Java doesn't just cast an object to a String. It instead will give you the String representation. And that's what __toString() in PHP does.
// Java
class SomeClass{
public String toString(){
return "some string representation";
}
}
// PHP
class SomeClass{
public function __toString()
{
return "some string representation";
}
}
And from the other side:
// Java
new SomeClass().toString(); // "Some string representation"
// PHP
strval(new SomeClass); // "Some string representation"
What do I mean by "giving the String representation"?
Imagine a class for a library with millions of books.
Casting that class to a String would (by default) convert the data, here all books, into a string so the String would be very long and most of the time not very useful.
To String instead will give you the String representation, i.e., only the library's name. This is shorter and therefore gives you less, but more important information.
These are both valid approaches but with very different goals, neither is a perfect solution for every case, and you have to choose wisely which fits your needs better.
Sure, there are even more options:
$no = 421337 // A number in PHP
$str = "$no"; // In PHP, the stuff inside "" is calculated and variables are replaced
$str = print_r($no, true); // Same as String.format();
$str = settype($no, 'string'); // Sets $no to the String Type
$str = strval($no); // Get the string value of $no
$str = $no . ''; // As you said concatenate an empty string works too
All of these methods will return a String, some of them using __toString internally and some others will fail on Objects. Take a look at the PHP documentation for more details.
Some, if not all, of the methods in the previous answers fail when the intended string variable has a leading zero, for example, 077543.
An attempt to convert such a variable fails to get the intended string, because the variable is converted to base 8 (octal).
All these will make $str have a value of 32611:
$no = 077543
$str = (string)$no;
$str = "$no";
$str = print_r($no,true);
$str = strval($no);
$str = settype($no, "integer");
The documentation says that you can also do:
$str = "$foo";
It's the same as cast, but I think it looks prettier.
Source:
Russian
English
Double quotes should work too... it should create a string, then it should APPEND/INSERT the casted STRING value of $myVar in between 2 empty strings.
You can always create a method named .ToString($in) that returns
$in . '';
If you're converting anything other than simple types like integers or booleans, you'd need to write your own function/method for the type that you're trying to convert, otherwise PHP will just print the type (such as array, GoogleSniffer, or Bidet).
PHP is dynamically typed, so like Chris Fournier said, "If you use it like a string it becomes a string". If you're looking for more control over the format of the string then printf is your answer.
You can also use the var_export PHP function.
$parent_category_name = "new clothes & shoes";
// To make it to string option one
$parent_category = strval($parent_category_name);
// Or make it a string by concatenating it with 'new clothes & shoes'
// It is useful for database queries
$parent_category = "'" . strval($parent_category_name) . "'";
For objects, you may not be able to use the cast operator. Instead, I use the json_encode() method.
For example, the following will output contents to the error log:
error_log(json_encode($args));
Try this little strange, but working, approach to convert the textual part of stdClass to string type:
$my_std_obj_result = $SomeResponse->return->data; // Specific to object/implementation
$my_string_result = implode ((array)$my_std_obj_result); // Do conversion
__toString method or (string) cast
$string=(string)$variable; //force make string
you can treat an object as a string
class Foo
{
public function __toString()
{
return "foo";
}
}
echo new Foo(); //foo
also, have another trick, ı assume ı have int variable ı want to make string it
$string=''.$intvariable;
This can be difficult in PHP because of the way data types are handled internally. Assuming that you don't mean complex types such as objects or resources, generic casting to strings may still result in incorrect conversion. In some cases pack/unpack may even be required, and then you still have the possibility of problems with string encoding. I know this might sound like a stretch but these are the type of cases where standard type juggling such as $myText = $my_var .''; and $myText = (string)$my_var; (and similar) may not work. Otherwise I would suggest a generic cast, or using serialize() or json_encode(), but again it depends on what you plan on doing with the string.
The primary difference is that Java and .NET have better facilities with handling binary data and primitive types, and converting to/from specific types and then to string from there, even if a specific case is abstracted away from the user. It's a different story with PHP where even handling hex can leave you scratching your head until you get the hang of it.
I can't think of a better way to answer this which is comparable to Java/.NET where _toString() and such methods are usually implemented in a way that's specific to the object or data type. In that way the magic methods __toString() and __serialize()/__unserialize() may be the best comparison.
Also keep in mind that PHP doesn't have the same concepts of primitive data types. In essence every data type in PHP can be considered an object, and their internal handlers try to make them somewhat universal, even if it means loosing accuracy such as when converting a float to int. You can't deal with types as you can in Java unless your working with their zvals within a native extension.
While PHP userspace doesn't define int, char, bool, or float as an objects, everything is stored in a zval structure which is as close to an object that you can find in C, with generic functions for handling the data within the zval. Every possible way to access data within PHP goes down to the zval structure and the way the zend vm allows you to handles them without converting them to native types and structures. With Java types you have finer grained access to their data and more ways to to manipulate them, but also greater complexity, hence the strong type vs weak type argument.
These links my be helpful:
https://www.php.net/manual/en/language.types.type-juggling.php
https://www.php.net/manual/en/language.oop5.magic.php
I use variableToString. It handles every PHP type and is flexible (you can extend it if you want).

Categories