Arrays of Objects and __get: Friends Forever

In PHP, an object is always passed around as a reference, which allows one to deal with objects in a very transparent manner, since the only way to deal with a by-value copy instead of the real deal is to explicitly use the clone operator. Recently, I came upon a situation in which it was very useful for me to have an array of objects inside an object; the scenario was somewhat simple, a parent object can contain an indefinite number of children, and in order to have easy access to them I created a lazy loading property to contain them all as an array, indexed by their unique IDs. Of course, setting the stage for that is a bit more complicated than is needed for this example, so here is an extremely minimal example:

class foo {
	private $bar = array();
 
	public function __construct() {
		$this->bar[0] = new stdClass;
	}
 
	public function __get($n) {
		return $this->bar;
	}
}

So now we have a simple object with an array whose single element is an instance of PHP’s default object, stdClass. In reality you’d likely have more than just one element to the array, but it’s not necessary here to prove the point. Now, since objects are always returned by reference, accessing the first index of the array returned by __get when you try to access any member will allow you unfettered access to the contents of the object, to do with what you will (or rather, what the object will allow you to do).

With that in mind, let’s examine this:

$foo = new foo;
$foo->bar[0]->baz = 'I am a test';

This code is pretty easy to follow, and in fact does exactly what you’d expect: the stdClass object sitting in the first element of the “bar” array has a new member, “baz”, defined and assigned. Viewing the contents of the object will show that this is exactly what happened:

  ["bar":"foo":private]=> {
  array(1) {
    [0]=>
    object(stdClass)#2 (1) {
      ["baz"]=>
      string(11) "I am a test"
    }
  }
}

However, there’s a problem. Somewhere along the line, we generated a notice:

Notice: Indirect modification of overloaded property foo::$bar has no effect in …

While the notice certainly won’t halt the script’s execution, and the expected (and desired) action has taken place with no other apparent side effects, we are left with the conundrum of what to do with this notice (Note: While this issue has been brought to the attention of the PHP team, no word of a fix has yet surfaced). Since I am a firm believer that Notices and Warnings are potentially more dangerous than Fatal Errors, I won’t simply turn off error reporting; indeed, since the errors are still raised that doesn’t completely fix the small performance hit of generating the error, either.

In order to address this issue, it is important to understand what the notice is trying to tell us.  Once upon a time, __get was a return-by-reference function by default.  Of course, this doesn’t really help with wanting to prevent the modification of an object’s internal data, so __get was corrected to always return by value; in fact, even objects are “returned by value” in this case, since the value of the member variable is being returned (which just happens to also be a reference to an object), whereas the old __get would have returned a reference to the member variable itself; while the difference may seem subtle, it is monumental.  Since this change occurred, it was important to notify coders that if they attempted to modify the contents of an array element which came from an overloaded array, this action would have no effect, as the modified element would only exist in the copy returned from __get.

Armed with this knowledge of history, we have a few obvious options for solving this problem

  1. public function & __get($n).  This will technically prevent the warning from coming up, but if you’re going to go this route you might as well just declare all your member variables as public anyway, as this is what it will effectively cause __get to do.  It opens the door to such dangerous situations as:
    $foo->bar = 3;

    That’s right, if you return by reference explicitly in __get, then you will circumvent any rules you’ve set for assignment via __set. Even objects are not immune to this, as a reference to the member variable (itself containing a reference) will be returned. This option removes the efficacy of even having visibility operators for anything you intend to provide overloaded access to.

  2. Assign a variable to the contents of the array element. Again, technically, this works, but it is messy, inelegant, and is nowhere near the ideal. Here are two examples:
    $bar = $foo->bar;
    $bar[0]->baz = 'This works';
    ###
    $bar = $foo->bar[0];
    $bar->baz = 'This also works';

    Again, though, this is not the clean, simple approach we were looking for to begin with.

  3. Just turn off notices. Nah, we ain’t doin’ that.

So what’s left to consider? After thinking about the problem for a little while, I realized that this problem wouldn’t even exist if I could just store the array as an object instead, but objects don’t allow numerical indices, so it would take a little jimmy-rigging to get it to work. Here was the first version:

class arrayReference {
	private $_ = array();
 
	public function __set($n, $v) {
		$this->_[$n] = $v;
	}
 
	public function __get($n) {
		if (array_key_exists($n, $this->_)) {
			return $this->_[$n];
		}
		$this->_[$n] = null;
		return $this->_[$n];
	}
 
	public function __call($n, $a) {
		if ($n == 'array') {
			return $this->_();
		}
	}
 
	public function _() {
		return $this->_;
	}
}
 
class foo {
	private $bar = null;
 
	public function __construct() {
		$this->bar = new arrayReference;
		$this->bar->{0} = new stdClass;
	}
 
	public function __get($n) {
		return $this->bar;
	}
}
 
$foo = new foo;
$foo->bar->{1} = $foo;
$foo->bar->{99} = new stdClass;
$foo->bar->{99}->baz = 33;

Which, for the adjusted syntax, actually worked out pretty well. It might take more than an instant glance from your average PHP coder for what’s going on to make sense, or even seem syntactically correct, but it certainly worked; it even allowed for loop-based iteration by doing something like so:

foreach($foo->bar->array() as $k => $v)

While that isn’t ideal, it’s fairly transparent about what it’s doing.

I wish there were a more climactic way to put this, but there isn’t: The next step involved me trying to combine the SPL’s ArrayObject built in class to allow natural array access to my wrapper class, and after a few minutes playing with my new hideous child-beast amalgamate and its Reflection, I finally settled on this for the final version of the class:

class foo {
	private $bar = null;
 
	public function __construct() {
		$this->bar = new arrayObject;
	}
 
	public function __get($n) {
		return $this->bar;
	}
}

No more messy syntax, no compromises, no hideous amalgamate beasts, and no figuring out how to mangle my behemoth class this lesson actually needed to be applied to in order to extend ArrayObject for the purposes of accessing just one property, as I saw advocated elsewhere during the googleing portion of my problem solving routine. The example I first gave? Works just fine, and no error since the property being returned is an object, not an array. Sometimes the best solution is fiendishly simple; the only real consideration I had to make here was that, in its actual application, the array in question was declared null so it could be lazy loaded, and since you can’t use the “new” keyword or even type-hinting in class member declarations, I had to be careful to make sure the lazy loading mechanism would still work, but I was never declaring a traditional array either: all in all, a 5 minute job to implement and test.

Five minutes that made the past day or so of work seem rather silly indeed.

January 11th, 2010 by Clark | Comments Off

Did You Know? Class Visibility in PHP

While it remains an imperative-style language, since version 5 PHP’s object model has gotten significantly more sophisticated. While in PHP 4 objects were little more than arrays with functions, the newer versions have most of the trimmings of modern OOP. Among those, probably considered a basic triviality at best, is member visibility. In fact, since PHP will assume that, if no visibility modifier is supplied, a method is public, it’s possible to write a class without ever thinking about its visibility.

Of course, if you’ve done anything much with OOP you can understand exactly why visibility is important, and why you’d want public-facing getters and setters to do your bidding (in most cases) instead of directly modifying members; heck, it’s about the closest we’re going to get to strong-typing in PHP. However, there is one very important “Gotcha!” in PHP’s visibility model: it is enforced at the class-level, not at the instance level.

This means, quite simply, that instances of the same class can call each other’s private/protected methods. I’m not here to decry this and tell you how to avoid it, because it’s here to stay so far as we can tell. I am here to embrace and, yes, evangelize it. Consider the case of the “User” object — that is, an object to represent the properties of a user. In most sufficiently complicated systems, a user will have to have permissions, which may even apply to different tiers of the application, or smaller object subdivisions, groups, etc – such a discussion is beyond the scope of this article – and I happen to already have just such an object in mind, as it is what is currently occupying most of my days at work.

Now, we have a user object, and somehow this object represents permissions. In my case, the user object will not always need to load its permissions to perform a task, and because of this the permissions (as well as anything else that doesn’t reside in the main table) are lazy-loaded the first time they are accessed via the getter. The block of code to do this, of course, is abstracted away, so any time I might need user permissions, I just call this:

$this->lazyLoadPermissions();

And this function, declared as private, takes care of checking to see if permissions are loaded yet, and if not, it loads them. When the user object is stored in the session at the end of the script’s execution, the permissions are not saved with the rest of the data (thank you __sleep()), and the cycle begins anew the next time I try to access this data.

So where does this neat visibility functionality come into play? One of the tasks I need to perform now and again is determining whether or not a particular user can claim “authority” over another user. Which is to say, just because I have user management privileges doesn’t mean I should be able to disable a user who is flagged as the owner of an object equal-to or higher-than my own permissions extend. So, to solve this problem, I wrote a simple function called hasAuthorityOver which accepts an instance of the user object as a parameter, and then tries to compare their permissions. Here are the first few lines:

	public function hasAuthorityOver(User_Object $subject) {
		$this->lazyLoadPermissions();
		$subject->lazyLoadPermissions();

As you can see, since the visibility is enforced at class level, and both of these objects are instances of User_Object, it is possible to call private methods on other objects, allowing you some small amount of flexibility in maintaining object integrity; of course, if you aren’t expecting this functionality, it can be jarring, but since it’s not going to change it’s worth embracing for the sake of making life easier.

Update! A new example enters the arena!

Another application of this technique might work as follows. Suppose you have an object Foo, which represents some arbitrary resource in a heirarchy, and Foo can have children which are also of type Foo. You might have something resembling this:

class Foo {
    private $children = array();
 
    public function setup(/* ... */, Foo $parent) {
        // ...
        $parent->addChild($this);
    }
 
    protected function $addChild(Foo $child) {
        // ...
    }
}

In this case, while the addChild method is hidden from public access, potential children may call their parent’s addChild method in order to add themselves in one easy step. This solves a problem of granting visibility between certain classes while still restricting it from the public scope, as you may elect to provide a “common ancestor” in order to allow objects to cross class boundaries. Food for thought!

December 3rd, 2009 by Clark | Comments Off

On Net Neutrality – A Plea

Recently, McCain introduced a bill for consideration which would effectively block the FCC’s attempts at creating so-called “Network Neutrality” rules which ISPs and Telcos would be required to follow.  Now, setting aside for a moment the fact that McCain has received more than double as much money as the next-highest senator to be bankrolled by the Telco/ISP industry, and the comments made by leading nutjob crazy-person and all-around internet expert Glenn Beck, I’d like to first offer an explanation of what’s at stake here for those who don’t really understand the nuts-and-bolts of how the internet works.

I am going to use a very general analogy for how the internet works: a city.  Now, the city that is the internet is a very strange city indeed.  This city isn’t owned by any single country or government.  Just about anyone can come and go as they please.  Now, this city has three basic pieces, and they way they blend isn’t that different from how any city works:  you have content “Servers,” content “Consumers,” and a transit system.  The Servers could be anything from a tent someone just set up for a while to a huge mall, or a towering building, but it is basically somewhere you can get some content.  In Internet City, just about anybody can become a Server.  Then, there are the Consumers.  This is probably where you fit in to Internet City — when you use the internet, you are at home, or at work, or on your phone, but you are mostly-if-not-exclusively retrieving content from these Servers (this includes posting on social media sites, such as Twitter, Facebook, MySpace, et al).

The third part of the city is the transit system, which is your ISP.  At the top of the chain are the people who make all the roads, the asphalt, the car you will drive around the internet city, and pretty much everything you will need to get from point A to point ∞.  These are the Tier-1 Network Providers (and to some extent the larger Tier-2 providers, but this discussion is beyond the scope of this analogy); they are few, and they are powerful.  Of course, they generally don’t personally make every single road; who handles the road from there just depends on where it leads, who is willing to go there, and what services they intend to offer.  These are the Tier-2 and Tier3 Networks, and they are probably more familiar to you.

Now, how fast you can get somewhere depends on three things: What kind of car you bought (your specific internet package), what kind of road the journey takes (the quality of ALL the connections from you to your destination, and back), and how far you have to go.  If you have a mac-daddy broadband connection, and you are accessing a major site (major news networks, etc), you’ll spend most of your time on the metaphorical highway, and should get your data rather quickly, and the inverse is true as well.  Any further delving into how this works is also beyond the scope of this analogy, but you get the idea.

So what is Net(work) Neutrality?  The idea is that no matter from where or whom traffic comes, ISPs may not give preferential treatment to it.  As fast as the hardware will carry it must it go.  Groups and people who support this include small ISPs, who don’t want their customers to get abused by the larger and higher-tier internet providers, as well as Tim Berners-Lee, a man whom you may not have heard of but whom you are in contact with right now, as he practically invented the “World Wide Web” we have come to know.  Opposing this is the idea that an ISP should be allowed to decide to give (at their own, private, and in this writer’s opinion, dubious, whim) preferential treatment to some data, at the expense of other data.  On the relatively mild side of the spectrum, they could choose to allocate their network resources in such a way that, for example, their particular VoIP service received preference over competitors such as Vonage and Skype.  This is mild, and arguably benign in the grand scheme of things (so long as they advantage isn’t dialed to extreme levels, to the point that it is a detriment to competitors), and not what the issue is about.  Given total freedom of how data flows, they could route traffic in such a way that their own VoIP service takes precedence over their competitor’s VoIP service — they could even extort a fee to avoid this sort of “traffic shaping” — all without the consumer being able to defend against this action.  The customer would then be nearly forced to use that company’s VoIP service, or any service it chose, in order to get any semblance of quality.

A real-world example would be like allowing the government to create a lane of traffic in which only USPS vehicles could travel, and then forcing UPS and FedEx to use 1-lane dirt roads instead of the highways, since they are a competing service.  Or, in the analogy of Internet City, it would be like the powers-that-be on the roads checking to see where you are going (in Internet City, you have to announce where you’re going or you can’t get there), and then forcing you to use smaller, slower roads, or yield to indefinite amounts of other traffic, based on whether or not you were going to one of their in-house holdings.  Nightmarish.

Some of the points brought up against Net Neutrality are, quite frankly, absolutely ludicrous.  As someone posted on the PC World forums:

“What this article completely fails to state (talk about one-sided reporting!) is that Google has devoted far more money to lobbying for regulation of the Internet than the telcos have to defending itself against it. Google has given hundreds of millions of dollars to slimy DC “astroturf” groups — that is, groups that pretend to be acting in the “public interest” but in fact do what their contributors tell them to do — which are lobbying for “network neutrality” legislation and regulation. And if you look at the details of all of these regulations — which start with high-minded language that talks about “freedom” and “openness” — all of them would tie the hands of ISPs and of Google’s competitors, while giving Google free rein to do whatever it wants, including to serve as an Internet gatekeeper. The regulations would also raise the price of Internet service, lower the quality of that service, and reduce consumers’ competitive choices by putting small providers out of business.

Remember: corporations don’t act out of the goodness of their hearts. Monopolist Google wouldn’t be doing this if it weren’t seeking to maximize its profits at the expense of consumers. So, remember: “network neutrality” isn’t neutral. It is Google’s corporate agenda, and it strongly favors Google.”

Wow, that is a lot of Big Brother Meets Google conspiracy theorizing (Ballmer, is that you?)! Aside from that, the points this person raises are thus:

  1. It will raise the price of internet service. How, exactly? One of the possibilities is that, after some time (maybe a few years) of ISPs shaping traffic however they please, they will offer a new “unshaped” plan for only $20.00 more per month, thereby allowing them to charge you more for the same service you’re getting at the time this article was written. However, if we are given true Net Neutrality, there is no reason for the price to go up (other than inflation, which doesn’t count). After all, if nothing changes, then there’s no new way to sell us back what we’re already getting.
  2. It would lower the quality of internet service. Again, how? If you think that internet service means that all you do all day is browse your ISPs website and use their video service, their email service, their phone service, and so on, then maybe it would “lower” the quality from the standpoint that it would not be “increasing” the quality, which as previously mentioned would be at the expense of everyone else. Quality won’t degrade because we didn’t decide to let the ISPs tell us what is more valuable. To re-iterate the point, Net Neutrality basically means nothing changes.
  3. It will reduce consumers’ competitive choices by putting small providers out of business. No, just no. Small ISPs in Canada came out strongly in favor of Net Neutrality before such legislation was passed anyway.  The larger wholesale (Tier-2) internet providers were shaping bandwidth to the point that it affected large numbers of users of the smaller Tier-3 providers, and the small providers resisted, but at the end of the day they are buying internet (albeit in larger increments than you or I) from the Tier-1 providers, and they are the ones against Net Neutrality.  Funny how the exact people who are against neutrality are feeding you the exact opposite of truth about what will happen to the “competition.”  And, to round out this bullet point, Tier-1 providers who are going to bat on this one (AT&T, Cogent, et al) just don’t care what the little guys are doing: they have the pipes in the middle, and everyone else needs them.

Of course, these are just the arguments on Net Neutrality that actually have something to do with the subject at hand!  Then there are the downright lies spread by, among others, Glenn Beck, such as:

  1. Net Neutrality will bring the Fairness Doctrine to the internet, resulting in government censorship/control of the content on the internet. It is extremely important to remember that, above all, the Internet does not exist solely in America.  The internet is no longer any more an American thing than it is a Russian thing or any other location-based thing.  The internet is vast, it is (from the point of view of the average user) limitless, and no one country owns it.  America could try to censor the content located in America.  America might even try to create treaties with other nations to control what is hosted in their countries.  However, all this will do is open up a market for “regulation-free” hosts, in countries who wouldn’t sign any such treaty (maybe a nice time to wire-up some third-world African nations?), or something else like it.  Let me, again, put this in the simplest terms possible: NO SINGLE COUNTRY CAN CONTROL THE CONTENT OF THE INTERNET.  IN ALL LIKELIHOOD, NO COMBINATION OF COUNTRIES CAN CONTROL THE CONTENT OF THE INTERNET.The internet is not just one person, one company, or one country.

    And to think, I said all of that without even mentioning that NET NEUTRALITY DOES NOT IN ANY WAY, SHAPE OR FORM REFERENCE OR ATTEMPT TO INSTITUTE ANY SORT OF FAIRNESS DOCTRINE. This argument would be laughable if it weren’t given so much credence by lying morons like Glenn Beck who, like McCain (from whom I respectfully withhold the indictment of “lying moron”), really don’t know the first thing about the technology they are so passionately speaking about, and the credence it will be given by the people that listen to and trust them.  This issue is a Red Herring.
  2. The government will be stepping in as a watchdog of the internet. No, the government would simply be stepping in to maintain the status quo so that Tier-1 providers don’t start exploiting their customers in unfair ways. Everybody, whether Servers or Consumers, pays for the “pipes in the middle” that is the transit system — why does the transit system then get to start deciding at what speed or priority I get to receive the content I’ve payed them good money to get?  This issue is a misunderstanding.
  3. Net Neutrality is a ploy by left-wing liberals to socialize internet access. I don’t even have a diatribe for this one, I’ll just rest on saying that no, it’s not in the bill, it’s not on the table, no. Prominent liberals, such as “Van” Jones, have spoken about how we should be giving broadband access, for free, to everyone, like they do in some other countries, but this is a separate goal from the standpoints of the technology, the FCC, and the implementation, as well as the bill that is on the table.  These views are not encompassed by Net Neutrality, but are in fact a Red Herring.
  4. Revolution!  Marxism!  Destroying Capitalism!  Rabble rabble! It is important to remember that you can hire someone to kill someone else, but this is considered an unfair, immoral, and reprehensible business practice and thus it is forbidden.  Regulations on how you can do business with respect to, quite frankly, not just plain crapping all over the environment, the public, and your own consumers, are commonplace in our legal system; you really, really wouldn’t want to live in a world where companies could do whatever they wanted any time as long as it turned a buck.  And as for all the talks of people somehow magically using Net Neutrality for revolutionary and/or Marxist goals?  These are, you guessed it, Red Herrings!  And a special breed of Ad Hominem Red Herrings at that!  In fact, given the blatantly untrue and often unfounded accusations that Beck has made against his opponents, I’d say this also qualifies as a Straw Man Fallacy.
  5. The government will be controlling content. No, see argument 1.
  6. The internet won’t work as well, things will load slowly, etc. The reason given here is/was that there won’t be enough competition and so on.  Again, Network Neutrality advocates the status quo — that is, just because you have the traffic before you sell it doesn’t mean you can decide how it’s used once you’ve sold it to me.  This is an Outright Lie.
  7. Net Neutrality does not help innovate business. You’re right, it doesn’t. It protects the little guy from having big businesses “innovate” more money out of his wallet. Next.
  8. The government will take over the internet. Again, see argument 1 — the American government can no more regulate the internet than it can nail Jell-O to a tree.  The long and the short of it is that, even if the government suddenly decided it wanted to own all hosting services (remember, content is DISTINCT from transport), anyone can set up a server on any computer connected to the internet, and suddenly they are content providers.  The internet is a vast, untamed, wild environment.  THE GOVERNMENT CANNOT CONTROL IT.

Mark Lloyd said something very important that bears quoting:

“Unfortunately, the powerful cable and telecom industry doesn’t value the Internet for its public interest benefits. Instead, these companies too often believe that to safeguard their profits … they must control what content you see and how you get it. Their plans could have dire consequences for those whose voices are often marginalized by our nation’s media system.” -Mark Lloyd, Federal Communications Commission.

Beck’s guest then attacked him, specifically saying “they turn things inside out,” then going on to imply that Lloyd wanted to use Net Neutrality as a means to Government Control and a re-introduction of the fairness doctrine, and that he would use this new government brand internet to give voices to the “marginalized people” a la the fairness doctrine. He not only completely misconstrued (I’d say misunderstood except I believe that he is an evil little man) the quote but, in fact, turned it as inside out as he claimed the Net Neutrality proponents are doing.

TL;DR Net Neutrality, though technically regulation, is very mild and serves only to prevent the ISPs and Telecoms from regulating how the traffic you pay for gets shaped; it provides no slippery slope nor sets any precedent for the government to control the internet. Supporting Net Neutrality (and opposing Sen. McCain’s bill) is supporting the status quo, and supporting the rights of the consumer. The government cannot, and will not, control the content of the internet; not only is not that even on the table here, it is fundamentally impossible, and outside the scope of even the FCC. Before you overreact, learn what’s actually going on. Please.

P.S., for another well-thought-ought viewpoint on net neutrality, check out this post on Brad Ideas.  He believes that we don’t need to codify Net Neutrality into law, but I think he would also support the not coding into law of the exact opposite.  I disagree with him, and think that we should make it law, if only because this is the second time that opposition has arisen loudly in government, but his opinion is worth reading nonetheless.

Additional Link: http://www.ethioplanet.com/news/2009/10/25/google-verizon-join-forces-to-support-net-neutrality/

October 25th, 2009 by Clark | Comments Off

Blankets – Nature’s Simple Truths

Just as a quick FYI, it has come to my attention that all programming languages suck. Prolog, PL/1, Perl, C, C++, ASM, Haskell, PHP, Python, Ruby, Tcl, Java, Delphi, COBOL, FORTRAN, Pascal, Visual Basic, ASP.NET, Ocaml, C# and so on… all worthless. This comes as a huge relief.

According to further reading I’ve done, all programming languages are awesome and supreme. There’s no language as good as, apparently, every single language out there.

Except BASIC. BASIC sucks. I think we can all agree on that one. BASIC, QBASIC, whatever-BASIC — all sucks.

Oh, and I think we can also agree that the next time we hear someone refer to themselves as an HTML Programmer, we’re going to laugh heartily, right before kicking their head in.

October 9th, 2009 by Clark | Comments Off