PHP OOP and callback from usort

Not for 'how-to' coding questions but PHP theory instead, this forum is here for those of us who wish to learn about design aspects of programming with PHP.

Moderator: General Moderators

Post Reply
jcobban
Forum Commoner
Posts: 41
Joined: Mon Mar 08, 2010 7:40 am

PHP OOP and callback from usort

Post by jcobban »

I have been doing OOP for over 30 years now in a wide range of languages, but in particular C++ and Java. I appreciate that the OOP features of PHP are superficial but I have encountered a situation where I am prevented from defining a class in the way that seems natural to me from my experience with other languages.

Code: Select all

    class TestClass {
	private $aField; // integer value
	function _construct($value)
	{
            $this->aField	= $value;
	}		// TestClass::_construct

	function compare($other)
	{
	    if ($other instanceof TestClass)
	    {			// comparing two instances
		return $other->afield - $this->afield;
	    }			// comparing two events
	    else
		throw new Exception("parameter is not instance of TestClass");
	}		// TestClass::compare
    }		// class TestClass

    $instances	= array(new TestClass(5),new TestClass(3));
    $sorted	= usort($instances, array($this, 'compare'));

The above of course fails because $this is not defined at the point where usort is called. However I have extensively searched the published examples and I cannot find any sample in either the PHP documentation or any of the fora which addresses this issue. The array($this, 'compare') syntax is given in many examples as a way to exploit polymorphism, but none of the examples explain the context in which this form can be used to declare a callback.

The definition of a callback function in PHP essentially precludes it being a normal class method. Yes there is a situation where you can call a normal class method from another class method, but you cannot perform a sort using a comparison method like the above from outside the class, where you do not have access to $this. Even if you do have a class method it might as well have "static" defined because the comparison method must have two parameters to define what it is comparing, it cannot, as above, compare the current instance to another instance.

I have long felt that the use of a static method indicates a poor class design because static methods defeat polymorphism.

It also seems really weird coming from any other language to see a function referred to by its character string name rather than by an object instance. To me this seems to be exposing the internal implementation of PHP in a way that should be unnecessary.

I understand that this is just the way PHP is, but I dislike being forced to add a wrapper function around a comparison method that is defined in the way that comparison methods are defined in almost every other language just to get it accepted syntactically.

Is there any forum for discussions of PHP evolution where I could discuss this issue.
User avatar
requinix
Spammer :|
Posts: 6617
Joined: Wed Oct 15, 2008 2:35 am
Location: WA, USA

Re: PHP OOP and callback from usort

Post by requinix »

It seems you're used to sorting that behaves like $a->compare($b). That's not how usort() works so of course you're having problems.

The callback to usort() is a static comparison method and receives two arguments (conventionally called $a and $b) that are the values to sort. If you want it to behave like $a->compare($b) then you need to make your callback do that:

Code: Select all

usort($instances, function(TestClass $a, TestClass $b) { return $a->compare($b); });
Note that usort() does not return an array copy. It will modify the $instances you passed to it. (If you want a copy, make a copy of $instances and sort that.)
User avatar
requinix
Spammer :|
Posts: 6617
Joined: Wed Oct 15, 2008 2:35 am
Location: WA, USA

Re: PHP OOP and callback from usort

Post by requinix »

As to the argument about how things are supposed to work,
Well that's just, like, your opinion, man.
PHP is primarily procedural. That's how it is and that's very unlikely to change. There's nothing stopping you from implementing things the way you like: make a class representing a collection and provide a method to sort it. You can make sure all items in the collection implement a "Comparable" interface which defines a "compare" method, then call that during the sort.

It's a different language. It doesn't work like Java or C/C++ or C# or Python or any other language. You might as well complain that German has masculine and feminine words because you're used to English not doing that.
jkon
Forum Newbie
Posts: 16
Joined: Mon Feb 15, 2010 6:01 am

Re: PHP OOP and callback from usort

Post by jkon »

PHP is not “primary procedural” PHP is a multi paradigm language , that most write PHP in primary procedural way even if they use classes is a fact , but this has nothing to do with the language itself. I am writing strictly OOP PHP many years now. As requinix mentioned use type hinting not evaluation , compare method of TestClass can take only a TestClass object so we have
public function compare(TestClass $testObj)
{

}

also don't mix the PHP functions for arrays with objects , (objects lists are exception to that but again if implements IteratorAggregate interface). I can't understand what you are trying to do with “usort($instances, array($this, 'compare'));” and do you believe polymorphisms is in this example.
User avatar
requinix
Spammer :|
Posts: 6617
Joined: Wed Oct 15, 2008 2:35 am
Location: WA, USA

Re: PHP OOP and callback from usort

Post by requinix »

jkon wrote:PHP is not “primary procedural” PHP is a multi paradigm language , that most write PHP in primary procedural way even if they use classes is a fact , but this has nothing to do with the language itself.
Strings rely on string functions. There is no string class.
Numbers rely on numeric functions. There is no number class.
Arrays rely on array functions. ArrayObject exists but it's not inline with the language and you create it by passing actual arrays.
Forms rely on global variables. Cookies rely on a global variable and a setter function.

PHP has had classes since PHP 4 and they received an overhaul with PHP 5, and people are free to use them, but at its core the language itself is still procedural.
jkon
Forum Newbie
Posts: 16
Joined: Mon Feb 15, 2010 6:01 am

Re: PHP OOP and callback from usort

Post by jkon »

I agree with you ,of course, that PHP wasn't designed as an OOP language, so in its core has mixed functional and procedural programming. For example is PDO in the core of PHP those days ? Is PDO OOP ? String manipulation as you mentioned is still a thing but I can't remember when I needed a string function that my OOP wrapper couldn't provide me. Do I still use PHP functions ? Yes of course when I am writing something that is in the core (in the framework) almost never in everyday life programming. Almost 95% of a time , there other 5% that you haven't decided if that has meaning to be in a layer , so you use it and if you use it again is time to build that OOP layer. I understand that many people are programming in PHP in other ways and I am not claiming that this is the right one , but you can treat PHP as an OOP language , the language support it and can play along.
Post Reply