Php variable initialise to database queries - php

For a particular process I am storing a list of mysql queries in Database using php variables for condition data retrieval.
I'm storing:
Select count(1) from Users where user='$user1'
I have written a script where I first initialize: $user1="XYZ";
Then I select the above query from database and try to execute it again using mysql_query.
But the value of $user1 is not getting initialized as required.
Please fidn below the psuedo code:
$user1="xyz";
//selecting the query
$select_table="SELECT * FROM `test`";
$result_table=mysql_query($select_table);
$select_query=mysql_result($result_table,$j,"Select_Query");
$panelinttable_result=mysql_query($select_query);

This will not work as when you retrieve data, $user1 will not be a variable but a part of string "Select count(1) from Users where user='$user1'".
Using str_replace() should work :
$select_query = mysql_result($result_table,$j,"Select_Query");
$select_query = str_replace('$user1', $user1, $select_query);
$panelinttable_result=mysql_query($select_query);
Also, why are you storing those queries in database ?
It would be better to make functions for this.
function userExists($user) {
$query = mysql_query("Select count(1) from Users where user = '".$user."'");
return mysql_num_rows($query);
}

Related

handling database with php best option

i am doing a mini project of social networking , i am having a doubt about table .
let see , i need to provide post in their page. to do this,should i have to create table for each user or just create one table and use it for multiple users (data can be fetched by selecting particular user name and display it in their page ).
which is the best way?
my php code:
<?php
$query="select * from table_name where user=$username order by time desc;";
?>
To answer your question
It's best to just use 1 table of users and have a separate able for your posts. Your users table should have all the information for each specific users with 1 unique value that is automatically generated by the MySQL database. (Use auto-increment) And in the posts table you should have all the data for each post with a user_id column that holds the unique value from the users table, this way you know who posted it.
Here is a mockup table structure:
Users table:
uid | name | email
Posts table:
uid | user_id | message
user_id in the posts table should always be equal to some uid in the users table.
Every single table should always have some unique value that is assigned its primary value
My real concern
I am very concerned with the security of your application. Prepared statements are WAY easier to use, and WAY more secure.
In the code snippet that you shared:
<?php
$query="select * from table_name where user=$username order by time desc;";
?>
this query is very insecure, as Bobby Tables would tell you. I'm not sure why type of database connection you are using, but I suggest PDO. I wrote a function that makes this very very easy, here is the snippet for that:
This is a file I usually call connection.php that you can import on any page you need to use your database.
<?php
$host = 'localhost';
$db = '';
$user = '';
$pass = '';
$charset = 'utf8';
$dsn = "mysql:host={$host};dbname={$db};charset={$charset}";
$opt = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
$pdo = new PDO($dsn, $user, $pass, $opt);
function pdoQuery($query, $values = []) {
global $pdo;
if(!empty($values)) {
$stmt = $con->prepare($query);
$stmt->execute($values);
} else {
$stmt = $con->query($query);
}
return $stmt;
}
?>
This function allows you to EASILY use prepared statements by just
including the connection.php page and writing queries in a way that is
readable, clean, and secure. As I'm sure a lot of people reading this are not used to Prepared Statements or know how they
work, the rest of this post will explain that.
One of the biggest differences here is that instead of using String
Interpolation in
your query, you will set variables as question marks ?, so your
query looks like this: UPDATE table SET user=? instead of UPDATE
table SET user='$user' - and the variables will be sent later for
safety, so this prevents SQL Injection.
This it the way your query would look now:
pdoQuery("SELECT * FROM `table_name` WHERE user=? ORDER BY `time` DESC", [$username]);
This is basically how it works:
pdoQuery(string $query, array $variables)
If you pass no variables, it automatically uses the query() function, if you do pass variables it automatically binds and executes the statements. No matter what query you do, the function always returns the query as an object, so you can act on it using any method you can normally use on a PDO query after the execute.
If you know how these work, you can stop reading here :) I put some
exmaples below of some of the ways you can manipulate the return data
to do what you need to do.
This function returns the object of the query you requested, so if you wanted to loop through all of the results of your query you use it like this:
$stmt = pdoQuery("SELECT * FROM `table_name` WHERE `user`=? ORDER BY time DESC", [$username])->fetchAll();
foreach($stmt as $row) {
$row['name']."<br>";
}
Or if you just wanted to get a single column from a specific row, you could use it like this:
$username = pdoQuery("SELECT `username` FROM `users_table` WHERE uid=? ORDER BY `time` DESC", [$uid])->fetchColumn();
Which will return the username from user where uid=$uid as a string
or if you wanted several values from 1 specific row, you could do
$user = pdoQuery("SELECT `username`,`name`,`email` FROM `users_table` WHERE uid=? ORDER BY time DESC", [$uid])->fetch();
Which will return to $user as an array that has the username, name, and email of the user.
You can also use this function to INSERT, UPDATE, or basically any type of query you can think of. This is how you insert:
pdoQuery("INSERT INTO `table_name` (`name`,`col2`, `col3`) VALUES (?,?,?)", [$name, $col1, $col2]);
My PDO Class
Since writing this post, I have created a new database wrapper class called GrumpyPDO (Hosted on Github).
This class method returns the object of the query you requested, so if you wanted to loop through all of the results of your query you use it like this:
Fetch All
GrumpyPDO Long Syntax
$stmt = $db->run("SELECT * FROM `table_name` WHERE `user`=? ORDER BY time DESC", [$username])->fetchAll();
GrumpyPDO Short Syntax
$stmt = $db->all("SELECT * FROM `table_name` WHERE `user`=? ORDER BY time DESC", [$username]);
Loop:
foreach($stmt as $row) {
$row['name']."<br>";
}
Single Column Return
Or if you just wanted to get a single column from a specific row, you could use it like this:
//Long Syntax
$username = $db->run("SELECT `username` FROM `users_table` WHERE uid=? ORDER BY `time` DESC", [$uid])->fetchColumn();
//Short
$username = $db->cell("SELECT `username` FROM `users_table` WHERE uid=? ORDER BY `time` DESC", [$uid]);
Which will return the username from user where uid=$uid as a string
Entire Row Return
or if you wanted several values from 1 specific row, you could do
//Long Syntax
$user = $db->run("SELECT `username`,`name`,`email` FROM `users_table` WHERE uid=? ORDER BY time DESC", [$uid])->fetch();
//Short Syntax
$user = $db->row("SELECT `username`,`name`,`email` FROM `users_table` WHERE uid=? ORDER BY time DESC", [$uid]);
Which will return to $user as an array that has the username, name, and email of the user.
DML Queries
You can also use this function to INSERT, UPDATE, or basically any type of query you can think of. This is how you insert (All DML's are similar):
$db->run("INSERT INTO `table_name` (`name`,`col2`, `col3`) VALUES (?,?,?)", [$name, $col1, $col2]);

CakePHP 3 Raw SQL Query

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 ...');

issue with SELECT COUNT(id)

I've been using this command to retrieve the number of the fields which have same email address:
$query = $db->query("SELECT COUNT(`user_id`) FROM `users` WHERE `email`='$email'") or die($db-error);
There are 3 records in users table with the same email address. The problem is when I put * instead of COUNT(user_id) it returns correctly: $query->num_rows gives 3 but when I use COUNT(user_id) then $query->num_rows returns 1 all the time. how can I correct this or where is my problem?
When you use $query->num_rows with that query it will return 1 row only, because there is only one count to return.
The actual number of rows will be contained in that query. If you want the result as an object, or associative array give the count a name:
$query = $db->query("SELECT COUNT(`user_id`) AS total FROM `users` WHERE `email`='$email'") or die($db-error);
And in the returned query total should be 3, while $query->num_rows will still be 1. If you just want the value a quick way would be using $total = $query->fetchColumn();.
As others have said though, be careful with NULL user ids, because COUNT() will ignore them.
Emails have to be uinque in users table. Thus, you need no count at all.
You ought to use prepared statements.
You shouldn't post a code that will never run.
Here goes the only correct way to run such a query:
$sql = "SELECT * FROM `users` WHERE `email`=?";
$stm = $db->prepare($sql);
$stm->execute([$email]);
$user = $stm-fetch();
(the code was written due to erroneous tagging. For mysqli you will need another code, but guidelines remains the same.)
Something like this
$sql = "SELECT * FROM `users` WHERE `email`=?";
$stm = $db->prepare($sql);
$stm->bind_param('s',$email);
$stm->execute();
$res = $stm->get_result()
$user = $res->fetch_assoc();
in $user variable you will have either userdata you will need in the following code or false which means no user found. Thus $user can be used in if() statement all right without the need of any counts.
In case when you really need to count the rows, then you use this count() approach you tried. You can use a function from this answer for this:
$count = getVar("SELECT COUNT(1) FROM users WHERE salary > ?", $salary);
That's the correct behaviour: If you use the COUNT function, the result of your select query will be just one row with one column containing the number of data sets.
So, you can retrieve the number of users with the given E-mail address like this:
$query = $db->query("SELECT COUNT(`user_id`) FROM `users` WHERE `email`='$email'") or die($db-error);
$row = $query->fetch_row();
$count = $row[0];
Note that this is faster than querying all data using SELECT * and checking $query->num_rows because it does not need to actually fetch the data.

sqlite3 - efficient way to count rows returned from SELECT statement in PHP without using COUNT()

I'm an SQL noob and learning how to use PDO. I'm doing a course which introduces basic user login functions. In an example of a login page, they check the username/password against a MySQL database. I edited their code slightly to be able to simultaneously check whether the user/pass combo exists and also grab the user's first name:
$sql = sprintf("SELECT firstname FROM users WHERE username='%s' AND password='%s'",
mysql_real_escape_string($_POST["username"]),
mysql_real_escape_string($_POST["password"]));
// execute query
$result = mysql_query($sql);
if (mysql_num_rows($result) == 1) {
$_SESSION["authenticated"] = true;
// get contents of "firstname" field from row 0 (our only row)
$firstname = mysql_result($result,0,"firstname");
if ($firstname != '')
$_SESSION["user"] = $firstname;
}
What I want to do is use SQLite instead and do the same thing. Searching around has only resulted in people saying you should use a SELECT COUNT(*) statement, but I don't want to have to use an extra query if it's possible. Since I'm SELECTing the firstname field, I should only get 1 row returned if the user exists and 0 if they don't. I want to be able to use that number to check if the login is correct.
So far I've got this:
$dsn = 'sqlite:../database/cs75.db';
$dbh = new PDO($dsn);
$sql = sprintf("SELECT firstname FROM users WHERE username='%s' AND password='%s'",
$_POST["username"],
$_POST["password"]);
// query the database and save the result in $result
$result = $dbh->query($sql);
// count number of rows
$rows = sqlite_num_rows($result);
if ($rows == 1) { ...
But this is returning Warning: sqlite_num_rows() expects parameter 1 to be resource, object given.
Is there a way I can do this efficiently like in MySQL, or do I have to use a second query?
EDIT:
I found this, not sure if it's the best way but it seems to work: How to get the number of rows grouped by column?
This code let me do it without the second query:
// query the database and save the result in $result
$result = $dbh->query($sql);
// count number of rows
$rows = $result->fetch(PDO::FETCH_NUM);
echo 'Found: ' . $rows[0];
$rows is an array so I can just count that to check if it's > 0.
Thanks to everyone who commented. I didn't know until now that there were 2 different approaches (procedural & object oriented) so that helped a lot.
Normally, you can use PDOStatement::rowCount(), however, SQLite v3 does not appear to provide rowcounts for queries.
You would need to seperately query the count(*), or create your own counting-query-function.
The documentation comments have an example of this
A bit late, but i tried this with SQLite3 successful:
$result = $db->query('SELECT * FROM table_xy');
$rows = $result->fetchAll();
echo count($rows);

how to return array for mysql_query?

// make empty array
$sqlArray=array();
$jsonArray=array();
// START NEED FAST WORKING ALTERNATİVES -----------------------------------------------------
// first 20 vistors
$query = "SELECT user_id FROM vistors LIMIT 20";
$result = mysql_query ($query) or die ($query);
// make vistors user query array
while ($vstr_line = mysql_fetch_array($result)){
array_push($sqlArray, $vstr_line['user_id']);
}
// implode vistors user array
$sqlArray_impl = implode("', '", $sqlArray);
// END NEED FAST WORKING ALTERNATİVES -----------------------------------------------------
// Get vistors information
$query = "SELECT id, username, picture FROM users WHERE id IN ('$sqlArray_impl')";
$qry_result = mysql_query($query) or die($query);
while ($usr_line = mysql_fetch_array($qry_result)){
array_push($jsonArray, $usr_line['id'].' - '.$usr_line['username'].' - '.$usr_line['picture']);
}
print_r($sqlArray);
echo '<br><br>';
print_r($jsonArray);
see this my functions..
i need a replacement for fast working alternatives..
function within the range specified above, to me, running faster than the alternative.
the query will return back array ?
thx for all helpers !
Can you use a JOIN or SUB SELECT to reduce the query count from 2 to 1? Might not give much of a boost but worth a shot and a cleaner implementation.
Where is the bottleneck? Most likely the db and not the php code.
Are the tables/columns properly indexed? Run EXPLAIN on both queries.
Easiest would be to include first query as subquery eliminating one turn to the DB and a lot of code:
// Get vistors information
$query = "SELECT id, username, picture FROM users WHERE id IN (SELECT user_id FROM vistors LIMIT 20)";
$qry_result = mysql_query($query) or die($query);
Unless there is more reason to have the first one seperate, but that is not visible in your code example.
If you use PDO (recommended anyway...), you can return the result array all at once using fetchAll().
For your second query, you can use string concatenation in MySQL to directly return the result you want.

Categories