10

I have the following function:

function array_duplicates($array)
{
    $duplicates = array();
    $unique = array_unique($array);
    for ($i = 0; $i < count($array); $i++) {
        if (!array_key_exists($i, $unique)) {
            $duplicates[] = $array[$i];
        }   
    }   
    return $duplicates;
}

This function obviously doesn't apply to any certain model, and it's not a template helper. Where would be the appropriate place to put this function? (Please don't say "anywhere you want.")

Jason Swett
  • 43,526
  • 67
  • 220
  • 351
  • 1
    I am not familiar with sympfony so I can't answer your question butI can say if you have performance issues with this project this method will be one of the bottlenecks. In your for loop you calculate array length on every iteration that's quite heavy process. You need to pre-calculate it previously and use variable in loop. BTW, in most cases `foreach` loop is slightly faster than `for`. – Leri Oct 04 '12 at 17:46
  • @PLB While it is always good to precompute the length of the array, it's a stretch to say that this is a bottleneck. There are no queries (or other typically slow operations) in the loop for one; and you also don't know the size of the array. It could be an array with 10 or so elements, in which case it's not going to take long to run even if it is recomputing the length of the array every iteration. – Paul Oct 04 '12 at 17:57
  • @ascii-lime When you are in a process of creating project that will be released you should create as flexible code as possible. You don't know when you'll need to re-factor your code. And for performance every ms counts. I won't go for performance at first stages of development if it "hurts" code readability but otherwise you should do your best to avoid potential bottlenecks like this one. Shortly, when you can write better code, write it, IMO. – Leri Oct 04 '12 at 18:23
  • http://programmers.stackexchange.com/a/80092/9971 – Jason Swett Oct 04 '12 at 18:35

2 Answers2

15

This might be the type of thing you'd put into a service. Create a class like this:

class ArrayUtils
{
    function array_duplicates($array)
    {
        ... 
        return $duplicates;
    }
}

And then define it as a service. If you're using YAML, you'd put something like this into your config.yml file:

services:
    arrayUtils:
        class:        Full\Path\To\ArrayUtils

Under this configuration, Symfony will create a single instance of your ArrayUtils, and give all your controllers access to it. Then you can call it like this:

class SomeController
{
    public function someAction()
    {
        ...
        $duplicates = $this->get("arrayUtils")->array_duplicates($array);
        ...
    }
}

This is all part of Symfony's dependency injection framework. It's pretty cool, and I recommend reading up on it here: http://symfony.com/doc/2.0/book/service_container.html

Alternative Option

Now, that might be a little overkill for such a small chunk of code. If you're only going to be using this in a single bundle, then you might want to just put it into a base controller, and have all your other controllers extend that base controller.

class BaseController
{
    function array_duplicates($array)
    {
        ...
    }
}

class SomeController extends BaseController
{
    function someAction()
    {
        $this->array_duplicates($array);
    }
}
Thomas Kelley
  • 10,187
  • 1
  • 36
  • 43
  • Where on the filesystem would I put the code in your first suggestion? – Jason Swett Oct 04 '12 at 18:32
  • Or, to word that differently, where within the project's directories would I put that code? – Jason Swett Oct 04 '12 at 18:33
  • Well, the real answer is: wherever you want. To simplify things though, I always keep a directory under my bundle directory called "Service", and put all my services there. So the class would be something like: \SomeBundle\Service\ArrayUtils. – Thomas Kelley Oct 04 '12 at 18:43
  • Thanks. What makes this more challenging is that I need to use `array_duplicates()` in an entity, and evidently you can't get to services from entities. So I have to pass an `ArrayUtils` instance through to the entity that uses that function? If so, that seems lame. That's another issue, though, I guess. – Jason Swett Oct 04 '12 at 18:55
  • Will it _only_ be used in your entities? If so, then instead of my second option of extending a base controller, you might consider extending a base entity... Put the method into the base entity, and you'll have access to that method from any entity that extends it. – Thomas Kelley Oct 04 '12 at 19:03
  • 1
    Probably, but that feels like a hack. This array util doesn't have anything to do with entities. – Jason Swett Oct 04 '12 at 19:26
3

By convention, utility classes go under the Util namespace.

If you use bundles, a class would go into the YourBundle\Util namespace. If you don't, it would go into the Acme\Util namespace — the src/Acme/Util folder.

Community
  • 1
  • 1
Elnur Abdurrakhimov
  • 44,533
  • 10
  • 148
  • 133