use arrays more sparingly in 2.0

A colleague of mine gave a presentation today, comparing some aspects of Yii and PHP to Rails and Ruby - that and some other array-related explorations with PHP of late, got me thinking about the convention of using arrays for pretty much anything.

Somebody mentioned the issue in this thread, but I felt the topic deserves a dedicated thread.

Arrays should be used only when it makes sense - for instance, it’s great to use array for lazy initialization of behaviors, application-components, etc.

It’s not so great to use arrays everywhere else though.

For one, arrays do not provide any kind of type-checks or property checks, in IDEs, or at run-time - at least not in good time.

For another, array-manipulation is not very convenient in PHP - as my colleague pointed out, when defining additional filters in a controller sub-class, it gets really ugly and tedious:


public function filters()

{

  return array_merge(parent::filters(), array(

    array('another_filter'),

  ));

}

In addition to being inconvenient and ugly, it’s also not very flexible - as he pointed out, what if I need this or that filter added specifically before or after the filters defined by the parent class, it gets even more clunky.

Lastly, there are performance-related issues with arrays. Arrays, when passed as arguments and modified, get copied in-memory. And also, in PHP 5.4, class-properties have been optimized, so that the property-names are not copied to every instance of a class - rather, PHP now maintains a shared property-table for all instances, meaning less memory and CPU overhead for all the property-name duplicates in previous versions.

It would be much more convenient and safer to have something like this:


public function init()

{

  parent::init();


  $this->appendFilter(new ThisFilter('x', 'y', 'z'));

  $this->prependFilter(new ThatFilter('a', 'b', 'c'));

}

For controllers, things like actions, access-rules and filters, these could be much more conveniently (and more safely) in the init() method, constructing objects and calling methods to register them.

For models, things like attribute metadata (names and labels), validations, relations, etc. could all be created directly and added via method-calls.

After all, if you load a controller or model, it’s probably because you’re about to use it, so there’s not much point in delaying or abstracting the construction of dependent objects.

Even if the delaying the initialization of validations and relations does make sense for performance reasons, it would still be safer to construct actual objects in the validations() and relations() callbacks.

On a related note, since PHP 5.3, we now have closures - which can be used for lazy instantiation, providing type-sensitivity in IDEs, and avoiding arrays. This could be useful e.g. for application components, since the configuration can now consist of actual code, not only setting properties on the constructed components, but calling methods on them, firing events, and so on.

Just some thoughts that were going through my head today.

I agree with using arrays in less places too, for the reason my IDE will pick up the class and it’s properties in its auto complete so I don’t have to run to the documentation as much.

+1

I am not a big fan of typing so many array literals and I think objects might often be easier.

Even in the case of application config arrays are a pest. I need different configs for console, development, unit test, system test and production.

But on one point, I have to ask…

I thought PHP’s fancy copy-on-write made passing arrays as argument quite efficient, so long as the function doesn’t change it.

http://www.research.ibm.com/trl/people/mich/pub/200901_popl2009phpsem.pdf

Hi,

While I agree with your general thoughts on arrays I don’t like a syntax like this. It feels to me very javaish. On top of it I will have to memorize specific functions for generic things, like appending a filter appendFilter/prependFilter then appending a rule or something. I’d rather use the good old array_merge for everything instead.

So is -1 from me.

+1

However, action filters should get removed http://www.yiiframework.com/forum/index.php/topic/31466-action-filter-vs-behavior/

-1 from me. Arrays may be sometimes "messy", but you manitulate in any way you want to get the desired result. When you have methods - you are limited by them and if something is not in API - you have to hack it.

Maybe if this is added as an addition, not the replacement, that we can live with that. Leaving the arrays will help with porting apps from 1.1 to 2.0 once it’s out.

That’s a bad thing?

Not if you use a decent IDE—part of mindplay’s argument.

If you configure an object using an array then you need to remember the names of the required properties. But with this suggestion, my IDE will prompt me. And it will know what types to expect where because Yii is so wonderfully consistent with using docblocks correctly.

You are not limited to methods. You may instantiate the object and then configure it using [font=“Lucida Console”]->[/font] to set properties. Which I think is better than setting [font=“Lucida Console”]‘propertyName’ => ‘value’[/font] pairs in an array because, as mindplay said, your IDE will autocomplete property names and check their type. That’s really useful.

(And I think it will make for tidier code, but that’s just my opinion.)

Yes it is, for me. If I wanted a javaish syntax then I’d have gone with a java framework.

Java frameworks require a JVM.

I like Yii because it already has a C#/Java taste. If you want to develop with obsolete concepts, Yii is already a wrong choice.

I agree, but this discussion shouldn’t be about Arrays versus Objects.

There are cases for arrays, and cases for objects.

There are parts in Yii1 that would be better served with objects (filters, relations, etc), and these kind of situations should be reevaluated for Yii2.

An example of what I think mindplay is advocating is Yii 1.1’s CDbCriteria.

I wish I had a similar way to specify relations, e.g. CRelation. That way extending a model and changing its relations would be much easier. It’s wicked hard as it stands.

I have a model, witch has about 15 relations defined. I truly do not want it to be defined by OOP style - array approach is FAR better in that case and it aligns much better than methods. I align my arrays in the manner when each ‘array’ defined has it’s level shifted by one tab. Methods are aligned differently and I have to say even PHPStorm fails at this task always - I have to re-align it by hand every time a method call is wrapped by IDE.

Lets say we make OOP style interface. But we still have to pass arrays to the methods to configure that damn relation. Making relation configuration by making an object like


$this->addRelation('myRelation', new Relation(self::HAS_ONE, 'ModelName', 'ref_id'));

is just unnecessary. I like Yii because it does not try to be like Java world and copy Zend Framework or Symphony 2. Really, if I want that kind of code i will switch to Symphony for that case. Arrays are easier, have less overhead and less complexity. And that’s to my liking is very good. PHP is a script language, not a compiled one. Simpler is better, keep up with the KISS.

soso is 100% correct with his remark to Java - many tend to shift things to enterprise way and make things unnecessary complex. Yii was developed for building apps easy and straight forward, balancing the things and making developers life easier. Now people want to make Yii work for projects where they should (and I have to say they MUST) choose ZF or Symphony - those are built for that kind of big serious enterprise stuff. It’s their credo. And Yii is for small-medium sized projects. You can build a big project, but in that case you start to use Gii (probably use giix at that point) full scale and pretty much you generate most of the stuff via your templates - you don’t give a damn if a relation is defined via array or object - you don’t touch that code at all.

We have a community here in Latvia of about 20-25 WEB developers and we established that for serious enterprise kind of apps everyone uses Symphony at work. And for more front-end or personal stuff every developer uses Yii at the moment - many have moved their personal or side projects to it - because it’s easier than doing them in Symphony - it’s just too big and too complex for that stuff.

Ogh, one more thing. SamDark in his presentations stated that for Yii 2.0 they compacted things and removed unnecessary entities. And now you, people, wana add more OOP. You know, only one phrase comes to mind: “Over my dead body!”. In this case it’s a figure of speech, but it illustrated the though very well.

I totally agree with psih.

Next to this, arrays are a handy way of composing an object configuration outside of the object. Using init() this is only possible if you add a lot … a whole lot of additional code.

Keeping the array() style definitions: +2

I also stand for array usage.

I have a long experience in C/C++, and also a bit of perl, Visual Basic and C#. (I don’t know Java very much …)

PHP to me has been a well-balanced creole of those languages. It’s easy to learn in its syntax, having a proper looseness on its variable types, enriched with wide varieties of libraries, and, above all, very convenient with its array. I love the practical easiness and efficiency of PHP.

IMO, Yii shares the virtue of PHP in its policy. I’m afraid going to far on strictness will harm its easiness.

It’s true that an associative array can’t be an alternative to an object. It won’t give us type hinting. But it’s a price we have to pay for another big advantage. We can spare a lot of thinking time because of the extensive and consistent use of array throughout the framework.

That part is so true. I rarely consult docs now for options to configure an object - they are, I’d say, extreemly consisten throught the framework and when I wana something additional - I have to consult the related class API reference anyway to know what values it can have and what it does exactly.

By the way - objects with dynamic properties are not fast and eat memory. And as some of you may know, in PHP 5.4 optimizations where added that drasticly reduced memory consumption for objects when their properties are defined explictly in the source code.

Here is a memory comsumption difference between 5.3 and 5.4 on my work project for the same page with same data (I used yii-debug-toolbar to get the numbers. Plus it renders quite a lot of data):

5.3: Memory Peak Usage 11,253 KB

5.4: Memory Peak Usage 7,924 KB

And that’s quite simple page with not much AR usage.

I’m looking forward to 5.4 where we can simple type [] instead of array()

That would at least solve the problem of ugliness