Skip to content

Array sorting by object property or array index#535

Closed
inmarelibero wants to merge 3 commits into
twigphp:masterfrom
inmarelibero:master
Closed

Array sorting by object property or array index#535
inmarelibero wants to merge 3 commits into
twigphp:masterfrom
inmarelibero:master

Conversation

@inmarelibero

Copy link
Copy Markdown

Let's put I have an array of Author objects (id, firstname, lastname), or an array of arrays like:

[
    {'firstname': 'Woody', 'lastname': 'Allen'},
    {'firstname': 'Wayne', 'lastname': 'Coover'},
    ...
]

and I want to sort them by "lastname" object attribute or array index.

This pull request aims to improve the twig_sort_filter() function, allowing it to accept the attribute of an object or the index of an array a user wants to order an array with.
It can also sort hybrid arrays.

So then a user can use the Twig sort() function like:

{% for entity in authors | sort('firstname') %}
    {{ entity.firstname }} {{ entity.lastname }} 
{% endfor %}

and for case sensitive comparation:

{% for entity in authors | sort('firstname', false) %}
    {{ entity.firstname }} {{ entity.lastname }} 
{% endfor %}

Comment thread lib/Twig/Extension/Core.php Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice feature. But closure breaks compability with PHP 5.2 wich supported by twig

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, I didn't realize that.

in that case I could build an array before calling the uasort() function.

calling

uasort($tempArray, 'twig_sort_filter_custom_compare')

should not break php5.2 compatibility, right?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, this is correct

@nikic

nikic commented Nov 26, 2011

Copy link
Copy Markdown
Contributor

Alternatively we could think about getting closures / lambdas in Twig.

@stof

stof commented Nov 26, 2011

Copy link
Copy Markdown
Member

@nikic you mean closures defined in the template ? Please don't do that. Twig is a templating engine, not a new programming language.

@inmarelibero

Copy link
Copy Markdown
Author

every @stof code remark is right, thanks!

If you agree, I could prepare a new PR based on @stof and @Koc observations.

This could be the plan:

  • leaving the twig_sort_filter() as it was before
  • adding a new function called twig_sort_filter_by_attribute() which implements the functionality I'm proposing

this would add a new filter in the Twig core.

So it is necessary to find the name of the new Twig function and the new function declared in Core.php

The twig function name could be:

{{ uasort(array) }}

because implements the uasort function of PHP as sort Twig function implements the sort PHP function

and the function declared in Core.php could be:

function twig_sort_filter_by_attribute($array, $attribute = null, $case_insensitive = true)

even if I'm not so happy with the names. anyway they could be changed in any time before merge

@stof

stof commented Nov 26, 2011

Copy link
Copy Markdown
Member

@inmarelibero no need for a new PR. Simply push to the same branch to update this one.

@inmarelibero

Copy link
Copy Markdown
Author

ah, great. as you see I'm learning right now many things

proposed a different implementation of the sorting mechanism
Comment thread lib/Twig/Extension/Core.php Outdated

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see a problem here: if an object field name contains underscores, dashed etc.. the getter could not work correctly.

would be nice something like:

$getter = preg_replace("/[^a-zA-Z0-9]/", "", "get".$attribute);

?

Comment thread lib/Twig/Extension/Core.php Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the types should be string and boolean here

twig_sort_by_attribute_filter

added $options to function declaration

added support to ArrayAccess
@fabpot

fabpot commented Dec 3, 2011

Copy link
Copy Markdown
Contributor

That's not something that belongs to the core for many reasons.

First, it is slow and uses a lot memory for big arrays. Then, the code will never be generic enough: it contains some assumptions (like the getter to use for object) or the fact that it does not work with object properties. Implementing something generic would need many more arguments and will become quite complex pretty fast.

@fabpot fabpot closed this Dec 3, 2011
@inmarelibero

Copy link
Copy Markdown
Author

Using a lot of memory for big arrays is independent on being in the core or not. Of course if someone proposes a better way to sort an array, he's welcome.

About the generic code it could be reached in two ways:

  1. considering issue Move method Twig_Template::getAttribute to function #536 opened by @Koc

  2. adding the support for:

[object]->[$attribute]

[object->[$attribute]()

[object]->is[$attribute]

these pattern is already implemented in Template.php, and here are too complex? Which are the additional arguments needed?

Surely the best way would be having available the function getAttribute in some way.

I disagree this is not an important functionality, personally I some times needed to sort an array based on an attribute in the template, and had to write much code in twig to achieve that. I don't know how many people encountered this problem. I hope you reconsider that.
Anyway thanks to everyone for contributing to this

@stof

stof commented Dec 3, 2011

Copy link
Copy Markdown
Member

Le 03/12/2011 12:11, inmarelibero a écrit :

Using a lot of memory for big arrays is independent on being in the core or not. Of course if someone proposes a better way to sort an array, he's welcome.
Twig wants to be fast and efficient. So a filter having bad performances
is a bad candidate to be included in the core.
Of course it is not more efficient when being in an extension, but it is
not part of Twig itself anymore.

Christophe | Stof

@inmarelibero

Copy link
Copy Markdown
Author

just to say to all interested people I'm moving all this to twig-Extensions, preparing a pull request.

here is the link: https://github.com/inmarelibero/Twig-extensions

fabpot added a commit that referenced this pull request May 27, 2026
…`join`/`replace` filters and the `in`/`not in` operators (fabpot)

This PR was squashed before being merged into the twig-3.x branch.

Discussion
----------

Fix sandbox `__toString` bypasses via `Traversable` in `join`/`replace` filters and the `in`/`not in` operators

Fixes #512

Commits
-------

e3f6665 Fix deprecation notices in tests
475fb69 Guard sandbox `__toString` walker against self-referencing iterables
e9e818c Fix sandbox `__toString` bypass via `Stringable` + `Traversable` containers
8d6af07 Fix sandbox `__toString` bypass via the `in` and `not in` operators
cc1e21a Fix sandbox __toString bypass via Traversable in join/replace filters
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

5 participants