Wierd bug in CodeIgniter when I queried two tables with relationship... o_O - codeigniter

So I got a wierd bug (or maybe I'm just stupid), when I runs an active record query. Take a look at this:
$results = $this->db->
select('cd.casino_name, cd.casino_opened, cd.casino_latitude, cd.casino_longitude')->
from('casino_data as cd, casino_cities as cc')->
where('cd.city_id',$city_id)->
where('cd.city_id=cc.city_id')->
get()->result_array();
Then I got that:
Error Number: 1054
Unknown column 'cd.city_id=cc.city_id' in 'where clause'
SELECT `cd`.`casino_name`, `cd`.`casino_opened`, `cd`.`casino_latitude`, `cd`.`casino_longitude`
FROM (`m_casino_data` as cd, `m_casino_cities` as cc)
WHERE `cd`.`city_id` = 1
AND `cd`.`city_id=cc`.`city_id`
Filename: httpdocs/_dev/libraries/Test.php
Line Number: 649
Sh*t happened... Or in v2.0 CI has been changed something in the DB class?
help plz...thx

The problem is there with the where clause
$results = $this->db->
select('cd.casino_name, cd.casino_opened, cd.casino_latitude, cd.casino_longitude')->
from('casino_data as cd, casino_cities as cc')->
where('cd.city_id',$city_id)->
where('cd.city_id','cc.city_id')->//this would produce WHERE cd.city_id = cc.city_id
get()->result_array();

CodeIgniter's AR protecting works poorly sometimes. In this cases I think you should use an optional parameter FALSE to avoid autoprotecting. But not all function accepts this parameter - but where yes!
$this->db->where() accepts an optional third parameter. If you set it to FALSE, CodeIgniter will not try to protect your field or table names with backticks.
See documentation (you can find near 4. Custom string).

Related

Binding on `statement` not supported in Eloquent 5.1?

I'm new to Laravel and trying to do a string query in Eloquent. I was trying to use DB::statement, but I kept getting errors about placeholders in the query string. It seems I either don't have the syntax right, or bindings are unimplemented or unsupported?
The reason I want to use statement is because I'm doing an INSERT... SELECT, which I haven't been able to find any documentation about in Eloquent.
Here's my code:
$ php artisan tinker
Psy Shell v0.5.2 (PHP 5.6.13-0+deb8u1 — cli) by Justin Hileman
>>> echo \DB::statement('CREATE DATABASE :db', [':db'=>'test']);
Illuminate\Database\QueryException with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 1 (SQL: CREATE DATABASE :db)'
>>> \DB::statement('CREATE DATABASE ?', ['test']);
Illuminate\Database\QueryException with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 1 (SQL: CREATE DATABASE test)'
These are the two syntax forms (? and :string) from PDO. Other methods in DB such as select and insert support this, according to the documentation.
The relevant parts of these errors are near '?' at line 1 (SQL: CREATE DATABASE :db) and near '?' at line 1 (SQL: CREATE DATABASE test). MySQL thinks there is an unbound ? in the query string. I didn't even use that syntax in the first query. I'm concluding from that that the bind() method did not correctly bind my placeholders.
This question on Laracasts is asking about the syntax, but there is no accepted answer.
Edit One answer says that statement() doesn't support CREATE. I tried some queries out with SELECT, and got the same results, with both placeholders:
>>> \DB::statement('SELECT 1 WHERE \'a\' = ?', array('a'));
Illuminate\Database\QueryException with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE 'a' = ?' at line 1 (SQL: SELECT 1 WHERE 'a' = a)'
>>> \DB::statement('SELECT 1 WHERE \'a\' = :letter', array(':letter'=>'a'));
Illuminate\Database\QueryException with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE 'a' = ?' at line 1 (SQL: SELECT 1 WHERE 'a' = :letter)'
Actually, you can use create and drop query in DB::statement(), but named bindings is not used in that way.
Here are some queries that will success.
drop and create do not accept bindings.
>>> \Db::statement('create database test')
=> true
>>> \Db::statement('drop database test')
=> true
Do not use backslash and single quotes in the statement
>>> \Db::statement('insert into users (id, name) values (?, ?)', ['1', 'John'])
=> true
DB::statement() only return ture when success, so if you want to see select results, you should use DB::select()
>>> \Db::statement('select * from users')
=> true
>>> \Db::select('select * from users')
=> [
{#770
+"id": 1,
+"name": "John",
},
]
Remove leading : in the second argument.
>>> \Db::statement('update users set name = :name where id = :id', ['id' => 1, 'name' => 'John'])
=> true
You will get affect rows if you use DB::update and DB::delete
>>> \Db::delete('delete from users where id = :id', ['id' => 1])
=> 1
The errors you receive are only indirectly related with Laravels DB::statement() function. They all fail within that method at the line
return $me->getPdo()->prepare($query)->execute($bindings);
within the file vendor/laravel/framework/src/Illuminate/Database/Connection.php
Responsible for that failure is the resulting call to PDO::prepare()
The Docuemenation says:
Parameter markers can represent a complete data literal only. Neither part of literal, nor keyword, nor identifier, nor whatever arbitrary query part can be bound using parameters. For example, you cannot bind multiple values to a single parameter in the IN() clause of an SQL statement.
Also have a look at the user contributed notes at the above php.net documentation. Additionally have a look at Can PHP PDO Statements accept the table or column name as parameter?
Your create examples are not supported by PDO.
The reason your SELECT examples fail is simply due to an invalid syntax.
\DB::statement('SELECT 1 WHERE \'a\' = ?', array('a'))
You are simply missing the FROM clause. This example works perfeclty well at my test computer:
$ret = \DB::statement('SELECT 1 FROM `users` WHERE `username` = ?', ["gregor"]);
But
$ret = \DB::statement('SELECT 1 WHERE `username` = ?', ["testname"]);
Generates the exact error, you receive.
Also note, that \DB::statement does not return any ressources. It just indicates by returning true or false, whether the query suceeded.
Your option is to use DB::raw() within your insert() statement, if you want to use INSERT...SELECT. Some googling will help you, to find the proper solution. Maybe as Starting Points: Raw Queries in Laravel, or How to use raw queries in Laravel
What you're trying to do is passing the table name through binding.
DB::statement('select * from ?',['users'])
which according to this post, it's not possible.
of course if you want to sanitize the data you can use an array of short codes like so:
$tables = ['users','test','another'];
and the query would look something like:
$code = 0;
DB::statement("select * from $tables[$code] where a=?",[2]);
DB::statement("create table $tables[$code]");

Codeigniter select_avg('columnname') WHERE thisaverage > x

What I want to do is select items from my database where the average review is greater than 7.
$this->db->select_avg('reviews.overall');
That query selects the average review 'as overall'.
Therefore i assumed i could simply then use
$this->db->where('overall>','7');
This however does not work.
ANy ideas?
Thanks
EDIT
Putting in a space
$this->db->select_avg('reviews.overall');
$this->db->where('overall >','7');
Yields the error
Column 'overall' in where clause is ambiguous
It is ambiguous but how am I now meant to reference it??
Thx
It's writen in the codeigniter user manual too:
$this->db->select_avg(); Writes a "SELECT AVG(field)" portion for your query. As with select_max(), You can optionally include a second parameter to rename the resulting field.
If you enable profiler in CI, you would see, what query does this code generate.
Your code is generated like this:
SELECT AVG(reviews.overall) as reviews.overall FROM ....
Use it like this:
$this->db->select_avg('reviews','overall');
$this->db->from('table name');
$this->db->where('overal >', 7);
$Q = $this->db->get();

ActiveRecord search returns 'Syntax error or access violation' error

In my Yii application, I have a model that represents siteconfig table and have four columns:
integer config_id,
string key,
string value,
string update_time.
I created a model using Gii (to ensure that I will not make any mistakes). I don't publish entire code here, cause this is 100% unmodified by me, standard model code generated by Gii. Since my problem is related to search, I only publish important part of generated code (the search() method):
public function search()
{
// Warning: Please modify the following code to remove attributes that
// should not be searched.
$criteria=new CDbCriteria;
$criteria->compare('config_id',$this->config_id);
$criteria->compare('key',$this->key,true);
$criteria->compare('value',$this->value,true);
$criteria->compare('update_time',$this->update_time,true);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
));
}
I'm trying to use generated model in normal Yii ActiveRecord search like that:
$etona = new SiteConfigurationRecord();
$crit = new CDbCriteria();
$crit->select = "value";
$crit->condition = "key=:key";
$crit->params = array(":key"=>"sitename");
$etona = $etona->find($crit);
But, instead of getting expected search results, a strange (for me) error occurs:
CDbCommand failed to execute the SQL statement: SQLSTATE[42000]:
Syntax error or access violation: 1064 You have an error in your SQL
syntax; check the manual that corresponds to your MySQL server version
for the right syntax to use near 'key='sitename' LIMIT 1' at line 1.
The SQL statement executed was: SELECT value FROM siteconfig t
WHERE key=:key LIMIT 1
Where did I go wrong?
You used key for column name, which is a reserved word in MySQL. Yii uses table alias in queries, but does not take any special care in case of reserverd word used as columns names. So, you have to take care of this by yourself.
For example:
$etona = new SiteConfigurationRecord();
$crit = new CDbCriteria();
$crit->select = "value";
$crit->condition = "t.key=:key"; // 't' is default alias
$crit->params = array(":key"=>"sitename");
$etona = $etona->find($crit);
This should solve your problem.
As #Dmitry explained, SQL doesn't allow you to use the column name key. The Yii call in the code in your answer works because Yii performs parameter binding automatically, using names other than reserved words for the parameters. And it also uses fully-qualified column names (prefixes all column name references with <tablename>., regardless of what invalid column name (reserved words) you pass the findByAttributes method.
now it works.. ^^
i just use this code...
$etona = SiteConfigurationRecord::model()->findByAttributes(array('key'=>'sitename'));
maybe i need to study activerecord more somehow...
but still i don't know why the code above doesn't work

Issue with where clause in active record class

$params['title'] is a string and $params['feed'] is an integer. Column's 'title' type is varchar and column's 'feed' type is integer. The PHP code is:
$this->db->where('title', $params['title']);
$this->db->where('feed', $params['feed']);
$query = $this->db->get('news');
So everything should be fine, BUT...
A Database Error Occurred
Error Number: 1064
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'riots: intense anger after deaths of three young men AND `feed` = '1'' at line 3
SELECT * FROM (`news`) WHERE `title` = Birmingham riots: intense anger after deaths of three young men AND `feed` = '1'
Filename: C:\path\system\database\DB_driver.php
Line Number: 330
Of course, it's obvious why an error occurred. Is there any way to fix it (apart from not using active record class)? Looked at CI's documentation, but have no idea why this problem occurred.
EDIT
Solved by changing to
$this->db->where('title', (string) $params['title']);
And other clause accordingly. And now have a bunch of identical errors in other models. Well, I guess the only solution is to add var type everywhere manually.
It looks like this SimpleXML class's title property isn't a string.
You could simply cast it to a string as soon as you get it, instead of waiting until you do the insert.
data['title'] = (string) $item->title;

CodeIgniter: Unknown column xxx in ‘where clause’

I am working on a bug(?) for a few hours now, but couln’t fix it.
This is my code:
if(!$this->db->get_where('merken',array('m_merken' => $brand))->count_all_results()){
$insetData = array('m_name' => $brand);
$this->db->insert('merken', $insetData);
}
$brand contains ‘Acer’ in this preview.
A Database Error Occurred
Error Number: 1054
Unknown column ‘Acer’ in ‘where clause’
SELECT * FROM (`merken`) WHERE `m_name` = Acer
I want to check if it already exists, but it won’t work very well.
Without quotes, your statement:
SELECT * FROM (`merken`) WHERE `m_name` = Acer
Acer refers to a column-name. If your intent is a string literal, put it in single-quotes, as in:
SELECT * FROM (`merken`) WHERE `m_name` = 'Acer'
Also, as a matter of good programming practice, avoid SELECT *, better to SELECT each column you want to return, even if the list is lengthy.
-- EDIT --
I suspect I'm missing the point... the SQL is generated. Two things to check:
Is m_name correctly declared as a string/varchar/char field?
Failing that, try literally setting the brand name to 'Acer', with the quote marks. I doubt this is a reasonable solution, though.

Resources