Hey.. I've run into a problem using several "like" in my sql-query (generated with Codeigniter's activerecord):
SELECT * FROM (`posts`) WHERE `city` LIKE '%test%' AND `title` LIKE '%%' OR `text` LIKE '%%'
Thing is, it appears to read this query as if there was a parenthesis around the first like and the second like, but I want there to be a parenthesis around the second and the last like (I want it to compare if the last or the next to last works).
How can I achieve this using Codeigniter's Active Record class?
Current code:
if($type != 0)
$this->db->where('type', $type);
$this->db->like('city', $area);
$this->db->like('title', $words);
$this->db->or_like('text', $words);
return $this->db->get('posts')->result_array();
Previous answer is correct. I would like to add the following...
In Codeigniter supporting the following overall...
$this->db->like();
$this->db->or_like();
$this->db->not_like();
$this->db->or_not_like();
Hope this will help someone.
I don't think CI is adding any paranthesis. It will add an 'AND' between the first two statements and an 'OR' between the last two. To achieve what you want, I would write my own statement. It's very straightforward.
$sql = SELECT * FROM 'posts' WHERE city LIKE ? AND ( title LIKE ? OR text LIKE ? );
$query = $this->db->query($sql, array($area, $words, $words));
Notice how I've used binding. This automatically escapes characters for you.
this will do the trick
$this->db->select('*')->from('my_table')
->group_start()
->where('a', 'a')
->or_group_start()
->where('b', 'b')
->where('c', 'c')
->group_end()
->group_end()
->where('d', 'd')
->get();
// Generates:
// SELECT * FROM (`my_table`) WHERE ( `a` = 'a' OR ( `b` = 'b' AND `c` = 'c' ) ) AND `d` = 'd'
when you have to use table join as well try following method
public function get_all_airports($para) {
$this->db->select('airports.name as air_name, airports.city, airports.type, airports.home_link, country.name as con_name');
$this->db->from('airports');
$this->db->join('country', 'airports.iso_country = country.code', 'inner');
$this->db->where("airports.type !=", "small_airport");
$this->db->where("airports.type !=", "closed");
$this->db->where("airports.type !=", "heliport");
$this->db->where("airports.type !=", "medium_airport");
$this->db->where("airports.type !=", "seaplane_base");
$where = "(country.name LIKE '%$para%' OR airports.city LIKE '%$para%')";
$this->db->where($where);
echo json_encode($this->db->limit(20)->get()->result());
}
Related
I am attempting to build a query on the fly depending upon what is entered in a form. When I do so, I check what the sql statement is in the Console. I have OR and AND contitions, so I use a call back to build the query. the SQL statement that results is:
select `id`, `activity_name`, `activity_name_web`, `year`, `season`, `sex`,
`active_on_web`, `begin_active_on_web`, `end_active_on_web`, `begin_age`,
`end_age`, `begin_date`, `end_date` from `activities` where (season='fall'
OR season='summer' is null) order by `begin_date` desc, `activity_name` asc
limit 25 offset 0 []
notice the words "is null". I can't determine how this phrase is being added.
The Code:
$qry_where = "1";
$arry_Season = array();
if($this->a_fall)
$arry_Season[] = "LOWER(`season`)='fall'";
if($this->a_spring)
$arry_Season[] = "LOWER(`season`)='spring'";
if($this->a_summer)
$arry_Season[] = "LOWER(`season`)='summer'";
if($this->a_winter)
$arry_Season[] = "LOWER(`season`)='winter'";
if(count($arry_Season)>0) {
$qry_where = $arry_Season[0];
if(count($arry_Season)>1){
array_shift($arry_Season);
foreach($arry_Season as $season){
$qry_where .= " OR " . $season;
}
}
}
$activities = Activity::select('id','activity_name','activity_name_web','year','season', 'sex', 'active_on_web',
'begin_active_on_web', 'end_active_on_web', 'begin_age', 'end_age', 'begin_date','end_date')
->where(function($query) use ($qry_where) {
if($qry_where == "1")
$query->where('id','>',0);
else {
$query->where(DB::raw($qry_where));
}
})
->orderBy('begin_date','desc')->orderBy('activity_name','asc')
->paginate(25);
So, if the users checks the box labelled "fall", I add it to the query builder.
so - Where is the phrase "is null" coming from.
select `id`, `activity_name`, `activity_name_web`, `year`, `season`, `sex`,
`active_on_web`,`begin_active_on_web`, `end_active_on_web`, `begin_age`,
`end_age`, `begin_date`, `end_date` from `activities`
where (season='fall' OR season='summer' is null)
order by `begin_date` desc, `activity_name` asc limit 25 offset 0 []
btw, say I check fall and summer, then I ddd($qry_where) just before I build the query, I get this:
"LOWER(`season`)='fall' OR LOWER(`season`)='summer'"
I also need to mention that I am using a livewire component.
thanks for the help in advance.
#apokryfos thank you for your quick answer. It was driving me crazy. It seems when I passed a variable into the ->where(DB::raw()), it evaluated the variable too late for the ->when() to see that the variable contained a comparison?
In any case, I tweeked the solution that #apokryfos a bit and came up with the following:
$activities = Activity::select('id','activity_name','activity_name_web','year','season', 'sex', 'active_on_web',
'begin_active_on_web', 'end_active_on_web', 'begin_age', 'end_age', 'begin_date','end_date',
'cost_member','cost_non_member')
->when(count($seasons) > 0, function($query) use ($seasons) {
$query->whereIn('season', $seasons);
})
->orderBy('begin_date','desc')->orderBy('activity_name','asc')
->paginate($this->items_on_page);
the ->whereIn() could not process the "DB::raw('LOWER(season)', $seasons)" as suggested. If i want to make sure that the data in the [activities].[season] column, I will either have to make sure the seasons are input into the table in lower case, or do a ->select(DB:raw('LOWER(season)') in the SQL statement. I like the first option.
thank you again for your input apokryfos
You did a where(<raw query>) which defaults to do a WHERE <raw query> is not NULL since WHERE assumes a comparison. Here's what I think is a more concise version of your query:
$seasons = array_filter([
$this->a_spring ? 'spring' : null,
$this->a_summer ? 'summer' : null,
$this->a_fall ? 'fall' : null
$this->a_winter ? 'winter' : null
]);
$activities = Activity::select('id','activity_name','activity_name_web','year','season', 'sex', 'active_on_web',
'begin_active_on_web', 'end_active_on_web', 'begin_age', 'end_age', 'begin_date','end_date')
->when(count($seasons) > 0, function($query) use ($seasons) {
$query->whereIn(DB::raw('LOWER(season)'), $seasons);
})->when(count($seasons) == 0, function ($query) {
$query->where('id', > 0); // Not sure you need this part
})
->orderBy('begin_date','desc')->orderBy('activity_name','asc')
->paginate(25);
I am trying to retrieve data from table using codeigniter.
doing something like that:
....
$this->db->where('course_request.enrollment_policy !=', '2');
//I want to write next statements something like:
$this->db->if_where('course_request.enrollment_policy ', '3')
then
$this->db->where('course_request.status', '3');
else
other codeigniter where_in
Hope you got my problem.
Looking for solution, Thanks in advance.
Solved.
who says it is not possible in CI?
$this->db->where('(CASE WHEN `course_request`.`enrollment_policy` = 3 THEN `course_request`.`status` = "3" ELSE course_request.status="0" OR course_request.status = "3" END )' , NULL,FALSE);
Just paste this in your where :
AND (
CASE
WHEN `course_request`.`enrollment_policy` = 3
THEN `course_request`.`status` = '3'
ELSE 1=1
END
)
and give second param NULL , third param FALSE
So I'm just hypothetically thrilled to be querying my hypothetical database:
$query->select($db->quoteName(array('user_id', 'name')));
I would, however, like the query to look like:
SELECT `user_id` AS `uid`, `name` AS `User-Name`
How the heck do I get the AS in there?
I know this question is 6 months old, so you've probably found an answer or worked around it, but for anyone else who has a similar problem:
$query->select($db->quoteName(array('user_id','name'),array('uid','User-Name')));
If you only want to use an alias for some fields, just pass null in the array for the fields you don't want to alias, so for example:
$query->select($db->quoteName(array('user_id','name'),array(null,'User-Name')));
would give
"SELECT `user_id`, `name` AS `User-Name`"
My preferred way is this:
I create an array with the fields I want to select:
$fields = array(
'a.id' => 'id',
'a.field1' => 'field1',
'a.field2' => 'field2',
'a.field3' => 'field3',
'b.field1' => 'bfield1',
'b.field2' => null,
'b.field3' => 'bfield3',
);
In the above array, the keys are used for the db Column names of the query, the values for the aliases, as you can see later in the $query->select().
*When you do not need an alias - just set null.
This helps better to control and check what fields I want and how to name them - and is better for maintenance or changes and is portable enough, as I only have to change my $fields array according to my needs.
Then the Joomla select command can be like:
$query->select( $db->quoteName(
array_keys($fields),
array_values($fields)
));
This will produce the following SQL SELECT query:
SELECT `a`.`id` AS `id`,`a`.`field1` AS `field1`,`a`.`field2` AS
`field2`,`a`.`field3` AS `field3`,`b`.`field1` AS
`bfield1`, `field2`, `b`.`field3` AS `bfield3`
Try the following:
$query->select($db->quoteName('user_id') .' AS '. $db->quoteName('name') .' AS '. $db->quoteName('User-Name'));
Be sure to use the full query as described here:
http://docs.joomla.org/Selecting_data_using_JDatabase
So yours will look something like this:
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->select($db->quoteName('user_id') .' AS '. $db->quoteName('name') .' AS '. $db->quoteName('User-Name'));
$query->from($db->quoteName('#__tablename'));
$db->setQuery($query);
$results = $db->loadObjectList();
Please note that I havent tested this query using AS so let me know if it works or not
I've got this to work:
->select($db->quoteName(array('user_id`' . ' AS ' . '`uid', 'name`' . ' AS ' . '`User-Name')))
It's better to use what Joomla! suggest us.
Note by putting 'a' as a second parameter will generate #__content AS a
So, you may have something like this:
$query
->select('*')
->from($db->quoteName('#__content', 'a'))
I have a custom validation rule that is checking the DB for NULL.
I need to look for null or empty.
HAVE:
$query = $this->db()->table($table);
...
foreach( $null_columns as $col )
$query->where_null($col);
Which results in something like: SELECT * FROM t WHERE col1=foo AND col2 IS NULL
WANT:
SELECT * FROM t WHERE col1=blah AND (col2 = '' OR col2 IS NULL)
QUESTION:
Is where-nested() the right tool for the job?
If so, I'd really like to see an example.
If not, what's a good way to approach this?
Well, I ended up getting it to work this way:
$query = $this->db()->table($table);
...
foreach( $null_columns as $col )
{
$query->where(function($q) use($col){
$q->where($col,'=','');
$q->or_where_null($col);
});
}
... but would still like to see an example of using where_nested() to do this, if possible. I always appreciate learning something new :)
I'm trying to group my entity by a field (year) and do a count of it.
Code:
public function countYear()
{
$qb = $this->getEntityManager()->createQueryBuilder();
$qb->select('b.year, COUNT(b.id)')
->from('\My\Entity\Album', 'b')
->where('b.year IS NOT NULL')
->addOrderBy('sclr1', 'DESC')
->addGroupBy('b.year');
$query = $qb->getQuery();
die($query->getSQL());
$result = $query->execute();
//die(print_r($result));
return $result;
}
I can't seem to say COUNT(b.id) AS count as it gives an error, and
I do not know what to use as the addOrderby(???, 'DESC') value?
There are many bugs and workarounds required to achieve order by expressions as of v2.3.0 or below:
The order by clause does not support expressions, but you can add a field with the expression to the select and order by it. So it's worth repeating that Tjorriemorrie's own solution actually works:
$qb->select('b.year, COUNT(b.id) AS mycount')
->from('\My\Entity\Album', 'b')
->where('b.year IS NOT NULL')
->orderBy('mycount', 'DESC')
->groupBy('b.year');
Doctrine chokes on equality (e.g. =, LIKE, IS NULL) in the select expression. For those cases the only solution I have found is to use a subselect or self-join:
$qb->select('b, (SELECT count(t.id) FROM \My\Entity\Album AS t '.
'WHERE t.id=b.id AND b.title LIKE :search) AS isTitleMatch')
->from('\My\Entity\Album', 'b')
->where('b.title LIKE :search')
->andWhere('b.description LIKE :search')
->orderBy('isTitleMatch', 'DESC');
To suppress the additional field from the result, you can declare it AS HIDDEN. This way you can use it in the order by without having it in the result.
$qb->select('b.year, COUNT(b.id) AS HIDDEN mycount')
->from('\My\Entity\Album', 'b')
->where('b.year IS NOT NULL')
->orderBy('mycount', 'DESC')
->groupBy('b.year');
what is the error you get when using COUNT(b.id) AS count? it might be because count is a reserved word. try COUNT(b.id) AS idCount, or similar.
alternatively, try $qb->addOrderby('COUNT(b.id)', 'DESC');.
what is your database system (mysql, postgresql, ...)?
If you want your Repository method to return an Entity you cannot use ->select(), but you can use ->addSelect() with a hidden select.
$qb = $this->createQueryBuilder('q')
->addSelect('COUNT(q.id) AS HIDDEN counter')
->orderBy('counter');
$result = $qb->getQuery()->getResult();
$result will be an entity class object.
Please try this code for ci 2 + doctrine 2
$where = " ";
$order_by = " ";
$row = $this->doctrine->em->createQuery("select a from company_group\models\Post a "
.$where." ".$order_by."")
->setMaxResults($data['limit'])
->setFirstResult($data['offset'])
->getResult();`