Search similar results - php

In my database, I will have college building rooms (such as B100, A200, TLAB100) and I want it so that when people search for a specific room (such as B101, B102) it will return the building name without the ending number, so: B100.
My controller so far looks like this:
$results = $this->Building->find('all', array(
'conditions' => array(
'Building.building LIKE' => $this->data['Food']['q']
)
)
);
But I believe LIKE isn't the right command for it. Because it's not working that way

Why Like is not right?
$likeSmth = substr($this->data['Food']['q'], 0, -1);
'SELECT * FROM tbl WHERE roomnumber LIKE '.$likeSmth.'%'
and etc.

Related

How to get all rows from related table using join in Zend Framework

I have two tables. First table contain offer details and second table contains offer collection of languages(collection can be selected in main offer form). I want to use query with "join" language table to get all of them in single query. How it's look like:
Relation
Trying to get all of the offers I want to get all offer languages as one field.
array [
'id' => string '11',
'name' => string '134',
'date' => string '01-12-2016',
'languages' => array(all language value from related table)
]
Here is my query:
$select = $this->getDbTable()->select()
->setIntegrityCheck(false)
->from(array('o' => 'offers'), array('o.*'))
->joinLeft(array('ol' => 'offer_language'), 'ol.id_offer = o.id', array('ol.*'));
$resultSet = $this->getDbTable()->fetchAll($select)
In that way if one offer has a three language then I get three same offer with different language field.
Zend Version: 1.11
Thanks for help.
The solution is to use a Zend_Db_Expr with GROUP_CONCAT.
Here are two posts that will give you a clear explanation:
Can I concatenate multiple MySQL rows into one field? and How to use GROUP_CONCAT with Zend Framework?
Your code will end up looking something like this:
$select = $this->getDbTable()->select()
->setIntegrityCheck(false)
->from(array('o' => 'offers'), array('o.*'))
->joinLeft(array('ol' => 'offer_language'), 'ol.id_offer = o.id', array('languages' => new Zend_Db_Expr('GROUP_CONCAT(ol.language)')))
->group('o.id');
Good luck!

Combining and and or operators in Phalcon\Mvc\Model\Criteria

I'm just writing my first phalcon application and have a question for filtering a query using Phalcon\Mvc\Model\Criteria.
Finally I want a query like this
SELECT *
FROM table
WHERE
status = 'A' AND
(
title LIKE 'combining%' OR
title LIKE 'phalcon%' OR
(
title LIKE 'criteria%' AND
title LIKE '%phalcon'
)
)
For me it seems there is no way for parenthesis in phalcons model criteria. The only way to achieve this is by writing phql.
Instead of writing a complete phql I maybe can write something like this, but that is getting the same complexity
<?php
$query = Table::query();
$query->where('status = :status:', array('status' => 'A'));
$query->andWhere('(
title LIKE :title1: OR
title LIKE :title2: OR (
title LIKE :title3: AND
title LIKE :title4:
)
)', array(
'title1' => 'combining%',
'title2' => 'phalcon%',
'title3' => 'criteria%',
'title4' => '%phalcon'
));
It looks like Criteria's "where", "andWhere" and "orWhere" methods will add the outer parenthesis for you, then you can manually write the inner parenthesis.
$query = Model::query()
->where('status = "A"')
->andWhere('title LIKE "combining%" OR
title LIKE "phalcon%" OR
(
title LIKE "criteria%" AND
title LIKE "%phalcon"
)
');
$models = $query->execute();
You can test that the where clause is correct.
var_dump($query->getWhere());

Comparing 2 fields within a Mongo Aggregation Query

I have a collection in my Mongo Database called WorkOrder with 2 fields DateComplete and DateDue. Using those 2 fields I'd like to use the aggregation framework to count the number of 'Late' Work Orders by comparing the two fields. However the research I've found hasn't had any useful ways to format the query so that the 'Late' Work Orders will be filtered through. Does anyone know of a way to format a Mongo DB Aggregation Query (preferably in PHP) that can compare 2 fields in the collection?
EDIT:
An example entry in WorkOrder might look like
_id
some mongo id
DateDue
2014-10-10
DateCompleted
2014-10-12
This entry would want to be filtered through since DateCompleted is greater than DateDue. I didn't know about the $cond operator so I haven't tried anything for that yet.
EDIT:
After trying #BatScream's suggestion with the following query in my PHP script
array(
'$cond' => array(
'if' => array(
'dateDue' => array(
'$lt' => 'dateComplete
)
)
)
)
However the MongoCollection::Aggregate function told me that $cond wasn't a recognized operator.
EDIT: #BatScream's answer seems to work but I wasn't aware of the fact that the group operator doesn't work properly after a $project is applied. I was hoping to be able to group these document on another field cID, is that possible?
The below aggregation pipeline would give you the result, considering your fields are of ISODate type. If not i suggest you to store them as ISODate type and not Strings.
db.collection.aggregate([
{$project:{"isLateWorkOrder":{$cond:[{$lt:["$dateDue","$dateCompleted"]},
true,false]}}},
{$match:{"isLateWorkOrder":true}},
{$group:{"_id":null,"lateWorkOrders":{$sum:1}}},
{$project:{"_id":0,"lateWorkOrders":1}}
])
The PHP syntax should look similar to,
$projA = array("isLateWorkOrder" =>
array("$cond" =>
array(array("$lt" =>
array("$dateDue","$dateCompleted")),
true,false)))
$matchA = array("isLateWorkOrder" => true)
$grp = array("_id" => null,"lateWorkOrders" => array("$sum" => 1))
$projB = array("_id" => 0,"lateWorkOrders" => 1)
$pipeline = array($projA,$matchA,$grp,$projB);
$someCol -> aggregate($pipeline)
or, simply using the count function:
db.collection.count({$where:"this.dateDue < this.dateCompleted"})

CakePHP - SQL query Join

Ok, so i'm in a pickle trying to figure a way for how to do this :
I have a live search(using ajax) which allows the user to select a criteria from a dropdown list and then enter a value which will be matched to values inside the database. This is quite trivial stuff, and on direct fields of the main model, i don't have any issues.
I have a Donor Model/table which consists of attributes such as ID, Name, Surname etc, but more importantly it also has FK of other associated models such as blood_group_id, donor_type_id, which map back to the respective models (BloodGroup and DonorType).. These two are already set with the associations and I am beyond that part, as I am already retrieving Donor records with associated model data.
Here is the search method which will hopefully help you in understanding my problem better.
public function search() {
if($this->request->is('post')){
if(!empty($this->request->data)){
$criteria = $this->request->data['criteria'];
$query = $this->request->data['query'];
$conditions = array("Donor." .$criteria. " LIKE '". $query . "%'");
The above checks if its a post request and whether data was sent. The criteria and user input are used to construct the query..
This is where my problem arises.. (When the user select search By blood type, as a criteria from the drop down)the above expects the user to enter the id of the blood_group rather than A+ or A- for instance.. So if the input is 1(id of blood group A+), the results are returned as expected. But I want the user to be able to enter A+...
Here is the rest of the method :
$this->Paginator->settings = array(
'conditions' => $conditions,
'limit' => 2
);
$donors = $this->Paginator->paginate('Donor');
$this->set('donors', $donors);
$this->beforeRender();
$this->layout= 'ajax';
}
}
}
I have tried this approach, setting up the conditions using the Model's name such as
if($criteria == 'blood_group_id'){
$conditions = array("BloodGroup.id" . " LIKE '". $query . "%'");
}elseif($criteria == 'donor_type_id'){
$conditions = array("DonorType.id" . " LIKE '". $query . "%'");
}else{
$this->Paginator->settings = array(
'conditions' => $conditions,
'limit' => 2
);
}
But this returns all the records irrespective of the input.
I also tried changing the settings for the paginator with no luck
$settings = array(
'joins' => array(
'table' => 'blood_groups',
'alias' => 'BloodGroup',
'type' => 'LEFT',
'conditions' => array(
"BloodGroup.id" => "Donor.blood_group_id",
"AND" => $conditions
)
),
'limit'=> 2
);
Any help on how to accomplish what I explained above, would greatly be appreciated!
simply:
if($criteria == 'blood_group_id')
$conditions = array("BloodGroup.name LIKE" => $query.'%');
(assuming bood_types has a 'name' column)
Also let me suggest you to use the CakeDC search plugin (https://github.com/CakeDC/search).

get a single value from a table using the query() method inside a model

I have a very complex setup on my tables and achieving this via any of the find() methods is not an option for me, since I would need to fix relationships between my tables and I don't have the time right now, so I'm looking for a simple fix here.
All I want to achieve is run a query like this:
SELECT MAX( id ) as max FROM MyTable WHERE another_field_id = $another_field_id
Then, I need to assign that single id to a variable for later use.
The way I have it now it returns something like [{{max: 16}}], I'm aware I may be able to do some PHP on this result set to get the single value I need, but I was hoping there was already a way to do this on CakePHP.
Assuming you have a model for your table and your are using CakePHP 2.x, do:
$result = $this->MyTable->field('id', array('1=1'), 'id DESC');
This will return a single value.
see Model::field()
This example is directly from the CakePHP documentation. it seems you can use the find method of a model to get count
$total = $this->Article->find('count');
$pending = $this->Article->find('count', array(
'conditions' => array('Article.status' => 'pending')
));
$authors = $this->Article->User->find('count');
$publishedAuthors = $this->Article->find('count', array(
'fields' => 'DISTINCT Article.user_id',
'conditions' => array('Article.status !=' => 'pending')
));

Categories