zend-frameworkzend-framework3zend-view

How to sort a view easily


I'd like to sort my tablebased view in Zend 3.

Here is part of my viewscript:

<table class="table">
<tr>
    <th>id</th>
    <th>cccid</th>
    <th>gesch id</th>
    <th><a href="<?= $this->url('mandant',array('query' => array('sort' => 'desc'))); ?>">Name</a> </th>
    <th>langname</th>
    <th>&nbsp;</th>
</tr>


<?php 

foreach ($mandants as $mandant) : 
    //  $unit=$units->fetchAllP($project->ProjectID);
//var_dump(get_object_vars($project));?>
     <tr>
         <td><?= $this->escapeHtml($mandant->id)?></td>
         <td><?= $this->escapeHtml($mandant->cccid) ?></td>
         <td><?= $this->escapeHtml($mandant->geschid) ?></td>
         <td><?= $this->escapeHtml($mandant->name) ?></td>
         <td><?= $this->escapeHtml($mandant->langname) ?></td>
        <td>
            <a href="<?= $this->url('mandant', ['action' => 'show', 'id' => $mandant->id]) ?>">Show</a> 
            <a href="<?= $this->url('mandant', ['action' => 'edit', 'id' => $mandant->id]) ?>">Edit</a> 

        </td>
    </tr>
<?php endforeach; ?>
</table>

I'd to click the columnnames to sort the hole table. Like I click of name and the view ist sorted by name.

As you can see there is the rest of trying a bit. Is there anyway a possibility in the view or do I need a controlleraction? I really would like to do it in zend not with ajax or other.

How to do it properly?

****EDIT 1

I tried a bit further and created an action sortAction which returns a new Viewmodel:

        return new ViewModel([
        'mandants' => $this->mandantTable->sortMandant(0,0),
    ]);

This works of course but a also need a new viewscript and the given parameters to the called modelfunction pick the field which is sorted by. Second parameter gives asc or desc.

I really would appreciate to learn something about how to do it properly, like best practise.


Solution

  • The following code examples are written without testing. This should never be used in production. It 's just a push in the right direction.

    Query Parameters in the Controller

    Without touching the routing für your controller, query parameters are the easier way to get your issue solved.

    YourController extends AbstractActionController
    {
        protected $tableGateway;
        ...
        public function sortAction()
        {
             // contains the db field, which should the result sorted by or an empty string
             $sort = $this->params()->fromQuery('sort', '');
    
             // contains the sort direction the db query should ordered by (asc or desc)
             $direction = $this->params()->fromQuery('order', '');
    
             // executes sql query with the given parameters
             $result = $this->tableGateway->getSortedResult($sort, $direction);
    
             // return result to the view
             return new ViewModel([
                 'result' => $result,
             ]);
        }
        ...
    }
    

    For safety reasons you should filter or validate your query parameters before you transfer it to your table gateway function.

    The Table Gateway with variable sort order

    The table gateway function getSortedResult should take two parameters $sort and $direction.

    class YourTableGateway extends TableGateway
    {
        ...
        public function getSortedResult(string $sort, string $direction) : ResultSet
        {
            $select = $this->getSql()->select();
            $select->columns([
                'column_a',
                'column_b',
                'column_c',
            ]);
            $select->order($sort . ' ' . $direction);
    
            $resultset = $this->selectWith($select);
    
            return $restulset;
        }
        ...
    }
    

    As you can see the given parameters are directly inserted into the order function of your select statement. Please do not take this for production! Always check this parameters for fieldnames, that are in your table and directions ASC and DESC to avoid SQL injection!

    The changes in your view

    You have to set a link in your table head with query parameters.

    <thead>
        <tr>
            <th><a href="<?= $this->url('name', [ 'action' => 'show', 'id' => 1 ], [ 'query' => [ 'sort' => 'name', 'order' => 'ASC' ]]); ?>">Table Headline 1</a></th>
            <th><a href="<?= $this->url('name', [ 'action' => 'show', 'id' => 1 ], [ 'query' => [ 'sort' => 'gender', 'order' => 'ASC' ]]); ?>">Table Headline 2</a></th>
        </tr>
    </thead>
    

    The url view helper takes usually three parameters whereby the last parameters are optional. The first parameter is the name of your route. The second one defines route parameters defined in your route configuration. The third parameter is for optional parameters like query params. For your query params sort and order you have to note the query key, which has an array value of the column name, that should be ordered by and as second the direction, which should be sorted by.

    Simple as pie, ha? ;)

    Conclusion

    A JavaScript solution would be more performant, because you don 't have to fire a request for every time you want to sort your result. That could be done by an initial request and the sorting would be done by the client. Anyway ... I think this is the JavaScript free Zend Framework only solution you wanted.