Is it possible to overload operators in PHP?
Asked Answered
T

6

72

Specifically, I would like to create an Array class and would like to overload the [] operator.

Teddman answered 24/4, 2009 at 21:46 Comment(0)
C
56

If you are using PHP5 (and you should be), take a look at the SPL ArrayObject classes. The documentation isn't too good, but I think if you extend ArrayObject, you'd have your "fake" array.

EDIT: Here's my quick example; I'm afraid I don't have a valuable use case though:

class a extends ArrayObject {
    public function offsetSet($i, $v) {
        echo 'appending ' . $v;
        parent::offsetSet($i, $v);
    }
}

$a = new a;
$a[] = 1;
Claud answered 24/4, 2009 at 22:6 Comment(6)
Not only a helpful answer, but the right answer. I use ArrayObjects all the time, and it's an elegant way not only override arrays but to extend the whole object-model and make PHP kick some serious butt.Semivitreous
Not a helpful answer or the right answer. The question is about operator overloading, not whether or not a library with an object called ArrayObject exists.Withdrawal
-1 Use the ArrayAccess interface. Don't extend ArrayObject. You are inheriting lot's of logic you probably don't need and additionally extension of ArrayObject is unpredictable in many aspects, because there is so much magic involved.Kelleher
NikkiC, your answer is probably much better, shouldn't you add it as a real answer?Rattoon
Worth noting particularly if you need an array, rather than a hashtable, you can use SplFixedArray to give you much faster array functionality - overload it, add a private array(), and use is_numeric to decide where to store data; will give you a massive speed boost for large arrays - don't know why php doesn't do this by default!Nae
Is there any Interface allowing us to override += and use array_merge on array objects (custom or spl)? The concept of holding array data in a centralised object (being able to be referenced instead of copied) theoretically is absolutely superior and should find more application - but lacking Interfaces to abstract all aspects of array behaviour makes the Spl*-Interface ecosystem feel rather half baked...Turgor
M
30

Actually, the optimal solution is to implement the four methods of the ArrayAccess interface: http://php.net/manual/en/class.arrayaccess.php

If you would also like to use your object in the context of 'foreach', you'd have to implement the 'Iterator' interface: http://www.php.net/manual/en/class.iterator.php

Mcdermott answered 15/12, 2011 at 9:6 Comment(1)
+1. To implement the ArrayAccess interface is the ONLY valid answer to the OP's problem. All other are suboptimal.Unsociable
S
24

PHP's concept of overloading and operators (see Overloading, and Array Operators) is not like C++'s concept. I don't believe it is possible to overload operators such as +, -, [], etc.

Possible Solutions

Samadhi answered 24/4, 2009 at 22:0 Comment(1)
Better than the Iterator is the SPL ArrayObject, which I've linked to below. It provides the whole slew of array functionality.Claud
W
11

For a simple and clean solution in PHP 5.0+, you need to implements the ArrayAccess interface and override functions offsetGet, offsetSet, offsetExists and offsetUnset. You can now use the object like an array.

Example (in PHP7+):

<?php
class A implements ArrayAccess {
    private $data = [];

    public function offsetGet($offset) {
        return $this->data[$offset] ?? null;
    }

    public function offsetSet($offset, $value) {
        if ($offset === null) {
            $this->data[] = $value;
        } else {
            $this->data[$offset] = $value;
        }
    }

    public function offsetExists($offset) {
        return isset($this->data[$offset]);
    }

    public function offsetUnset($offset) {
        unset($this->data[$offset]);
    }
}

$obj = new A();
$obj[] = 'a';
$obj['k'] = 'b';
echo $obj[0], $obj['k']; // print "ab"
Wily answered 3/6, 2014 at 9:9 Comment(1)
This is the best (most accurate) answer in regard of the OP question. If you simply want to use the [] operator on your object, implementing ArrayAccess interface is the way to go.Froh
A
4

It appears not to be a feature of the language, see this bug. However, it looks like there's a package that lets you do some sort of overloading.

Aten answered 24/4, 2009 at 22:2 Comment(2)
Looking at the package, it seems to not be compatible with any php > 5.5, and hasn't been updated since 2013Nae
This answer is outdated.Justification
S
-1

Put simply, no; and I'd suggest that if you think you need C++-style overloading, you may need to rethink the solution to your problem. Or maybe consider not using PHP.

To paraphrase Jamie Zawinski, "You have a problem and think, 'I know! I'll use operator overloading!' Now you have two problems."

Shanel answered 25/4, 2009 at 2:45 Comment(9)
-1 answer is simply incorrect, as it IS possible to overload the [] operator. Additionally, its likely that @Chad is not trying to solve a problem with operator overloading, but keeping his code neat and succinct.Misunderstood
That's why I said "Put simply, no" rather than "No." I didn't want to explain that you do it by extending certain classes in weird ways, because 1) operator overloading is a bad enough idea even when the syntax for doing it is clean, and 2) the syntax for doing it in PHP isn't clean.Shanel
Need to rethink my design? So if I want to do complex arithmetic or extensive date arithmetic, I have to use function calls instead of operators? Yuck.Monogamy
I submit that date operations do not map cleanly to normal arithmetic operators. You might say, "Well when I use a + sign in a date operation, it doesn't mean addition, it means something similar but subtly different," to which I would say that using a commonly-understood operator for something different than what that operator is used for is going to primarily lead to confusion and sorrow.Shanel
@Shanel By that logic, we should have different operations for Integers and Floats. (Some languages, like OCaml IIRC, do have this, e.g. + for integer addition and +. for float addition.) My guess is you'd say that's a pain in the neck, but it simply shows there's a trade-off you're making there too, and different people simply do it to different degrees. Get off your high horse of one-true-wayism :-) Using the same operator for different purposes isn't heresy, it's practical. (Parentheses for argument lists and operator precedence?! That way lies MADNESS!)Amazing
@agnoster: The issue is context. Parentheses for argument lists and operator precedence are easily distinguished: Is there a function name at the beginning? But with using + for integer and date operations, there's no guaranteed way to tell by looking at the operands what's going to happen to the data. You have to look elsewhere to find out what data types the operands are. Now that's not exactly onerous, but it is an extra step that can lead to misunderstanding. Integers and floats behave nearly identically under addition, so that's not a great counterexample.Shanel
@Shanel Integers and Floats do not behave identically under arithmetic on a computer! 3 / 2 is not the same as 3.0 / 2.0, for starters - similarly, many properties that hold in one type don't with another. My point is not that date arithmetic is 100% a great idea. It's just that you should be aware you are probably making the same trade-offs you are arguing against, just with other data types. You can wave your hands and say "well, ints and floats are roughly the same", and I can do the same with numbers and dates (they're just integer seconds from the Epoch, right?)Amazing
Operator overloading can be abused, but so can any programming construct. Saying that operators don't tell you what will happen to the data is as true as saying functions don't tell you what will happen to the data. Guarantees don't exist for anything that is user (programmer) defined. Operators aren't always a good way to build an API, but clearly sometimes they are.Veneration
@agnoster: I said "nearly identically," not "identically." I'm aware of the differences. The point is that using + for integer addition and float addition is not likely to confuse people; it's long been well-understood what the differences are. Using + for date arithmetic is not well-understood and is likely to lead to the aforementioned confusion and sorrow. I understand there are trade-offs, but I maintain that trying to use operators on data that do not have commonly-understood semantics for that operator is just going to lead to... well, you know where. :)Shanel

© 2022 - 2024 — McMap. All rights reserved.