I would like to pass array to like clause of active record in codeignter for that i have written the following:
$array_string = smart,intelligent,awesome;
$array_like = explode(',',$array_string);
and in model:
$this->db->like('topic',array($array_like));
but I am getting
Severity: Notice
Message: Array to string conversion
Any help or suggestion would be a great help.
See updated question here:
join not giving required result when using or_like codeigniter
You can't just pass an array to the like() function, it has to be a string. You need to apply a like clause for each of the keywords in the string.
You need to use or_like to match a record to either of the keywords, however, because if you just use like() each time, it will need to match all of the keywords due to the query being like LIKE "%smart" AND LIKE "%intelligent" etc. and that isn't what you require.
$array_string = "smart,intelligent,awesome";
$array_like = explode(',', $array_string);
foreach($array_like as $key => $value) {
if($key == 0) {
$this->db->like('topic', $value);
} else {
$this->db->or_like('topic', $value);
}
}
Try this way to avoid your problem of the rest of the where statement being ignored.
$array_string = "smart,intelligent,awesome";
$array_like = explode(',', $array_string);
$like_statements = array();
foreach($array_like as $value) {
$like_statements[] = "topic LIKE '%" . $value . "%'";
}
$like_string = "(" . implode(' OR ', $like_statements) . ")";
The value of $like_string will be (topic LIKE '%smart%' OR topic LIKE '%intelligent%' OR topic LIKE '%awesome%')
You can then use $like_string in the following way with ActiveRecord:
$this->db->where($like_string, FALSE);
Assuming you are using Codeigniter 2.1.4, as you can read in CodeIgniter active record documentation, you cannot pass the second argument as array in like function. You need to pass a string as argument.
$array_string = "smart,intelligent,awesome";
$array_like = explode(',', $array_string);
foreach ($array_like as $like)
{
$this->db->like('topic', $like);
}
Related
I'm trying to build a complicate query where there is an unknown number of postalcode areas posted to my api. At the moment I almost found the solution, but I can't concatenate my whereBetween parameters to the Query in the scope. I get the error query can't be casted to string, which also makes sense.
The array passed to the scope has the following structure: $plz = [[10000, 11000], [34200, 34500]];
Here is my code in the scope:
public function scopePlz($query, $plz)
{
$queryString = '';
foreach ($plz as $index => $single) {
$queryString .=
$index == 0
? "->whereBetween('postalcode_int', [$single[0], $single[1]])"
: "->orWhereBetween('postalcode_int', [$single[0], $single[1]])";
}
return $query . $queryString;
}
You could solve it like this:
public function scopePlz($query, $plz)
{
$first = array_shift($plz);
$query->whereBetween('postalcode_int', [$first[0], $first[1]]);
foreach ($plz as $single) {
$query->orWhereBetween('postalcode_int', [$single[0], $single[1]]);
}
return $query;
}
Get the first item from the array, add it like a where and then run the rest of the array through a foreach.
If you want one big where statement for all these postal codes, wrap this scope in an separate where method.
In my php file I get string which looks like [["category_id","=","3"],["price","<","40"]] from Android. I will use that for select query. But how can I get each item from it?
Here my code:
<?php
$filter = $_POST[‘filter’];
$filter_text = “”;
foreach($filter as $filter_item){
foreach($filter_item as list($column, $equality, $value)){
$filter_text .= "product." . $column . $equality. "'" . $value . "' AND ";
}
}
...
?>
Looks like you're constructing a WHERE clause to an SQL query. Here's a clue on how to build the string, but you should be using prepared statements instead of injecting user input directly into your query! Also, you don't actually need to nest a foreach, as is demonstrated below. See comments for explanation.
To use prepared statements (and please do!), you can substitute the variables in the ANDed conditions with "product.? ? ?";. Then use PDOStatement::bindValue(). Other flavors of parameter binding are available.
<?php
// Your input array.
$filters = [["category_id","=","3"],["price","<","40"]];
// Your question is unclear on this, but if your $_POST['filter'] is not actually an array, but a JSON string, then you may try this:
$filters = json_decode($_POST['filter'], TRUE); // TRUE to decode to associative array.
// $where holds each WHERE condition, so you can perform a clean string glue with implode().
// In your current string concatenation, additional conditions are required, or the query
// will fail due to an errant trailing AND if none are following.
$where = [];
// $filterText will hold this part of your WHERE clause. Consider renaming it to something
// more descriptive, like $whereSql.
$filterText = '';
foreach ($filters as [$key, $comparisonOperator, $value])
$where[] = "product.$key $comparisonOperator $value";
// Glue each condition with as many ANDs are necessary.
$filterText .= implode(' AND ', $where);
echo $filterText;
// Outputs: product.category_id = 3 AND product.price < 40
UPDATE: Your question is a little unclear on this, so I've added something that you can try. This updated answer now assumes your input isn't actually an array, but a JSON string.
You can use implode and some looping
$filter = isset($_POST['filter']) ? $_POST['filter'] : '';
$arr = json_decode($filter,true);
foreach($arr as $k => $v) {
$query['q'][] = [
'column' => 'product.' . $v[0],
'equality' => $v[1],
'value' => $v[2]
];
}
$filter = array();
foreach($query as $q) {
foreach($q as $k) {
$filter[]= sprintf("%s %s %s", $k['column'],$k['equality'],$k['value']);
}
}
$query = implode(' AND ',$filter);
echo $query;
// product.category_id = 3 AND product.price < 40
Warning: You are wide open to SQL Injections and should use parameterized prepared statements instead of manually building your queries. They are provided by PDO or by MySQLi. Never trust any kind of input! Even when your queries are executed only by trusted users, you are still in risk of corrupting your data. Escaping is not enough!
-Dharman
I know in Laravel 4 you can create a dynamic WHERE clause at runtime as from the following question:
Can you use query builder to build a query with a dynamic WHERE clause at runtime in laravel?
But can you do the same in laravel 3?
If not, is your only option instead to create raw SQL code as in the following:
$SQL = "SELECT * FROM " . $table;
$first = 1;
foreach($items as $key => $val)
{
if($first) $SQL .= " WHERE ";
else $SQL .= " AND ";
$SQL .= $key . " LIKE " . $VAL;
$first = 0;
}
It works pretty much the exact same way. Just use $query = DB::table('tablename'); in place of the first line in the related post then use it as the rest of the example shows.
You can do this using something like this:
$query = DB::table($table);
if(isset($key1) && isset($val1)) {
$query->where($key1, 'LIKE', $val1);
}
if(isset($key2) && isset($va2)) {
$query->where($key2, '=', $val2);
}
$result = $query->get(); // returns all matching models
You can chain as many where clause as you need until you call the get() method. Also check this answer/L-4 to get another idea. Reading the Laravel - 3 manual would help you.
You can use the query builder to perform queries such as this.
$query = DB::table($table);
// Get only the fields from the form that we care about...
$form_fields = Input::get('email', 'username');
// Build a dynamic query based on the form with WHERE's
foreach ($form_fields as $name=>&$value) {
$query->where($name, '=', $value);
}
// Finally get all of the results...
$results = $query->get();
This does work fine in Laravel 3. Check out this [http://forumsarchive.laravel.io/viewtopic.php?id=1494] forum post for more information
I have this code above which i use to implode some variable.
The issue is that i need to create the same thing for $hostess_name[] as i did for $hostess_id_selected[].
I don't know what am i doing wrong.
I need to implode it the same way as i did with $hostess_id_selected1
foreach($hostess_id as $val) {
$hostess_id_selected[] = $val;
$sqlnomehostess="SELECT nome_hostess FROM hostess where id='$val'";
$resultnomehostess=mysql_query($sqlnomehostess)or die(mysql_error());
$hostess_name= array();
while ($row=mysql_fetch_array($resultnomehostess,MYSQL_ASSOC)) {
$hostess_name[] = $row['nome_hostess'];
}
}
$hostess_id_selected1 = implode("-",$hostess_id_selected);
you have $hostess_name= array(); inside the loop. move it above
EDIT:
some tips:
foreach($hostess_id as $val) {
$hostess_id_selected[] = $val;
// this is pointless, i mean - you are recreating $hostess_id
btw, just a little tip for improvement - instead of running many SQL queries you can use a single query:
$sql = "SELECT GROUP_CONTACT(`nome_hostess` SEPARATOR '-') AS name_list
FROM `hostess`
WHERE id IN (".implode(',',$hostess_id).")";
if the items in $hostess_id are not necessarily numeric:
$sql_ids = array();
foreach($hostess_id as $id)
$sql_ids[] = mysql_real_escape_string($id);
$sql = "SELECT GROUP_CONTACT(`nome_hostess` SEPARATOR '-') AS name_list
FROM `hostess`
WHERE id IN (".implode(',',$sql_ids).")";
and after that:
the sql query returns 1 row with a column called "name_list", which contains the names joined with "-".
if you want to maintain the order of the id and name - you should do:
$sql = "SELECT
GROUP_CONTACT(`nome_hostess` SEPARATOR '-') AS name_list,
GROUP_CONTACT(`id` SEPARATOR '-') AS id_list
FROM `hostess`
WHERE id IN (".implode(',',$hostess_id).")";
implode is a basic function of php. It always work perfect.
Just check your array $hostess_id_selected, what it returning.
I think it will help you.
i have a variable and an user_name i want to search on a string(function_description) of the user_name for it
whats wrong with this :
$function_keywords = mysql_real_escape_string($_POST['function_keywords']);
if($function_keywords=="" || empty($function_keywords)){
redirect("show.php?functions=PHP");
}
//trim whitespace from the stored variable
$trimmed = trim($function_keywords);
//separate key-phrases into keywords
$trimmed_keywords = explode(" ",$trimmed);
// Build SQL Query for each keyword entered
foreach ($trimmed_keywords as $trimm){
// MySQL "MATCH" is used for full-text searching.
//this code is ebv weird , should check out soon!
$query = "SELECT *
FROM functions
WHERE isEnabled=1 AND isPrivate=0
AND function_description LIKE '{$trimm}'
AND user_name='{$user_name}'
";
// Execute the query to get number of rows that contain search kewords
$results=mysql_query ($query,$connection);
as far as "like" syntax goes you have to use the '%' symbol. if you query for
select * from table where column like '%yourkeyword%'
then it returns any rows with 'yourkeyword' inside the table column.
your statement will be true only if the column = 'yourkeyword'
That's highly inefficient. If someone puts in 5 keywords, you'd be running the search 5 times and getting 5 sets of results. Try something more along these lines:
$words = $_POST['function_keywords'];
if ($words == '') {
... abort ...
}
$parts = trim(explode(' ', $words));
$clauses = array();
foreach($parts as $part) {
$clauses[] = "function_description LIKE '%" . mysql_real_escape_string($part) . "%'";
}
$clause = implode(' OR ' , $clauses);
$sql = "SELECT .... WHERE (isEnabled=1) AND (isPrivate=1) AND (user_name='$user_name') AND ($clause)";
$result = mysql_query($sql) or die(mysql_error());
This'll build up a long series of or statements for each keyword specified, and run the whole thing as a single query.
To see if the function_description contains the keyword you need to use '%' which stands for anything much the way '*' does in unix. Try function_description LIKE '%{$trimm}%'