Symfony Query in controller - mysql

$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.

Related

Codeigniter sql binding

How do I use Codeigniter SQL Binding if there are two target dates?
Is how I did it below correct?
public function getInvestmentForBorrowing($id, $Interest, $Currency, $Loantime, $target_date, $Risk_category)
{
$query = '
select CASE WHEN (a.amount_financed - a.amount_invested - a.amount_withdrawn) < a.amount_per_borrower
THEN round((a.amount_financed - a.amount_invested - a.amount_withdrawn), 2)
ELSE round((a.amount_per_borrower) , 2)
END AS investable_amount, a.*,
c.IBAN as Return_IBAN, c.BIC as Return_BIC,
i.average_rate
from investment a
inner join userinfo c
on a.Owner = c.Owner and
c.UPDATE_DT is null
inner join exchange_rates i
on a.Currency = i.currency_id and
? between i.effective_dt and i.expiration_dt
where a.ORIG_ID = ? and
a.Interest <= ? and
a.Currency = ? and
a.status = 2 and
a.Loantime >= ? and
a.Available >= ? and
a.Risk <= ? and
a.UPDATE_DT is null
having investable_amount > 0';
$query = $this->db->query($query, array($target_date, $id ,$Interest, $Currency, $Loantime ,$target_date ,$Risk_category));
$result = $query->result();
return $result;
}
Write now the question marks just represent the array so I added two $target_date to the array but not sure if thats the right way to do it.
It appears to be ok according to the codeigniter documentation but i say that without regard to your original SQL being correct or not.
Just make sure that the number of ? match the number of values you are providing and they are in the right order.
One way to sanity check it, apart from just running it, is to place the following command right after you perform the query:
echo $this->db->last_query();
And providing it known data, you can cheat and just hard code some dummy values for testing, take the generated SQL and throw that into something like phpmyadmin and run it the generated SQL against the Database and see if it works with the expected results.
Just a side note regarding your variable naming style. I see you are mixing cases i.e. things like $target_date (all lower case) and $Risk_category (First letter uppercase). Just be aware that on a linux based system case does matter and mixing like that can cause errors. It's a good idea to decide on one and stick with it.

fetchrow_hashref issue in perl

I am not able to retrieve the output properly using the below code. Please help me to sort it out.
I am getting output differently to run in MySQL and Perl.
As of now it is returning undef when I use Dumper. But I want it to display null.
$reactivate_sth = $dbh->prepare("
SELECT
a,
b
FROM
table
WHERE
c = ?
AND
d = ?
ORDER BY
date DESC
");
$reactivate_sth->execute($c, $d);
print $result = $reactivate_sth->fetchrow_hashref();
OUTPUT:
MySQL:
Empty set (0.00 sec)
Perl:
HASH(0x3068198)
Data::Dumper
VAR1 = undef
You must make your code more readable. It's often useful to use a heredoc to quote SQL statements, like this
my $reactivate_sth = $dbh->prepare(<<END_SQL);
SELECT a, b
FROM table
WHERE c = ? AND d = ?
ORDER BY date DESC
END_SQL
$reactivate_sth->execute($c, $d);
my $result = $reactivate_sth->fetchrow_hashref;
Now $result is a reference to a hash, because you called the fetchrow_hashref method. Printing it will, as you have found, produce something like HASH(0x1cc5a8). You need to access the elements of the hash to make sense of the result
After that, I don't know what output you want. You can use the core Data::Dumper module to display the record that you've retrieved like this
use Data::Dumper;
print Dumper $result;
Does that help? You haven't asked for anything more
Finally I found the solution for this issue. I am not sure this one is a proper fix or not.
Please guide me if the fix is not professional.
if (!defined $result->{''}) {
$result = '';
}

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.

Propel ORM - Custom where clause

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.

Symfony Propel criteria

Is there any possible way to convert the MySQL object into criteria object? I tried this query:
select
p.disrepid,
p.subject, p.body,
c.disrepid as disrepid1,
c.subject as subject1,
c.body as body1
from discusreply as p, discusreply as c
where p.distopid=' . $this->id . '
and (c.disrepid = p.parentid or c.parentid = p.distopid)
order by p.disrepid ASC
I tried a lot for converting this query into a Criteria, But nothing happened. I want this criteria object for passing this into Pager class for completing the pagination.
$pager->setCriteria($c);.
You can use your own SQL do perform a query, but there is no automated way to turn sql into a Criteria object.
$con = Propel::getConnection(DATABASE_NAME);
$sql = "SELECT books.* FROM books
WHERE NOT EXISTS (SELECT id FROM review WHERE book_id = book.id)";
$stmt = $con->createStatement();
$rs = $stmt->executeQuery($sql, ResultSet::FETCHMODE_NUM);
$books = BookPeer::populateObjects($rs);
This bypasses Criterion objects all together. You mentioned wanting a criteria object so you could feed this into a pager. You can instead set a custom select method into your pager, which will then perform your custom query. If you need to pass a parameter into this, I would recommend extending sfPropel with your own pager class that can optionally pass parameters to your peer select methods so you don't have to use Criteria objects at all. As a quick alternative, you can do something like this, using your Criteria as a container for your select parameters:
$c = new Criteria();
$c->add(DiscussreplyPeer::ID, $myId);
$pager = new sfPropelPager();
$pager->setCriteria($c);
$pager->setPeerMethod('getReplies');
And then in your peer class:
public static function getReplies(Criteria $c) {
$map = $c->getMap();
$replyId = $map[DiscussreplyPeer::ID]->getValue();
$con = Propel::getConnection(DATABASE_NAME);
$sql = "select p.disrepid, p.subject, p.body, c.disrepid as disrepid1, c.subject as subject1, c.body as body1 from discusreply as p, discusreply as c where p.distopid=? and (c.disrepid = p.parentid or c.parentid = p.distopid) order by p.disrepid ASC";
$stmt = $con->prepareStatement($sql);
$stmt->setString(1, $replyId);
$rs = $stmt->executeQuery();
$results = array();
while ($rs->next()) {
// for example
$results['disrepid'] = $rs->getInt('disrepid');
}
return $results;
}
More tips on propel and symfony can be found at:
http://stereointeractive.com/blog/2007/06/12/propel-queries-using-custom-sql-peer-classes-and-criterion-objects/
This site will help a lot for learning to write criteria - you can use it to generate criteria code from pseudo SQL. I would also recommend grabbing the Symfony/Propel cheat sheets.
For your query in particular you will want something like this:
$c = new Criteria();
$c->addJoin(discusreply::DISREPID, discusreply::PARENTID, Criteria::INNER_JOIN);
$c->clearSelectColumns();
$c->addSelectColumn(discusreplyPeer::Disrepid);
...
$c->add(discusreplyPeer::DISTOPID, $this->id, Criteria::EQUAL);
...
$c->addAscendingOrderByColumn(discusreply::DISREPID);
I'm not sure that the Criteria system supports multiple clauses for an inner join so you may have to revert back to ad-hoc SQL for this query (if it does I would love to know how). The following code will create a ResultSet object similar to what you would get from simple database abstraction layers.
$sql = "SELECT ...";
$dbh = Propel::getConnection([DB]);
$sth = $dbh->createStatement();
$res = $sth->executeQuery($sql, ResultSet::FETCHMODE_NUM);
I don't think there is much of a disadvantage to using the ad-hoc method on a query like this since you will have to deal with ResultSet objects rather than table-specific objects when you are returning only specific columns.
You can try auto-generating the criteria from sql using this site.