Ty Yt
Ty Yt

Reputation: 466

Search with two fields not mandatory

I'd like to do a search function in my website. This research will show products based on product's name and seller's location. My view :

<?php echo $this->Form->create('Product', array('type' => 'GET')); ?>

<div class="col col-sm-4">
    <?php echo $this->Form->input('search', array('label' => false, 'div' => false, 'class' => 'form-control', 'autocomplete' => 'off', 'value' => $search)); ?>
</div>
    <div class="col col-sm-2">
        <?php echo $this->Form->input('searchCity', array('label' => false, 'div' => false, 'class' => 'form-control', 'autocomplete' => 'off')); ?>
    </div>
<div class="col col-sm-3">
    <?php echo $this->Form->button('Search', array('div' => false, 'class' => 'btn btn-sm btn-primary')); ?>
</div>

<?php echo $this->Form->end(); ?>

Two search fields : one for the name and the second for location.

My controller (worked for only one search field) :

if(!empty($this->request->query['search']) || !empty($this->request->data['name'])) {
        $search = empty($this->request->query['search']) ? $this->request->data['name'] : $this->request->query['search'];
        $search = preg_replace('/[^a-zA-Z0-9 ]/', '', $search);
        $terms = explode(' ', trim($search));
        $terms = array_diff($terms, array(''));
        $conditions = array(
            'Brand.active' => 1,
            'Product.active' => 1,
            'Product.date_discount >' => date('Y-m-d H:i:s')
        );
        foreach($terms as $term) {
            $terms1[] = preg_replace('/[^a-zA-Z0-9]/', '', $term);
            $conditions[] = array(
                'OR' => array(
                    array('Product.name LIKE' => '%' . $term . '%'),
                    //array('Brand.city LIKE' => '%' . $this->request->query['searchCity'] . '%')
                )
            );
        }
        $products = $this->Product->find('all', array(
            'recursive' => -1,
            'contain' => array(
                'Brand'
            ),
            'conditions' => $conditions,
            'limit' => 200,
        ));
        if(count($products) == 1) {
            return $this->redirect(array('controller' => 'products', 'action' => 'view', 'slug' => $products[0]['Product']['slug']));
        }
        $terms1 = array_diff($terms1, array(''));
        $this->set(compact('products', 'terms1'));
    }

No search fields are mandatory. If only name search field, it will show all products based on product's name whatever the location. If only city search field, it will show all products in location. If both, it will show all products based on name and location.

I don't know what to modify to do it. I tried to do another if(!empty($this->request->query['searchCity']) under the if I posted above but it didn't work (copy paste the first if and I changed conditions). What should I do?

Thanks.

Upvotes: 0

Views: 92

Answers (2)

Pradeep Singh
Pradeep Singh

Reputation: 1290

You can use this CakeDC Search plugin

First include the plugin in your app

CakePlugin::load('Search');

Then in your model include the behavior

public $actsAs = array(
   'Search.Searchable'
);

and

public $filterArgs = array(
    'search' => array(
        'type' => 'like'
    ),
    'searchcity' => array(
        'type' => 'like'
    )
);

and in your controller

public $components = array(
    'Search.Prg','Paginator'
);

public function find() {
    $this->Prg->commonProcess();
    $this->Paginator->settings['conditions'] = $this-> Product->parseCriteria($this->passedArgs);
    $this->set('products', $this->Paginator->paginate());
}

For complete example visit here

Upvotes: 1

Fr0zenFyr
Fr0zenFyr

Reputation: 1939

I'm unable to understand exactly what is being asked but from what I understand, the OR condition didn't work as expected and that is because there is a small problem with the syntax used in your $conditions. Additional arrays used for each field in conditions are not required, which is causing the problem. So,

instead of:

$conditions[] = array(
    'OR' => array(
        array('Product.name LIKE' => '%' . $term . '%'),
        array('Brand.city LIKE' => '%' . $this->request->query['searchCity'] . '%')
    )
);

use:

$conditions[] = array(
    'OR' => array(
        'Product.name LIKE' => '%' . $term . '%',
        'Brand.city LIKE' => '%' . $this->request->query['searchCity'] . '%'
    )
);

Also, use two different variables for static conditions and dynamic conditions(with $terms in foreach()) and then combine them using array_combine like this:

$conditions_st = array(
    'Brand.active' => 1,
    'Product.active' => 1,
    'Product.date_discount >' => date('Y-m-d H:i:s')
);


foreach($terms as $term) {
    $terms1[] = preg_replace('/[^a-zA-Z0-9]/', '', $term);
    $conditions_dy = array(
        'OR' => array(
            'Product.name LIKE' => '%' . $term . '%',
            'Brand.city LIKE' => '%' . $this->request->query['searchCity'] . '%'
        )
    );
}

$conditions = array_combine($conditions_st, $conditions_dy);

P.S: i just scanned through your code, and couldn't quite understand what you are trying to do. I just highlighted the problems I noticed.

Upvotes: 0

Related Questions