Zend framework 3 ORDER BY FIELD - zend-framework

How would you write the following query in Zend framework 3 ?
SELECT * FROM table_name ORDER BY FIELD(field_name, 'a','b','c');
I tried
$select->order(new Expression("FIELD(field_name, 'a', 'b', 'c')"),field_name);
but not moves...

I think you made a mistake somewhere, make sure that you've:
Imported Expression correctly with use.
removed the second argument form order(), there is none.
Zend\Db\Sql\Expression is the correct way to extend a query with DBMS-specific expressions.
With the following test script I get your expected result:
$platform = new Zend\Db\Adapter\Platform\Mysql();
$select = new Zend\Db\Sql\Select();
$select->from(['t' => 'table_name']);
$select->order(
new Zend\Db\Sql\Expression(sprintf(
"FIELD(t.%s, 'a', 'b', 'c')",
$platform->quoteIdentifier('field_name')
))
);
var_dump($select->getSqlString($platform));
Result is:
string(81) "SELECT `t`.* FROM `table_name` AS `t` ORDER BY FIELD(t.`field_name`, 'a', 'b', 'c')"
Few notes here:
Replace the Zend namespace with Laminas when you using Laminas instead.
Make sure you always quote identifiers with quoteIdentifier() from the platform instance (you should be able to receive the platform from your table or DB instance).
Use table aliases where you can, as an extra level of security against SQL Injections and they also make your life easier.
On big tables with thousand of rows I guess you're query will get very slow. So you can either add an index and if this doesn't work create another column with the pre-calculated value from FIELD() (you can either do this in your application or on the DDL level).

Instead of using expression, can you give string to order method
$select->order("FIELD(field_name, 'a', 'b', 'c')");
If field name is a variable
$select->order("FIELD(" . $field_name . ", 'a', 'b', 'c')");
If the issue still persists, then we can trace the issue by printing the query
$select->query()->__toString()
or
$select->__toString();
dont remember the query exactly, you can try them

Related

Does CodeIgniter Query Builder protect against sql injection even in more complexed queries?

I know that using CodeIgniter's Query Builder should protect against SQL injection. The Manual says that it "allows for safer queries, since the values are escaped automatically by the system." But I'm not sure if by "values" they mean anything that goes through the Query Builder, or only values that are passed in simple stucture like : $this->db->where('name', $name);
For instance, if I use:
$this->db->select('student_id, concat(fname, " ",lname) as student_name');
$this->db->from('student');
$this->db->join('class_has_teacher',"student.class_id=class_has_teacher.class_id AND teacher_id=$teacher_id");
$query = $this->db->get();
Would the $teacher_id in the JOIN condition also be escaped?
(In case it matters, I'm using CodeIgniter 3.1.9)
Yes, $teacher_id would be escaped.

Can I use rowmode: 'array' in combination with named parameters?

Is it possible to have rowMode: 'array' and named parameters at the same time? Right now, with the code below, I'm getting syntax error at or near "$"
db.query({
text: `
select task_nr, commitment
from surveys
where email = $<email> and id = $<id>
order by task_nr
`,
values: {email: email, id: id},
rowMode: 'array',
})
No, it is not possible, because rowMode is strictly part of the Parameterized Query, which by definition forwards query formatting to the driver->server where such thing as Named Parameters does not exist.
Unfortunately, if you really need to use rowMode, you can only use the basic $1, $2... variable formatting as supported by the server.
Strictly speaking, rowMode is not that valuable, it is fairly easy to reformat the data, and then just use pg-promise default formatting with all its nice formatting features.

Laravel WhereIn with multiple options in the field itself

Normally a whereIn in Eloquent compares a value from a field to an array with options. I like to reverse that and compare a option to multiple options in the field:
field contains 'option1,option2,option3'
Model::whereIn('field', 'option1')->get();
Is this possible?
You can make your query using LIKE:
Model::where('field', 'LIKE', '%option1%')->get();
Documentation on the syntax is available here: http://dev.mysql.com/doc/refman/5.7/en/pattern-matching.html
If you always add a comma , even after the last choice, like option1,option2,option3, you can use a bit of a more robust filter:
Model::where('field', 'LIKE', '%option1,%')->get();
And a comma at the start (or any other separator if that matters) would make it even better:
Model::where('field', 'LIKE', '%,option1,%')->get();
Otherwise you can have issues if one of your option is similar to another one at the end (if you have fish and goldfish as possible categories, using LIKE ',fish,' will guarantee that you don't match goldfish, while LIKE 'fish,' would match both fish and goldfish).
I'd recommend to store your categories like that: /fish/goldfish/water/ and then filter using LIKE '%/yourcategory/%'

PHP mongoDb driver , fetching data and then deleting it , is not working

This is the sample code :
$r = $coll->findOne();
$coll->remove(array("_id"=>$r["_id"])); // use the same object id as retreived from DB
$ret=$coll->findOne(array("_id"=>($r["_id"])));
var_dump($ret); // dumps the records that was supposed to be deleted
The records in the collection have MongoDB objectId, and not strings.
Same logic on console works fine and deleted the record correctly.
This is working for me. Here's the code:
$coll->drop();
print("Now have ".$coll->count()." items\n");
$coll->insert(array("x" => 'blah'));
$coll->insert(array("x" => "blahblah"));
print("Inserted ".$coll->count()." items\n");
$x = $coll->findOne();
print("Object X\n");
print_r($x);
$query_x = array('_id' => $x['_id']);
$coll->remove($query_x);
print("Removed 1 item, now have ".$coll->count()." items\n");
$y = $coll->findOne($query_x);
print("Object Y\n");
print_r($y);
Here's the output:
Now have 0 items
Inserted 2 items
Object X
Array
(
[_id] => MongoId Object
(
[$id] => 4d8d124b6803fa623b000000
)
[x] => blah
)
Removed 1 item, now have 1 items
Object Y
Are you sure there's not a typo somewhere?
Unlike the php == operator, mongo's equality operator always uses "Object equality" which is like php's identical comparison operator (===) or java's .equals(). While your code looks as though it should work (and it does work fine for me with a test dataset), something about your dataset may be causing php to cast the returned MongoId to a string. Read more about MongoId here.
Make sure that your query is supplying a MongoId for comparison by doing a var_dump of the query itself. Also, make sure that you are running the latest version of the PHP Mongo driver.
Since PHP is loosely typed it is most important to ensure that you cast all input values and search values to the expected and consistent data type otherwise it will surely not locate your expected document.
While using MongoDB within PHP I make it a point to cast everything intentionally in order to avoid any possible confusion or error.
Also, the mongodb-user group at groups.google.com is very good and responsive so if you are not already utilizing that resource I would definitely consider joining it.

Zend Framework how to echo value of SUM query

I created a query for the zend framework, in which I try to retrieve the sum of a column, in this case the column named 'time'. This is the query I use:
$this->timequery = $this->db_tasks->fetchAll($this->db_tasks->select()->from('tasks', 'SUM(time)')->where('projectnumber =' . $this->value_project));
$this->view->sumtime = $this->timequery;
Echoing the query tells me this is right. But I can't echo the result properly. Currently I'm using:
echo $this->sumtime['SUM(time)'];
Returning the following error:
Catchable fatal error: Object of class Zend_Db_Table_Row could not be converted to string in C:\xampp\htdocs\BManagement\application\views\scripts\tasks\index.phtml on line 46
Line 46 being the line with the echo in my view.
I've been searching now for two days on how to figure this out, or achieve the same result in a different way. Tried to serialize the value, but that didn't work either.
Is there somebody who knows how to achieve the total sum of a database column?
Any help is greatly appriciated!
note: Pretty new to zend framework...
Zend_Db has some nice utility methods like fetchAll (which you're using) to fetch different types of data:
fetchAll - for a set of rows
fetchRow - for a single row
fetchOne - for a single cell
Most simply:
$sum = $db->fetchOne('SELECT SUM(time) FROM tasks WHERE project_number = ?', $this->value_project);
You can use Zend_Db_Select with these methods too, like in your question:
//note that the SUM(time) part is passed as a Zend_Db expression, as it is not a column
$select = $this->db_tasks->select()
->from('tasks', new Zend_Db_Expr('SUM(time)'))
->where('projectnumber =' . $this->value_project);
$this->timequery = $this->db_tasks->fetchOne($select);
This works because the Zend_Db_Select object implements a toString method, to produce SQL.
$timequery= $timequeriestb->select(Zend_Db_Table::SELECT_WITH_FROM_PART)
->columns('SUM(time) AS Totaltime')
->where('projectnumber ='. $this->value_project));
The SQL you want is probably:
SELECT SUM(time) AS time_sum FROM tasks ...
Not sure how to do this in Zend. Then:
echo $this->sumtime['time_sum'];