I would like execute a query like this one in symfony using the Propel ORM:
UPDATE ADS SET HITS=HITS+1 WHERE ID=10;
I know that Propel API can let me set a previously fixed value for a column of a given record, but I definitely don't want to retrieve the column value first before issuing an update query since there are concurrent access.
Please, how could I achieve this?
Thanks.
This works in Symfony 1.3/1.4:
in AdsPeer:
public static function incrementHits($id)
{
$con = Propel::getConnection(AdsPeer::DATABASE_NAME);
$query = 'UPDATE hits SET hits + 1 WHERE id = '.$id;
sfContext::getInstance()->getLogger()->crit($query);
$stmt = $con->prepare($query);
$rs = $stmt->execute();
}
To use:
AdsPeer::incrementHits($id);
HTH
Mike
If you like you can do a Select using SQL in propel.
Here's an example:
class BookPeer extends BaseBookPeer {
.
.
.
/**
* Get just the Books that have not been reviewed.
* #return array Book[]
*/
function getUnreviewedBooks() {
$con = Propel::getConnection(DATABASE_NAME);
// if not using a driver that supports sub-selects
// you must do a cross join (left join w/ NULL)
$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);
return parent::populateObjects($rs);
}
You can try this with update as well.
Related
I'm using CakePHP 3, I need to run a raw SQL query on multiple tables. In CakePHP 2, this could be done by using the query() method on any model ( $this->Messages->query("select..") ).
I need the method that allows me to run a SQL query in CakePHP 3. Following is the code snippet I'm using:
$aumTable = TableRegistry::get('Messages');
$sql = "SELECT (SELECT COUNT(*) FROM `messages`) AS `Total_Count`,
(SELECT COUNT(*) FROM `messages_output`) AS `Total_Output_Count`,
(SELECT COUNT(*) FROM `messages_output` WHERE `is_success`=1) AS `Total_Successful_Output_Count`,
(SELECT COUNT(*) FROM `messages_output` WHERE `is_success`=0) AS `Total_Error_Output_Count`,
(SELECT COUNT(*) FROM `users`) AS `Total_User_Count`;";
// to run this raw SQL query what method should i use? query() doesn't work..
// $result = $aumTable->query($sql); ??
// $result = $aumTable->sql($sql); ??
If you can provide links to CakePHP 3 model documentation where I can find this info, that would be helpful too. I tried searching on google but could only find questions related to CakePHP 2.
First you need to add the ConnectionManager:
use Cake\Datasource\ConnectionManager;
Then you need to get your connection like so:
// my_connection is defined in your database config
$conn = ConnectionManager::get('my_connection');
More info: http://book.cakephp.org/3.0/en/orm/database-basics.html#creating-connections-at-runtime
After that you can run a custom query like this:
$stmt = $conn->execute('UPDATE posts SET published = ? WHERE id = ?', [1, 2]);
More info: http://book.cakephp.org/3.0/en/orm/database-basics.html#executing-queries
And then you are ready to fetch the row(s) like this:
// Read one row.
$row = $stmt->fetch('assoc');
// Read all rows.
$rows = $stmt->fetchAll('assoc');
// Read rows through iteration.
foreach ($rows as $row) {
// Do work
}
More info: http://book.cakephp.org/3.0/en/orm/database-basics.html#executing-fetching-rows
The documentation for this is here: http://book.cakephp.org/3.0/en/orm/database-basics.html#executing-queries
But what's not written there is how to execute it. Because it cost me a while, here is the solution for that:
1.You need to add
use Cake\Datasource\ConnectionManager;
2.init the ConnectionManager (as mentioned above)
$conn = ConnectionManager::get('my_connection');
3.Execute your SQL with something like this
$firstName = $conn->execute('SELECT firstname FROM users WHERE id = 1');
The question is already very old, but I still find it frequently.
Here is a solution for CAKEPHP 3.6 and (short) for newer PHP Versions.
It is not necessary to use the ConnectionManager get function and often it does not make sense, as the connection name may not be known at all. Every table has its / a connection which one can get with getConnection ().
If you are already in the Messages Table (src/Model/Table/MessagesTable.php), you can simply use the Connection
$con = $this->Messages->getConnection();
If you are not there (what your code would suggest with TableRegistry::get(), you can do that with this table as well
// $aumTable is declared in question
$con = $aumTable->getConnection();
then you can execute a RAW query as shown above:
$result = $con->execute ();
// short
$result = $this->Messages->getConnection()->execute ('Select * from ...')
// or ($aumTable is declared in question)
$result = $aumTable->getConnection()->execute ('Select * from ...');
For the user I am testing with, their org_id column value is "student_life"
I am trying to have this function display whatever rows have the student_life column = 1. (so yes there is a column student_life which is a boolean, and then I also have a separate column named org_id and in this case has the value student_life)
I am pretty sure there is a syntax error but I cannot figure it out.
function org_id_users_table()
{
$org_id = mysql_real_escape_string($_POST["org_id"]);
$sql = $this->query("SELECT * FROM ".DBTBLE." WHERE '$org_id' = '1'");
$result = $sql['sql'];
$num_rows = $sql['num_rows'];
$this->create_table($result, $num_rows);
}
(when I replace $org_id in the "$sql=..." line with student_life the code works.
You're quoting the column name, which makes MySQL think it's a string.
$sql = $this->query("SELECT * FROM ".DBTBLE." WHERE $org_id = '1'");
Edit:
Based on your comments, I think what you actually want is this:
$sql = $this->query("SELECT * FROM ".DBTBLE." WHERE org_id = '$org_id'");
Change quotes.
$sql = $this->query("SELECT * FROM ".DBTBLE." WHERE `$org_id` = '1'");
P.S. Why shouldn't I use mysql_* functions in PHP?
Where is this coming from? $_POST["org_id"]
Do you have a form on the page posting that? Or are you just trying to get that from the database? If so, wouldn't you need another query to obtain that first?
$row_MyFirstQuery['org_id']
Otherwise if it is $_POST["org_id"], wouldn't it be single quotes not double? $_POST['org_id']
I updated with success
$result = mysql_query("UPDATE $table SET `queue2` = `queue2` + 1 WHERE `id` = '$getid'");
but how can I get the "queue2" value without opening a new request to MySQL
I can simply get the new value with this command
$selresult = mysql_query("SELECT * FROM $table WHERE `id` = '$getid'") or die(mysql_error());
but I'm afraid that the database can get new update again and i will get higher number
Any idea how to do it ?
you can use query to update the value.
mysql_query("UPDATE user_profile SET userpoints = userpoints + 1 WHERE user_id = '".$user_id."'");
See URL:-
PHP + MySQL transactions examples
Try this:-
printf ("Updated records: %d\n", mysql_affected_rows());
mysql_query("COMMIT");
You will need to use a transaction between the queries to be certain.
The docs for transactions are here. A good SO question that covers it in detail: PHP + MySQL transactions examples
Edit:
Looking at it from a different angle, why don't you do it in reverse though? It might save the need for a transaction (thought it is possible that you get multiple reads before a write):
Get the value for your queue2 value to display in the page from this:
mysql_query("SELECT * FROM $table WHERE `id` = '$getid'");
You have the true value now, so you can run:
$result = mysql_query("UPDATE $table SET `queue2` = `queue2` + 1 WHERE `id` = '$getid'");
No transaction and you know the value of the data before the update.
I have a datatable with user information and a column called 'Bits'. There is a transfer function and I would like to transfer x amount of bits from the logged in user to the user they specify. I have the following function that works, but I would like to know if there is a better (simpler, cleaner, quicker?) way to do all of this, and possibly return the row of the first SQL statement at the end. I am not an advanced MySQL user by any means, but I am pretty sure there is a function I am missing that could make this much easier.
function transferBits($toid, $amount)
{
global $loggedInUser, $db;
$fromid = $loggedInUser->user_id;
$sql = "INSERT INTO `dl_Transfers` SET From_ID = '".$db->sql_escape($fromid)."',
`To_ID`='".$db->sql_escape($toid)."',
`Bits`='".$db->sql_escape($amount)."',
`When`=Now()";
$result = $db->sql_query($sql);
$sql2 = "UPDATE `dl_Users` SET Bits = Bits - '".$db->sql_escape($amount)."' WHERE `User_ID` = '".$db->sql_escape($fromid)."'";
$result2 = $db->sql_query($sql2);
$sql3 = "UPDATE `dl_Users` SET Bits = Bits + '".$db->sql_escape($amount)."' WHERE `User_ID` = '".$db->sql_escape($toid)."'";
$result3 = $db->sql_query($sql3);
}
I think you could hit the update in single query by joining on the previous record id from your insert on dl_Transfers:
UPDATE `dl_Transfers` r
JOIN `dl_Users` f ON ( r.From_ID = f.User_ID )
JOIN `dl_Users` t ON ( r.To_ID = t.User_ID )
SET f.Bits = f.Bits - r.Bits, t.Bits = t.Bits + r.Bits
WHERE r.Transfer_ID = ?;
Also as others stated in their comments, you should definitely use transactions here.
You might consider using a MySQL trigger to handle this. Basically, you would set it up so anytime there is an insert on dl_Transfers, it updates the appropriate rows in dl_Users.
http://dev.mysql.com/doc/refman/5.0/en/triggers.html
Here's my issue: I have 3 tables, with overlapping information (specifically, the username) in each. Except the username row isn't named the same thing in every table. Because the username is specific to the user, it makes sense to get all the other information about the user based on the username. Here's what I have. (The first function returns the query, the second function returns the information in an array (or is supposed to, anyway).
function get_user_by_id($id) {
global $connection;
$query = "SELECT * FROM ownerOrganization, owner, queue_acl";
$query .=" WHERE owner.ownerId=ownerOrganization.ownerId";
$query .=" AND owner.ownerId=queue_acl.user_id";
$query .= " AND owner.ownerId ='{$id}'";
$result_set = mysql_query($query);
confirm_query($result_set);
if ($user = mysql_fetch_array($result_set)) {
return $user;
} else {
return NULL;
}
}
function get_user_id() {
if (isset($_GET['ownerId'])) {
return get_user_by_id($_GET['ownerId']);
}
}
But when I do something like, $sel_user = get_user_id(); on another page, it doesn't actually pull up any of the selected users information... I assume that this is happening because my syntax regarding working with multiple tables is incorrect. Anyway, any input would be much appreciated.
To use JOINS, take this snipcode in example :
$query = "SELECT * FROM (ownerOrganization INNER JOIN owner ON owner.ownerId=ownerOrganization.ownerId) INNER JOIN queue_acl ON owner.ownerId=queue_acl.user_id";
$query .=" WHERE owner.ownerId ='{$id}'";
Regards
I was typing what more or less what #MTranchant wrote. I would suggest renaming your columns for easier query authoring and to avoid confusion. For instance your ownerOrganization.ownerid could be named oo_ownerid, and the other columns in the table could follow that naming convention.
Also, have you run the query against the database with a hard-coded $id that you know exists?
Lastly in the query string being sent to the next page, does a ownerId parameter appear that looks like "&ownerId="?