Propel ORM - Custom where clause - mysql

I'm trying to match md5(ID) to an id.
SELECT *
FROM `user` u
WHERE
MD5(`user_id`) = '66f041e16a60928b05a7e228a89c3799'
this is ID = 58
I tried something like this. I know I'm close I just don't know what I'm missing
$criteria = new Criteria();
$criteria->addAnd('md5('.User::USER_ID.')', $_REQUEST['fs'], Criteria::CUSTOM);
$user = UserPeer::doSelectOne($criteria);
Any ideas?

First of all, directly using Criteria objects is deprecated not recommended. You should use Active Query classes.
Using these classes, you will be able to write stuff like this :
UserQuery::create()
->where('md5(User.Password) = ?', $_REQUEST['fs'], PDO::PARAM_STR)
->findOne();
You'll notice that I use the PhpName both of the table and the column in the query.
EDIT : For raw conditions, the parameter type has to be specified. You'll find more information on this issue.

After lenghty T&E process I managed to get it done like this
$c = new Criteria();
$c->add(UserPeer::USER_ID, "md5(user.user_id) = \"".$_REQUEST['fs']."\"", Criteria::CUSTOM); // risk of SQL injection!!
$saved_search = UserPeer::doSelectOne($c);
For some reason PropelORM though that $_REQUEST['fs'] was name of the table rather than the value. \"" solved the problem.

Related

Symfony Query in controller

$query = $em->query("
SELECT c.id AS id
FROM collectif c, zone z
WHERE
c.zone_id = z.id
AND z.label = '$zone'
ANDc.collectif = '$collectif'
");
$c = $query->fetchAll();
$idc = $c['id'];
I have this query that returns a single line, Symfony shows me an error as what variable id undefined
NB: I know that's don't respect the concept of Symfony [MVC] but it's for a particular reason so if someone can tell me how I can resolve this problem
Thank you
$query->fetchAll() should return numeric array of elements so key id does not exists. You should try $c[0]['id'] to get value.
If you'd rather use the results in the assocative way, you can use fetchAssoc() instead:
$c = $query->fetchAssoc();
$idc = $c['id'];
Here is the documentation for reference:
http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/data-retrieval-and-manipulation.html#fetchassoc
I'm just giving an alternate way to do this.

Laravel 5 replicate() handle columns that have unique attribute

I am using laravel's replicate() method of a Model to generate a copy of exiting instance. It works fine if there are no columns that are to be unique
In my case there are some columns that are to be unique so I use this
$pr = Products::find(\Input::get('id'))->replicate();
$pr['product_code'] = $pr->product_code . '_'.$pr['id'];
$pr['name'] = $pr->name . '_'.$pr['id'];
$pr->save();
This will make sure that if a product is replicated once it will handle the unique column problem. But if the product is replicated again it will cause the problem again.
How I can I solve this issue
I would set in database product_code and name as nullables and then do something like this:
$product = Products::find(\Input::get('id'));
$newProduct = $product->replicate(['product_code', 'name']);
$newProduct->save();
$newProduct->product_code = $product->product_code.'_'.$newProduct->id;
$newProduct->name = $product->name.'_'.$newProduct->id;
$newProduct->save();
Of course you could wrap this into a function in case you do it in multiple places.
Recently ran into this issue, most efficient and effective was just to use unix time stamp. Here is another example to give you a better idea of what is going on without having to null fields and such.
$page = Page::find($id);
$duplicatePage = $page->replicate();
$duplicatePage->name = 'Copy of ' . $page->name;
$duplicatePage->slug = $page->slug . '-' . time();
$duplicatePage->save();
following #Marcin NabiaƂek's answer I solved the issue with small enhancements
$product = Products::find(\Input::get('id'));
$newProduct = $product->replicate();
$newProduct->save();
$newProduct->product_code = str_replace("_".$product->id,"",$product->product_code).'_'.$newProduct->id;
$newProduct->name = str_replace("_".$product->id,"",$product->name).'_'.$newProduct->id;
$newProduct->save();
This will remove the old _id from the name and product code for an entry which already has _id at the end and then add the new _id.

zend framework automatically alter queries

My database (mysql) tables use TIMESTAMP columns, and whenever I want them returned in a query, I want them to be queried as "UNIX_TIMESTAMP(columnname)".
How do you easily modify queries in zend framework to achieve this?
For example, the current code is:
select = $this->select();
$select->where('user_id = ?',$user_id);
return $this->fetchAll($select);
This eventually becomes:
select * from tablename where user_id = 42;
I want something that automatically finds the TIMESTAMP column and changes the resulting query to:
select user_id,name,unix_timestamp(created) where user_id = 42;
I know I can use a MySQL view to achieve this, but I'd rather avoid that.
Thanks.
RR
You should be able to specify the fields you want in the select using the $select->from() object.
Zend_Db_Select
You should end up with something like this.
$select = $this->select();
$select->from(
array('t' => 'tablename'),
array('user_id', 'name', 'UNIX_TIMESTAMP(created)')
);
$select->where('user_id = ?',$user_id);
return $this->fetchAll($select);
If you wanted to run an expression that doesn't have parenthese in the function, Use the Zend_Db_Expr() method to escape the query properly.

Propel Query and Mysql aggregate functions: cannot use default syntax (<column> = ?, value) inside where filter

I'm having some troubles creating query conditions in Propel 1.6 using Mysql date functions, such as:
$query = PostQuery::create()->where('YEAR(Post.PublishedAt) = ?', $year)->find();
The following works:
$query = PostQuery::create()->where('YEAR(Post.PublishedAt) = 2011')->find();
But in order to handle a $year variable, I then have to write something like:
$query = PostQuery::create()->where(sprintf('YEAR(Post.PublishedAt) = %d', $year))->find();
which seems wrong.
I've also tried to specify param type by adding: PDO::PARAM_INT const:
$query = PostQuery::create()->where('YEAR(Post.PublishedAt) = ?', $year, PDO::PARAM_INT)->find();
This doesn't work.
UPD: There are no errors. Just an empty collection as a result.
Could anybody help me? Thanks in advance.
According to OP
// works
PostQuery::create()->where('YEAR(Post.PublishedAt) = 2011')->find();
// doesn't work
PostQuery::create()->where('YEAR(Post.PublishedAt) = ?', $year)->find();
This would indicate that PDO is quoting the $year variable so it's actually doing the following when using params
PostQuery::create()->where('YEAR(Post.PublishedAt) = \'2011\'')->find();
As detailed in this bug report https://bugs.php.net/bug.php?id=44639
Do either of these work
PostQuery::create()->where('YEAR(Post.PublishedAt) = CONVERT(?,UNSIGNED)', $year,PDO::PARAM_INT)->find();
or (this is slightly cleaner)
settype($year,'int');
PostQuery::create()->where('YEAR(Post.PublishedAt) = ?', $year,PDO::PARAM_INT)->find();
Seems a bit idiotic to have to do it that way but it should convert the numeric string into a MySQL UNSIGNED INT suitable for the WHERE statement. Either way the above are either having MySQL convert it into a numeric type explicitly, or alternatively trying to ensure that PHP has it explicitly as an INTEGER type before binding it.

How to get Ruby MySQL returning PHP like DB SELECT result

So I use the PDO for a DB connection like this:
$this->dsn[$key] = array('mysql:host=' . $creds['SRVR'] . ';dbname=' . $db, $creds['USER'], $creds['PWD']);
$this->db[$key] = new PDO($this->dsn[$key]);
Using PDO I can then execute a MySQL SELECT using something like this:
$sql = "SELECT * FROM table WHERE id = ?";
$st = $db->prepare($sql);
$st->execute($id);
$result = $st->fetchAll();
The $result variable will then return an array of arrays where each row is given a incremental key - the first row having the array key 0. And then that data will have an array the DB data like this:
$result (array(2)
[0]=>[0=>1, "id"=>1, 1=>"stuff", "field1"=>"stuff", 2=>"more stuff", "field2"=>"more stuff" ...],
[1]=>[0=>2, "id"=>2, 1=>"yet more stuff", "field1"=>"yet more stuff", 2=>"even more stuff", "field2"=>"even more stuff"]);
In this example the DB table's field names would be id, field1 and field2. And the result allows you to spin through the array of data rows and then access the data using either a index (0, 1, 2) or the field name ("id", "field1", "field2"). Most of the time I prefer to access the data via the field names but access via both means is useful.
So I'm learning the ruby-mysql gem right now and I can retrieve the data from the DB. However, I cannot get the field names. I could probably extract it from the SQL statement given but that requires a fair bit of coding for error trapping and only works so long as I'm not using SELECT * FROM ... as my SELECT statement.
So I'm using a table full of State names and their abbreviations for my testing. When I use "SELECT State, Abbr FROM states" with the following code
st = #db.prepare(sql)
if empty(where)
st.execute()
else
st.execute(where)
end
rows = []
while row = st.fetch do
rows << row
end
st.close
return rows
I get a result like this:
[["Alabama", "AL"], ["Alaska", "AK"], ...]
And I'm wanting a result like this:
[[0=>"Alabama", "State"=>"Alabama", 1=>"AL", "Abbr"=>"AL"], ...]
I'm guessing I don't have the way inspect would display it quite right but I'm hoping you get the idea by now.
Anyway to do this? I've seen some reference to doing this type of thing but it appears to require the DBI module. I guess that isn't the end of the world but is that the only way? Or can I do it with ruby-mysql alone?
I've been digging into all the methods I can find without success. Hopefully you guys can help.
Thanks
Gabe
You can do this yourself without too much effort:
expanded_rows = rows.map do |r|
{ 0 => r[0], 'State' => r[0], 1 => r[1], 'Abbr' => r[1] }
end
Or a more general approach that you could wrap up in a method:
columns = ['State', 'Abbr']
expanded_rows = rows.map do |r|
0.upto(names.length - 1).each_with_object({}) do |i, h|
h[names[i]] = h[i] = r[i]
end
end
So you could collect up the rows as you are now and then pump that array of arrays through something like what's above and you should get the sort of data structure you're looking for out the other side.
There are other methods on the row you get from st.fetch as well:
http://rubydoc.info/gems/mysql/2.8.1/Mysql/Result
But you'll have to experiment a little to see what exactly they return as the documentation is, um, a little thin.
You should be able to get the column names out of row or st:
http://rubydoc.info/gems/mysql/2.8.1/Mysql/Stmt
but again, you'll have to experiment to figure out the API. Sorry, I don't have anything set up to play around with the MySQL API that you're using so I can't be more specific.
I realize that php programmers are all cowboys who think using a db layer is cheating, but you should really consider activerecord.