KoolReport's Forum

Official Support Area, Q&As, Discussions, Suggestions and Bug reports.
Forum's Guidelines

Multi Data filter: using filters within input query? #2351

Closed Niall McGuirk opened this topic on on Sep 22, 2021 - 11 comments

Niall McGuirk commented on Sep 22, 2021

I am trying to make a report using multiple inputs to filter the table, but only if they're set. I've managed to transpose my data from the example page (https://www.koolreport.com/examples/reports/advanced/multiple_data_filters/)

However, for the Tribe filter, I need to show data from in between the two dates, set in the start and end date filters above it. I'm trying to understand how to add multiple parameters to this bit of code, but I'm not sure which bit to duplicate.

")->params(
                            $this->params["years"]!=array()?
                            array(":years"=>$this->params["years"]):
                            array()

I'm also not sure that the colon array() bit on the end does, so I don't know which part I should duplicate for the other input parameters.

array(":years"=>$this->params["years"]):
                            array()

What does the :array() do?

Here us the tribe input code at the moment:

 <?php 
                    
            Select2::create(array(
                            "name"=>"select",
//                                  "dataStore"=>$this->dataStore("sales"),
                            "dataSource"=>$this->src("automaker")->query("
                            Select distinct
                             TribeName AS "Tribe Name"
                             From tbl_dealhack
                             left join tbl_dealhack_attachments on tbl_dealhack_attachments.dealhack_id = tbl_dealhack.id
                             left join tbl_profile on tbl_profile.user_id = tbl_dealhack.user_id
                             Left join tbl_attachment_type on tbl_attachment_type.id = tbl_dealhack_attachments.attachment_type_id
                             left join tbl_companytribe on tbl_companytribe.id = tbl_profile.TribeID
                             WHERE created_date BETWEEN "2020-06-04 12:47:00" AND "2021-12-21 12:00:00"
                             AND attachment_type_id = 4
//I'm trying to put created_date BETWEEN :start AND :end into the below code, so it adds the between condition if they're set                           
                            ".( $this->params["years"]!=array()?"where YEAR(orderDate) in (:years)":"")."
                            group by customerName
                        ")->params(
                            $this->params["years"]!=array()?
                            array(":years"=>$this->params["years"]):
                            array()
                        ),
                            "dataBind"=>"Tribe Name",
                            "attributes"=>array(
                                "class"=>"form-control",
                            )
                        ));

Here is the MyReport.php code

<?php
//Step 1: Load KoolReport
require_once "../../load.koolreport.php";

//Step 2: Creating Report class
class MyReport extends \koolreport\KoolReport
{
    use \koolreport\inputs\Bindable;
    use \koolreport\inputs\POSTBinding;

    protected function defaultParamValues()
    {
        $date=date_create("2021-07-16");
        date_add($date,date_interval_create_from_date_string("-42 days"));
        $sd = date_format($date,"Y-m-d");
        
        return array(
            "startDatePicker"=>date($sd . " 00:00:00"),
            "endDatePicker"=>date("Y-m-d 23:59:59"),
            "select"=>"",
            "locationSelector"=>"",
        );
        
//        return array(
//            "years"=>array(2003),
//            "customerNames"=>array(),
//            "productLines"=>array(),
//        );
    }
    
    protected function bindParamsToInputs()
    {
        return array(
            "startDatePicker",
            "endDatePicker",
            "select",
            "locationSelector",
        );
        
//        return array(
//            "years",
//            "customerNames",
//            "productLines"
//        );
    }

    protected function settings()
    {
        
        $config = include "../../config.php";
        return array(
            "dataSources"=>$config
        );
        
//        return array(
//            "dataSources"=>array(
//                "automaker"=>array(
//                    "connectionString"=>"mysql:host=localhost;dbname=automaker",
//                    "username"=>"root",
//                    "password"=>"password",
//                    "charset"=>"utf8"
//                ),
//            )
//        );
    }
    protected function setup()
    {
        $query_params = array();
        if($this->params["startDatePicker"]!=array())
        {
            $query_params[":start"] = $this->params["startDatePicker"];
            }
        if($this->params["endDatePicker"]!=array())
        {
            $query_params[":end"] = $this->params["endDatePicker"];
            }
        if($this->params["select"]!=array())
        {
            $query_params[":tribe"] = $this->params["select"];
            }
//        if($this->params["locationSelector"]!=array())
//        {
//            $query_params[":location"] = $this->params["locationSelector"];
//            }

        $this->src('dealhackdb')
        ->query("Select 
                 tbl_dealhack.id,
                 tbl_profile.user_id AS UserID,
                 hack_description AS Decription,
                 created_date AS 'Created',
                 attachment_location AS 'Attachment Location',
                 uploaded_date AS Uploaded ,
                 Company,
                 TribeName AS 'Tribe Name'
                 From tbl_dealhack
                 left join tbl_dealhack_attachments on tbl_dealhack_attachments.dealhack_id = tbl_dealhack.id
                 left join tbl_profile on tbl_profile.user_id = tbl_dealhack.user_id
                 Left join tbl_attachment_type on tbl_attachment_type.id = tbl_dealhack_attachments.attachment_type_id
                 left join tbl_companytribe on tbl_companytribe.id = tbl_profile.TribeID
                 WHERE 1=1
                 AND attachment_type_id = 4
                 
                 "
                .(($this->params["startDatePicker"]!=array())?"AND created_date BETWEEN (:start) ":"").""
                .(($this->params["endDatePicker"]!=array())?" AND (:end) ":"").""
                .(($this->params["select"]!=array())?"AND TribeName LIKE (:tribe) ":"").
                ""
                )
        ->params($query_params)
        ->pipe($this->dataStore("sales"));
        // GROUP BY year, productLine, customerName
        
        
        
//        $this->src('automaker')->query("
//            select
//                customerName,
//                productLine,
//                YEAR(orderDate) as year,
//                sum(quantityOrdered*priceEach) as amount
//            from orders
//            join customers
//            on
//                customers.customerNumber = orders.customerNumber        
//            join orderdetails
//            on orders.orderNumber = orderdetails.orderNumber
//            join products
//            on products.productCode = orderdetails.productCode
//            where 1=1
//            ".(($this->params["years"]!=array())?"and YEAR(orderDate) in (:years)":"")."
//            ".(($this->params["customerNames"]!=array())?"and customerName in (:customerNames)":"")."
//            ".(($this->params["productLines"]!=array())?"and productLine in (:productLines)":"")."    
//            GROUP BY year, productLine, customerName
//        ")
//            ->params($query_params)
//        ->pipe($this->dataStore("orders"));
    }
}

Sebastian Morales commented on Sep 23, 2021

Niall, if your input is not multiple (i.e array type) but single (i.e string or number type) don't compare it to the empty array array() but to the empty string "" or null value. Only compare inputs with array() if they are multiple select which is not the case with your "start", "end", and "select" inputs.

Niall McGuirk commented on Sep 23, 2021

So where is the comparison you're referring too? So I know for future reference, What is the syntax for comparing a string/number as oppose to an array?

>params(
                            $this->params["years"]!=array()?
                            array(":years"=>$this->params["years"]):
                            array()

or the if tree I've got:

        if($this->params["endDatePicker"]!=array())
//should this be !=""
Sebastian Morales commented on Sep 23, 2021

Instead of if ($this->params["endDatePicker"]!=array()), use if (! empty($this->params["endDatePicker"])) pls.

Niall McGuirk commented on Sep 23, 2021

I used the !empty code, and it is giving me a parameter number error:

I replaced the select condition because I want it to be used when set, but not the dates because I want them to always be used. The rest of the code is as above

protected function setup()
    {
        $query_params = array();
        if($this->params["startDatePicker"]!=array()){
            $query_params[":start"] = $this->params["startDatePicker"];
            }
        if($this->params["endDatePicker"]!=array()){
            $query_params[":end"] = $this->params["endDatePicker"];
            }
        if (! empty($this->params["select"])){
            $query_params[":tribe"] = $this->params["select"];
            }
Niall McGuirk commented on Sep 23, 2021

I solved it. The problem was I hadn't changed the section in the setup() $query, from:


                .(($this->params["select"]!=array())?"AND TribeName LIKE (:tribe) ":"").

to


                .(($this->params["select"])?"AND TribeName LIKE (:tribe) ":"").
Niall McGuirk commented on Sep 23, 2021

Hi Sebastian, in the Multiple Data Filters example the Select Product Lines input box is only assigned and used if the user assigns the value, and it also stays empty (unassigned) when the submit button is pressed.

However, my Tribe input box is assigned to London but not used, when loading the page, but is used upon pressing the submit button.

Would you know why my verion of the select is being assigned instead of staying empty, as it does on the Multiple Data Filter example? I'm not sure why its being assigned when it isn't on the example

MyReport.php

<?php
//Step 1: Load KoolReport
require_once "../../load.koolreport.php";

//Step 2: Creating Report class
class MyReport extends \koolreport\KoolReport
{
    use \koolreport\inputs\Bindable;
    use \koolreport\inputs\POSTBinding;

    protected function defaultParamValues()
    {
        $date=date_create("2021-07-16");
        date_add($date,date_interval_create_from_date_string("-42 days"));
        $sd = date_format($date,"Y-m-d");
        
        return array(
            "startDatePicker"=>date($sd . " 00:00:00"),
            "endDatePicker"=>date("Y-m-d 23:59:59"),
            "select"=>"",
            "locationSelector"=>"",
        );
        
//        return array(
//            "years"=>array(2003),
//            "customerNames"=>array(),
//            "productLines"=>array(),
//        );
    }
    
    protected function bindParamsToInputs()
    {
        return array(
            "startDatePicker",
            "endDatePicker",
            "select",
            "locationSelector",
        );
        
//        return array(
//            "years",
//            "customerNames",
//            "productLines"
//        );
    }

    protected function settings()
    {
        
        $config = include "../../config.php";
        return array(
            "dataSources"=>$config
        );
        

    }
    protected function setup()
    {
        $query_params = array();
        if($this->params["startDatePicker"]!=array()){
            $query_params[":start"] = $this->params["startDatePicker"];
            }
        if($this->params["endDatePicker"]!=array()){
            $query_params[":end"] = $this->params["endDatePicker"];
            }
        if (! empty($this->params["select"])){
            $query_params[":tribe"] = $this->params["select"];
            }

        $this->src('dealhackdb')
        ->query("Select 
                 tbl_dealhack.id,
                 tbl_profile.user_id AS UserID,
                 hack_description AS Decription,
                 created_date AS 'Created',
                 attachment_location AS 'Attachment Location',
                 uploaded_date AS Uploaded ,
                 Company,
                 TribeName AS 'Tribe Name'
                 From tbl_dealhack
                 left join tbl_dealhack_attachments on tbl_dealhack_attachments.dealhack_id = tbl_dealhack.id
                 left join tbl_profile on tbl_profile.user_id = tbl_dealhack.user_id
                 Left join tbl_attachment_type on tbl_attachment_type.id = tbl_dealhack_attachments.attachment_type_id
                 left join tbl_companytribe on tbl_companytribe.id = tbl_profile.TribeID
                 WHERE 1=1
                 AND attachment_type_id = 4
                 
                 "
                .(($this->params["startDatePicker"]!=array())?"AND uploaded_date BETWEEN (:start) ":"").""
                .(($this->params["endDatePicker"]!=array())?" AND (:end) ":"").""
                .((! empty($this->params["select"]))?"AND TribeName LIKE (:tribe) ":"").
                ""
                )
        ->params($query_params)
        ->pipe($this->dataStore("sales"));
        // GROUP BY year, productLine, customerName
        
        

//        
//        .(($this->params["startDatePicker"]!=array())?"AND created_date BETWEEN (:start) ":"").""
//                .(($this->params["endDatePicker"]!=array())?" AND (:end) ":"").""
//                .(($this->params["select"]!=array())?"AND TribeName LIKE (:tribe) ":"").
//        
    }
}

MyReport.view

<?php
    use \koolreport\datagrid\DataTables;
    use \koolreport\inputs\DateTimePicker;
    use \koolreport\widgets\koolphp\Table;
    use \koolreport\inputs\Select2;
?>
<div class="report-content">
    <div class="text-center">
        <h1>Multiple Data Filters</h1>
        <p class="lead">
            The example demonstrate how to build dynamic reports with multiple data filters
        </p>
    </div>
    
    <form method="post">
       <div class="col-md-12 form-group">
        <div class="row">
            <div class="col-md-6">
                
<!--                    <b>Select Years</b>-->
                   <b>Start Date</b>>
                    <?php 
                    
                    DateTimePicker::create(array(
                            "name"=>"startDatePicker",
                            "maxDate"=>"@endDatePicker",
                            "format"=>"DD/MM/YYYY HH:mm",
                            "themeBase"=>"bs4",
                        ));
                    
                    

                    ?>
                </div>    
  
                <div class="col-md-6">
<!--                    <b>Select Product Lines</b>-->
                   <b>End Date</b>
                    <?php 
                    
                    DateTimePicker::create(array(
                            "name"=>"endDatePicker",
                            "minDate"=>"@startDatePicker",
                            "format"=>"DD/MM/YYYY HH:mm",
                            "themeBase"=>"bs4",
                        ));
                    
                    

                    ?>                
                </div>
            </div>
<!--        </div>-->
        <div class="row">
            <div class="col-md-6">
                <div class="form-group">
                    <b>Tribe</b>
                    <?php 

    Select2::create(array(
                    "name"=>"select",
//                                  "dataStore"=>$this->dataStore("sales"),
                    "dataSource"=>$this->src("dealhackdb")->query("
                    Select distinct
                     TribeName AS 'Tribe Name'
                     From tbl_dealhack
                     left join tbl_dealhack_attachments on tbl_dealhack_attachments.dealhack_id = tbl_dealhack.id
                     left join tbl_profile on tbl_profile.user_id = tbl_dealhack.user_id
                     Left join tbl_attachment_type on tbl_attachment_type.id = tbl_dealhack_attachments.attachment_type_id
                     left join tbl_companytribe on tbl_companytribe.id = tbl_profile.TribeID
                     WHERE uploaded_date BETWEEN :start AND :end

                ")->params(
                    $this->params["startDatePicker"]!=array()?
                    array(":start"=>$this->params["startDatePicker"]):
                    array(),
                    $this->params["endDatePicker"]!=array()?
                    array(":end"=>$this->params["endDatePicker"]):
                    array()
                ),
                    "dataBind"=>"Tribe Name",
                    "attributes"=>array(
                        "class"=>"form-control",
                    )
                ));



            //        place above params bit for filters to be enable           
//                    ".( $this->params["startDatePicker"]!=array()?"WHERE created_date BETWEEN :start ":"AND '2021-12-21 12:00:00'")."
//                            AND attachment_type_id = 4  
//                            group by TribeName




            ?>                
                </div>  <!--2nd Form-Group end-->
            </div>
        </div> <!--2nd Row end-->
                
                <div class="form-group">
                    <button class="btn btn-primary">Submit</button>
                </div>    
            
        
        
    </form>
    <?php
    
    
        DataTables::create(array(
        "dataSource"=>$this->dataStore("sales"),
        "options"=>array(
            "paging"=>true),
        "themeBase"=>"bs4", // Optional option to work with Bootsrap 4
        "cssClass"=>array(
            "table"=>"table table-striped table-bordered "
        )
        ));
    
    
//    Table::create(array(
//        "dataSource"=>$this->dataStore("sales"),
//        "columns"=>array(
//            "customerName",
//            "productLine",
//            "amount"=>array("prefix"=>"$"),
//            "year"=>array("format"=>false)
//        ),
//        "grouping"=>array(
//            "year",
//            "productLine"
//        ),
//        "paging"=>array(
//            "pageSize"=>25
//        ),
//        "cssClass"=>array(
//            "table"=>"table-bordered"
//        )
//    ));
    ?>
</div>

Niall McGuirk commented on Sep 23, 2021

I changed the Tribe/select variable to be an array and it still operated like a string. Assigning the value London, instead of remaining empty. So, I'm not sure what is causing the the select variable to be assigned.

Sebastian Morales commented on Sep 24, 2021

Niall, a multi select can have an empty value (i.e an empty array) but a single select must always have a selected value among its options. In case you don't want that you must add an empty value to the beginning of options yourself, such as "" or "--". For example use this query:

    Select '--' as Tribe Name'
    UNION
    Select distinct
                     TribeName AS 'Tribe Name'
                     From tbl_dealhack
    ...
Niall McGuirk commented on Sep 24, 2021

Thanks, that seems to have worked to set it as Null. But it still uses the empty Tribe value when submit is pressed. I've tried to use a check if its "", but it doesn't seem to have worked. I'm trying to make it ignore the tribe input filter in the query, when the value is null.

Inputbox from MyReport.view.php

 Select2::create(array(
                    "name"=>"select",
//                                  "dataStore"=>$this->dataStore("sales"),
                    "dataSource"=>$this->src("dealhackdb")->query("
                    select '' AS 'Tribe Name'
                    UNION
                    Select distinct
                     TribeName AS 'Tribe Name'
                     From tbl_dealhack
                     left join tbl_dealhack_attachments on tbl_dealhack_attachments.dealhack_id = tbl_dealhack.id
                     left join tbl_profile on tbl_profile.user_id = tbl_dealhack.user_id
                     Left join tbl_attachment_type on tbl_attachment_type.id = tbl_dealhack_attachments.attachment_type_id
                     left join tbl_companytribe on tbl_companytribe.id = tbl_profile.TribeID
                     
                    
                ")->params(
                    $this->params["startDatePicker"]!=array()?
                    array(":start"=>$this->params["startDatePicker"]):
                    array(),
                    $this->params["endDatePicker"]!=array()?
                    array(":end"=>$this->params["endDatePicker"]):
                    array()
                ),
                    "dataBind"=>"Tribe Name",
                    "attributes"=>array(
                        "class"=>"form-control",
                    )
                ));

MyReport.php with altered if tree in setup, and if in query

<?php
//Step 1: Load KoolReport
require_once "../../load.koolreport.php";

//Step 2: Creating Report class
class MyReport extends \koolreport\KoolReport
{
    use \koolreport\inputs\Bindable;
    use \koolreport\inputs\POSTBinding;

    protected function defaultParamValues()
    {
        $date=date_create("2021-07-16");
        date_add($date,date_interval_create_from_date_string("-42 days"));
        $sd = date_format($date,"Y-m-d");
        
        return array(
            "startDatePicker"=>date($sd . " 00:00:00"),
            "endDatePicker"=>date("Y-m-d 23:59:59"),
            "select"=>"",
            "locationSelector"=>"",
        );
        
//        return array(
//            "years"=>array(2003),
//            "customerNames"=>array(),
//            "productLines"=>array(),
//        );
    }
    
    protected function bindParamsToInputs()
    {
        return array(
            "startDatePicker",
            "endDatePicker",
            "select",
            "locationSelector",
        );
        
//        return array(
//            "years",
//            "customerNames",
//            "productLines"
//        );
    }

    protected function settings()
    {
        
        $config = include "../../config.php";
        return array(
            "dataSources"=>$config
        );
        

    }
    protected function setup()
    {
        $query_params = array();
        if($this->params["startDatePicker"]!=array()){
            $query_params[":start"] = $this->params["startDatePicker"];
            }
        if($this->params["endDatePicker"]!=array()){
            $query_params[":end"] = $this->params["endDatePicker"];
            }
        if (($this->params["select"]!="")){
            $query_params[":tribe"] = $this->params["select"];
            }
//        if (! empty($this->params["select"])){
//            $query_params[":tribe"] = $this->params["select"];
//            }

        $this->src('dealhackdb')
        ->query("Select 
                 tbl_dealhack.id,
                 tbl_profile.user_id AS UserID,
                 hack_description AS Decription,
                 created_date AS 'Created',
                 attachment_location AS 'Attachment Location',
                 uploaded_date AS Uploaded ,
                 Company,
                 TribeName AS 'Tribe Name'
                 From tbl_dealhack
                 left join tbl_dealhack_attachments on tbl_dealhack_attachments.dealhack_id = tbl_dealhack.id
                 left join tbl_profile on tbl_profile.user_id = tbl_dealhack.user_id
                 Left join tbl_attachment_type on tbl_attachment_type.id = tbl_dealhack_attachments.attachment_type_id
                 left join tbl_companytribe on tbl_companytribe.id = tbl_profile.TribeID
                 WHERE 1=1
                 AND attachment_type_id = 4
                 
                 "
                .(($this->params["startDatePicker"]!=array())?"AND uploaded_date BETWEEN (:start) ":"").""
                .(($this->params["endDatePicker"]!=array())?" AND (:end) ":"").""
                .((($this->params["select"]!=''))?"AND TribeName LIKE (:tribe) ":"").
                "")
        ->params($query_params)
        ->pipe($this->dataStore("sales"));
        // GROUP BY year, productLine, customerName
        
        

//        .((! empty($this->params["select"]))?"AND TribeName LIKE (:tribe) ":"").
//        .(($this->params["startDatePicker"]!=array())?"AND created_date BETWEEN (:start) ":"").""
//                .(($this->params["endDatePicker"]!=array())?" AND (:end) ":"").""
//                .(($this->params["select"]!=array())?"AND TribeName LIKE (:tribe) ":"").
//        
    }
}

Sebastian Morales commented on Sep 27, 2021

Niall, in any case I suggest you put a var_dump command at the beginning of setup() to check for the exact "tribe" and other parameter values so that you know which values to compare to in null case:

function setup() 
{
    var_dump($this->params); echo "<br>";
    ...
Niall McGuirk commented on Sep 27, 2021

Thanks, that helped. Somehow the Filter is working as intended now; unused when set to "", Used in query when assigned to a value.

Build Your Excellent Data Report

Let KoolReport help you to make great reports. It's free & open-source released under MIT license.

Download KoolReport View demo
help needed
solved

Inputs