-3

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?

user31782
  • 7,087
  • 14
  • 68
  • 143
  • By permanently I mean the expression `(string)$first->foo` has been converted to, or being returned, as a value of different type temporarily. I want the expression `$first->foo` to be typecasted permanently. – user31782 Jan 18 '20 at 17:47
  • 1
    Again, that does not make sense because that's not how the language works. There is no way to do that, because that's not how the operation works nor how the language works. I don't think I can help you any longer. I tried, though. Good luck! – yivi Jan 18 '20 at 17:48
  • 2
    Those tags were irrelevant and not useful. They should not be applied to this question. Please do not add them back. – Cody Gray - on strike Jan 19 '20 at 05:52
  • @CodyGray Hey mate, would you please explain how `oop` and `public` tags are not relevant to the question? I agree with the `variables` tag as it says it's ambiguous. – user31782 Jan 19 '20 at 06:28
  • 1
    This isn't a question about object-oriented programming, so the [oop] tag is not relevant. You are just asking about type-casting, which isn't an OOP feature, nor is it related to OOP design. The [public] tag shouldn't exist at all. It does not provide any useful contextual information about the question. – Cody Gray - on strike Jan 19 '20 at 06:39
  • @CodyGray I am not asking about typecasting, I am asking specifically how to typecas private and protected properties of a class from outside the definition of a class, since class is a oop feature, hence my question is related to oop design. As for `public`, I reckon `private` tag fits even better and it provides useful information that my question is about private properties of a class. – user31782 Jan 19 '20 at 08:37

3 Answers3

8

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;
  1. 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).
  2. 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).

yivi
  • 42,438
  • 18
  • 116
  • 138
  • 1. So we can't typecast variables in php straight away, yeah? 2. If the only way to typecast is actually reassign another value(same value with different type) to the variable, there wouldn't be any way to typecast private or protected properties, yeah? – user31782 Jan 18 '20 at 17:19
  • 1
    Again, type casting is an operation that does not affect the operand. Typecasting does not change the type of variable, but produces a new value of the desired type. You cannot modify private or protected variables from outside the class... unless they have an accessor (think `setFoo($foo)`). – yivi Jan 18 '20 at 17:22
  • Would you be able to give some reference for the definition of _typecasting_. – user31782 Jan 18 '20 at 17:28
  • https://www.php.net/manual/en/language.types.type-juggling.php#language.types.typecasting – yivi Jan 18 '20 at 17:29
  • It doesn't define it. Do you know any official reference for C language typecast definition. – user31782 Jan 18 '20 at 17:33
  • 1
    This is getting far afield. The linked docs properly explains how typecasting works. You can continue doing your own research about type theory, and how typecasting works in different languages. Hopefully I helped you. Good luck! – yivi Jan 18 '20 at 17:37
3

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  
user31782
  • 7,087
  • 14
  • 68
  • 143
-3

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.

danish-khan-I
  • 776
  • 6
  • 15
  • 1
    This is not type **casting**. These are **typed properties**. This an answer to a different question. – yivi Jan 29 '20 at 09:39
  • 1
    From the Question _I want the expression $first->foo to be typecasted permanently._ . And this is exactly what my answer describes. He was able to convert id to string. – danish-khan-I Jan 29 '20 at 09:45
  • 1
    No, type casting is an **operation** converting an expression from one type to another. It happens at runtime. You are describing **declaring a property's type**. Not an operation but a declaration. It happens at compile time. This is not type casting. You either misunderstood the question, and/or the concepts. – yivi Jan 29 '20 at 09:47