PHP Silex how to use recursion?

122 Views Asked by At

Here in indexAction I must call to subcat function to recursively get a list of categories and subcategories, otherwise it does not work.

Note subcat calls itself.

How can I write subcat function outside indexAction? and call it from inside IndexAction. Doing this, i can reuse subcat.

class ItemsController implements ControllerProviderInterface {
    public function connect(Application $app) {
        $controllers = $app['controllers_factory'];

        $controllers
        ->get('/', array($this, 'indexAction'))
        ->bind('items_index');

        return $controllers;
    }

    public function indexAction(Application $app) {
        $categorias = array();

        function subcat($idPadre, array & $categorias, $app) {
            $sql = 'SELECT id, categoria FROM categorias' .
                ' WHERE id_padre=' . $idPadre .
                ' ORDER BY categoria';
            $query = $app['db']->fetchAll($sql);

            foreach ($query as $valor) {
                $a = subcat($valor['id'], $categorias, $app);
                $lista[$valor['id'].'-'.$valor['categoria']] = $a;
            }

            return $lista;
        };

        $estructura = subcat(0, $categorias, $app);
        print_r($estructura);
        return '';
    }    
}
3

There are 3 best solutions below

0
On

I solved this doing the service, where $app['Categorias.lista'] contain all the categories:

$app['Categorias.idPadre'] = 0;
$app['Categorias.lista'] = '';
$app['Categorias'] = $app->share(function ($app) {
    function subcat($idPadre, $app) {
        $sql = 'SELECT id, categoria FROM categorias' .
                ' WHERE id_padre=' . $idPadre .
                ' ORDER BY categoria';
        $query = $app['db']->fetchAll($sql);

        foreach ($query as $valor) {
            $lista[$valor['id'].'-'.$valor['categoria']] = subcat($valor['id'], $app);
        }

        return $lista;
    };

    $app['Categorias.lista'] = subcat($app['Categorias.idPadre'], $app);
});

then I test it in my indexAction method:

$app['Categorias.idPadre'] = 0;
$app['Categorias'];
print_r($app['Categorias.lista']);

and print_r gives this in my example:

Array
(
    [2-capacitor] => Array
        (
            [14-ceramico] => 
            [12-electrolitico] => 
            [13-multicapa] => 
            [16-polipropileno] => 
            [15-polyester] => 
        )

    [3-circuito impreso] => 
    [4-diodo] => 
    [1-resistencia] => Array
        (
            [11-ceramica] => 
            [5-metal] => Array
                (
                    [8-1W] => 
                    [9-2W] => 
                    [10-3W] => 
                    [7-mini] => 
                )

        )

    [20-teclado] => 
    [21-transformador] => 
    [17-transistor] => Array
        (
            [18-bipolar] => 
            [19-mosfet] => 
        )

)
0
On

You could register your reusable code as a service. You should find anything you need here: LINK

3
On

All you have to do is make your inner function a private function in your ItemsController.

class ItemsController implements ControllerProviderInterface {
    public function connect(Application $app) {
        $controllers = $app['controllers_factory'];

        $controllers
        ->get('/', array($this, 'indexAction'))
        ->bind('items_index');

        return $controllers;
    }

    public function indexAction(Application $app) {
        $categorias = array();

        $estructura = $this->subcat(0, $categorias, $app);
        print_r($estructura);
        return '';
    }

    private function subcat($idPadre, array & $categorias, $app) {
        $sql = 'SELECT id, categoria FROM categorias' .
            ' WHERE id_padre=' . $idPadre .
            ' ORDER BY categoria';
        $query = $app['db']->fetchAll($sql);

        foreach ($query as $valor) {
            $a = $this->subcat($valor['id'], $categorias, $app);
            $lista[$valor['id'].'-'.$valor['categoria']] = $a;
        }

        return $lista;
    }
}