I am creating an API in Laravel and using query strings to handle complex queries.
It is easy to handle queries like url/item/?color=red&age=3... to collect all items that are red and 3 years old.
But this is because these are discrete variables being queried for equality. Say for example I want to retrieve all users who registered after a certain date. How would I handle this?
I was thinking maybe:
url/item/?registered_later_than=DDMMYYYY
Is there a better way?
I'd suggest something like this:
url/item/?registered=>:DDMMYYYY
The parameter name is the name of the attribute
Right at the beginning of the parameter value is the operator
Operator and value is separated by a : (it actually can be any separation character you want)
Other examples:
url/item/?name=like:foo
url/item/?email==:foo.bar#example.com
I agree email==:foo looks a bit weird. You could also use words or abbreviations ("eq", "gt", etc) instead of operator signs.
How to parse it
$filters = Input::all();
$query = Model::newQuery();
foreach($filters as $attribute => $filter){
$parts = explode(':', $filter, 2);
$operator = $parts[0];
$value = $parts[1];
$query->where($attribute, $operator, $value);
}
I hope this gives you an idea how you could do it ;)
Not really a "better way" but you can try something like this :
url/item/?operator=lt&date=20141223
Operator can be :
lt : lesser than
gt : greater than
eq : equals to
etc.
Or whatever you want (maybe it's more readable with in full text: "greater_than", etc.). Hope I understood well your question and it will help you.
Related
I must have build a query from my store items. my store items have 10 field . I just let customer search in my item's optional.
for example first one maybe want to filter on field1 , second one maybe want to filter on field1 and field2,third one maybe want to filter on field6 and field8 and filde9,... .
how can i make a query more short more efficient for this ?
note 1: I don't want to use Raw method because of its vulnerability.
note 2: i see some answers in link 1 and link 2 but I think first one can not be use for
condition like : where('field1','>=','somevalue') or where('field2','like','%somevalue%') or any sort of condition with some complexity and second one has more "if" chaining and i want to have shorter than this if it's possible
You can do this in several ways depending on the syntax you'd like. One possible way is to use a separation symbol to pass multiple arguments:
/api/user?where[]=user_id|>=|5
/api/user?where[]=user_id|2
/api/user?where[]=user_id|2&where[]=status|activated
This simply allows you to pass multiple where options where the pipe | operator separates the arguments. Note that this may cause issues if you want the pipe character to be available as search argument for instance.
Then you could simply parse this url into your query like so:
foreach($request->get('where') as $i => $values) {
$values = explode('|', $values);
// Allow the third argument to be exchanged with the second one,
// similar to how the Laravel `where()` method works.
$query->where($values[0], $values[1], $values[2] ?? null);
}
Optionally, you can add a validation method so that the syntax will be properly checked beforehand. You can add this snippet to some boot() method of a service provider:
\Illuminate\Support\Facades\Validator::extend('query_where', function($attribute, $value) {
// Require minimum length of 2 parameters.
return count(explode('|', $value)) >= 2;
});
Next, your validation in your controller action would look like this:
$this->validate($request, [
'where' => 'nullable|array',
'where.*' => 'query_where',
]);
The possibilities are endless.
I am working with quicktable queries and everything seems to be fine.
Now I want to perform queries using like operators. For instance in PHP I can do something like:
$data ='content to search';
$stmt = $db->prepare('SELECT * FROM members where name like :name OR email like :email limit 20');
$stmt->execute(array(
':name' => '%'.$data.'%',
':email' => '%'.$data.'%',
));
Now in quick table, I have tried using CT, EX or HAS parameter etc with OR Operators. Only CT gives nearby result but not exact as per code below.
//Email = 7
//name =8
{
"from": "tableId",
"where": "{7.CT.'nancy#gmail.com'}OR{8.CT.'nancy'}"
}
Is there any way I can obtain a better search with like operators with Quickbase. The documentation here does not cover that.
CT is the closest string comparison operator in Quick Base to LIKE in SQL, but since you can't use wildcards in Quick Base queries you might need to group multiple query strings to achieve the same result. The is also a SW operator that can sometimes come in helpful for comparing parts of a strings.
I've been reading docs regarding these 2 functions, but I still can't quite get the difference between these two.
I get it that get_where selects data from DB, but when should we use where() function and not get_where()?
get_where()
There are tons of other ways to get data using CodeIgniter’s ActiveRecord implementation, but you also have full SQL queries if you need them:
Example:
$query = $this->db->get_where('people', array('id' => 449587));
Ultimately, get_where() is the naive case, and certainly the most commonly-used in my code anyway — I can’t think of an another framework in any other language that enables you to be this productive with data with a single line of code.
get_where([$table = ''[, $where = NULL[, $limit = NULL[, $offset = NULL]]]])
Parameters:
$table (mixed) – The table(s) to fetch data from; string or array
$where (string) – The WHERE clause
$limit (int) – The LIMIT clause
$offset (int) – The OFFSET clause
This function is working as get() but with also allows the WHERE to be added directly.
Identical to the $this->db->get(); except that it permits you to add
a where clause in the second parameter, instead of using the
db->where() function.
where()
This function enables you to set WHERE clauses in your query.
You can also add where clauses, sort conditions and so forth:
$this->db->select('first_name', 'last_name');
$this->db->from('people');
$this->db->where('id', 449587);
$this->db->order_by('last_name, first_name');
$query = $this->db->get();
It’s possible to chain all these conditions together on a single line, but I prefer putting them on separate lines for readability.
In simple word, get_where is a luxury to use but where() gives you more flexibility to use.
The get_where is a combined function -so to speak- of the both where() and get() functions,
according to the documentation :
$this->db->get_where()
Identical to the above function except that it permits you to add a
"where" clause in the second parameter, instead of using the
db->where() function
also by take a quick look at the source code of the get_where() method you will notice that
if ($where !== NULL)
{
$this->where($where);
}
where $where is the second parameter of get_where() method.
In simple terms, $this->db->get_where('table name', 'where clause') is an alias for $this->db->where('where clause')->get('table name');
I am fairly new to programming, php, Magento, and most of all, SQL. Please forgive me if this is somehow a dumb question.
I am trying to use Magento collections to select two different columns in two different tables and join them. These two columns contain product numbers that follow the same conventions and my goal is to get and display the product numbers that field a (lets call it 'product_id') contains that field b ('item_nr') does not.
Here is my function so far, located currently in a model that will be called by a controller action.
public function importCompare() {
$orderlistCollect = Mage::getModel('personal_orderlist/orderlist')->getCollection()
->addFieldToSelect('product_id')
->addFieldToFilter('b.item_nr', null)
->getSelect()
->joinLeft( array('b'=>$this->getTable('catalog/product')), 'main_table.product_id = b.item_nr', array('b.item_nr'));
echo $orderlistCollect;
}
By echoing the variable, I get the following query.
SELECT `main_table`.`product_id`, `b`.`erp_item_nr`
FROM `mag1personal_orderlist` AS `main_table`
LEFT JOIN `` AS `b` ON main_table.product_id = b.item_nr
WHERE (b.item_nr = '')
This looks fairly close to what I want, however the big problem is that I have no idea how to retrieve the information I should derive from this query and echo it. I've tried to use a variety of collection manipulation methods to no avail. Is it easy to use them out of order as well?
Any help here is appreciated.
Collections use interfaces from PHP's standard library to implement for each-able behaviors.
If that sounded like greek, give this a try.
foreach($orderlistCollect as $item)
{
$data = $item->getData();
var_dump($data);
$sku = $item->getSku();
var_dump($sku);
$sku = $item->getData('sku');
var_dump($sku);
}
If you're interested in learning how to do with with your own PHP objects, the Object Iteration section of the manual is a good place to start. However, there's no need to dive deep on this — just treat a collection like you would an array of objects, and you'll be fine.
I am trying to check that a combination of entries across five columns (I have parent1, parent2, parent3, parent4, and parent5 all of which are integers) does not already exist in my form validation.
I tried:
$query = Doctrine_Query::create()
->select('m.id', 'm.name') -> from ('Mix m')
->where('m.parent1=?', $values['parent1'])
->orWhere('m.parent1=?', $values['parent2'])
->orWhere('m.parent1=?', $values['parent3'])
->orWhere('m.parent1=?', $values['parent4'])
->orWhere('m.parent1=?', $values['parent5'])
->andWhere('m.parent2=?', $values['parent1'])
->orWhere('m.parent2=?', $values['parent2'])
...and so on.
Probably not the most efficient way, but regardless it is throwing an error if one of the values matches any of the columns already in the database, it's not checking for the actual combination...
Any help would be very appreciated!
How about...
// Set of possible matches
$set = array($values['parent1'], $values['parent2'], $values['parent3'], $values['parent4'], $values['parent5']);
// Let's make it two-dimensional for simpler DQL syntax
$sets = array($set, $set, $set, $set, $set);
// Multiple WHERE IN AND
$query = Doctrine_Query::create()
->select('m.id', 'm.name')
->from ('Mix m')
->where('m.parent1 IN ? AND m.parent2 IN ? AND m.parent3 IN ? AND m.parent4 IN ? AND m.parent5 IN ?', $sets);
The WHERE IN AND should make sure each value is matched. However, at least one fail case that comes to mind is that if multiple values in the $set are the same (e.g. '5, 5, 1, 4, 1', the query will give false matches. Maybe someone else can improve on that. Might be a slow query as well.