This is something I used to do in Java, I was wondering if there is an equivelant in PHP.
In Java, I'd do something like this (pseudo only as I've gotten rusty in the last year or so):
preparedStatement = new StringBuilder("SELECT something FROM somewhere");
ResultSet rs = preparedStatement.executeQuery();
while(rs.next())
{
if (someTest)
{
rs.updateRow[1]="someNewValue";
}
}
This is wide of the mark syntactically (and I bet it won't compile) but I hope it explains the kind of thing I was able to do. Not sure if it saved an actual DB query from being run but it did make my code alot cleaner.
So in PHP, I have something like this:
$query = "SELECT something FROM somewhere";
$result = mysql_query($query, $db);
while ($row = mysql_fetch_assoc($result))
{
if (someTest)
{
//how can I update this row without coding another query?
}
}
Is there an equivelant to this in PHP?
I'm using the vanilla mysql db methods, not mysqli or that other one (pod or something?) but I think I'd be safe to use mysqli on our servers if I need to.
Any help appreciated
Nope, you could however use mysql_fetch_object with a custom classname, and define a save() method on it that will run the update query for you. Keeps the logic out of the loop and in a Model for that data. Or use an full-blown ORM library which does this kind of thing.
As far as I'm aware, you can't update the row without running another query such as:
UPDATE table SET column1="value" WHERE (column2="value");
Related
Please anybody help me. I want to execute php script from mysql database. My plan is so many if(),else if() statement will be execute. I had used eval($row['data']) statement in to while() loop and it's worked. But only first one.not at all.
My code as below.
$conn = mysqli_connect();
$sql = "SELECT * FROM transaction ORDER BY id ASC";
$result = mysqli_query($conn, $sql);
if(mysqli_num_rows($result) > 0 ){
while($row = mysqli_fetch_array($result)){
eval($row['tran_php']);
// echo eval($row['tran_php']);
}
}
Here is only first one does work which one is if(). Do you have any solution to work all about the else if() statement end of the if() statement?
You have ever heared "eval is evil"? Its true. eval is a development nightmare and a good indicator for doing something wrong.
Only a idea. Do not store the PHP code in database. Store it as files, link to it in DB (filename and/or id) and include it by the regular way.
But always remember this can be a security issue if the code comes from users!
The best way is to encapsule everithing by a UI where the user inputs his stuff and PHP handles it for example by a Parser, build by you.
Why there is the need to do it with PHP-Code like you?
So honestly, this is the first time I am working with PDO and Error Exceptions. I have gone thru manuals as well as different Q/As resolved here in past and came up with code that I am pretty satisfied with. But I really really need your opinion on this. I have built few functions that I normally use often in my projects.
Please note that right now I am doing a test project just intended to learn these 2 new things.
First of all, I am not a fan of OOP and have always preferred procedural programming type.
function _database_row($_table, $_id = 0, $_key = "id") {
global $Database;
if(is_object($Database)) {
$Query = $Database->prepare("SELECT * FROM {$_table} WHERE {$_key} = :id");
if($Query->execute(Array(":id" => $_id))) {
$Query_Data = $Query->fetchAll(PDO::FETCH_ASSOC);
if(count($Query_Data) >= 1) {
if(count($Query_Data) == 1) {
return $Query_Data[0];
}
return $Query_Data;
}
} else {
throw new Exception("Database Query Failure: ".$Query->errorInfo()[2]);
}
}
return false;
}
the above function is intended to fetch a row from $_table table with $_id (not necessarily an integer value).
Please note that $_id may (sometimes) be the only thing (for this function) that is fetched from $_REQUEST. By simply preparing the statement, am I totally secure from any SQL injection threat?
I couldn't find an alternative to mysql_num_rows() (I indeed found few PDO methods to use fetchColumn while using COUNT() in the query. But I didn't prefer it that way, so I want to know if I did it right?
also before people ask, let me explain that in above function I designed it so it returns the row directly whenever I am looking for a single one (it will always be the case when I use "id" as $_key because its PRIMARY auto_increment in database), while in rare cases I will also need multiple results :) this seems to be working fine, just need your opinions.
example of use:
_database_row("user", 14); // fetch me the user having id # 14
_database_row("products", 2); // fetch me the user having id # 14
_database_row("products", "enabled", "status"); // fetch me all products with status enabled
...sometimes during procedural programming, I wouldn't like those nasty "uncaught exception" errors, instead I will simply prefer a bool(false). So I did it like this:
function __database_row($_table, $_id = 0, $_key = "id") {
try {
return _database_row($_table, $_id, $_key);
} catch (Exception $e) {
return false;
}
}
(don't miss the use of another leading "_"). This also seems to be working perfectly fine, so what's your opinion here?
IMPORTANT:
what is the use of "PDOStatement::closeCursor" exactly? I did read the manual but I am quite confused as I can call my functions as many times as I want and still get the desired/expected results but never "closed the cursor"
now... ENOUGH WITH SELECTS AND FETCHINGS :) lets talk about INSERTS
so I made this function to add multiple products in a single script execution and quickly.
function _add_product($_name, $_price = 0) {
global $Database;
if(is_object($Database)) {
$Query = $Database->prepare("INSERT INTO products (name, price) VALUES (:name, :price)");
$Query->execute(Array(":name" => $_name, ":price" => $_price));
if($Query->rowCount() >= 1) {
return $Database->lastInsertId();
} else {
throw new Exception("Database Query Failure: ".$Query->errorInfo()[2]);
}
}
return false;
}
This also seems to be working perfectly fine, but can I really rely on the method I used to get the ID of latest insert?
Thank you all!
There is a lot going on here, so I will try to answer specific questions and address some issues.
I am not a fan of OOP
Note that just because code has objects doesn't mean that it is object oriented. You can use PDO in a purely procedural style, and the presence of -> does not make it OOP. I wouldn't be scared of using PDO for this reason. If it makes you feel any better, you could use the procedural style mysqli instead, but I personally prefer PDO.
By simply preparing the statement, am I totally secure from any SQL injection threat?
No.
Consider $pdo->prepare("SELECT * FROM t1 WHERE col1 = $_POST[rightFromUser]"). This is a prepared statement, but it is still vulnerable to injection. Injection vulnerability has more to do with the queries themselves. If the statement is properly parameterized (e.g. you were using ? instead of $_POST), you would know longer be vulnerable. Your query:
SELECT * FROM {$_table} WHERE {$_key} = :id
actually is vulnerable because it has variables in it that can be injected. Although the query is vulnerable, it doesn't necessarily mean that the code is. Perhaps you have a whitelist on the table and column names and they are checked before the function is called. However the query is not portable by itself. I would suggest avoiding variables in queries at all -- even for table/column names. It's just a suggestion, though.
I couldn't find an alternative to mysql_num_rows()
There isn't one. Looking at the count of fetched results, using SELECT COUNT or looking at the table stats (for some engines) are surefire way to get the column count for SELECT statements. Note that PDOStatement::rowCount does work for SELECT with MySQL. However, it is not guaranteed to work with any database in particular according to the documentation. I will say that I've never had a problem using it to get the selected row count with MySQL.
There are similar comments regarding PDO::lastInsertId. I've never had a problem with that and MySQL either.
let me explain that in above function I designed it so it returns the row directly whenever I am looking for a single one
I would advise against this because you have to know about this functionality when using the function. It can be convenient at times, but I think it would be easier to handle the result of the function transparently. That is to say, you should not have to inspect the return value to discover its type and figure out how to handle it.
I wouldn't like those nasty "uncaught exception" errors
Exception swallowing is bad. You should allow exceptions to propagate and appropriately handle them.
Generally exceptions should not occur unless something catastrophic happens (MySQL error, unable to connect to the database, etc.) These errors should be very rare in production unless something legitimately happens to the server. You can display an error page to users, but at least make sure the exceptions are logged. During development, you probably want the exceptions to be as loud as possible so you can figure out exactly what to debug.
I also think that names should be reasonably descriptive, so two functions named __database_row and _database_row are really confusing.
IMPORTANT: what is the use of "PDOStatement::closeCursor" exactly?
I doubt you will have to use this, so don't worry too much about it. Essentially it allows you to fetch from separate prepared statements in parallel. For example:
$stmt1 = $pdo->prepare($query1);
$stmt2 = $pdo->prepare($query2);
$stmt1->execute();
$stmt1->fetch();
// You may need to do this before $stmt2->execute()
$stmt1->closeCursor();
$stmt2->fetch();
I could be wrong, but I don't think you need to do this for MySQL (i.e. you could call execute on both statements without calling closeCursor.
can I really rely on the method I used to get the ID of latest insert?
PDO's documentation on this (above) seems to be more forgiving about it than it is about rowCount and SELECT. I would use it with confidence for MySQL, but you can always just SELECT LAST_INSERT_ID().
Am I doing it right?
This is a difficult question to answer because there are so many possible definitions of right. Apparently your code is working and you are using PDO, so in a way you are. I do have some criticisms:
global $Database;
This creates a reliance on the declaration of a global $Database variable earlier in the script. Instead you should pass the database as an argument to the function. If you are an OOP fan, you could also make the database a property of the class that had this function as a method. In general you should avoid global state since it makes code harder to reuse and harder to test.
the above function is intended to fetch a row from $_table table with $_id
Rather than create a generic function for querying like this, it is better to design your application in a way that will allow you to run queries that serve specific purposes. I don't really see why you would want to select all columns for a table for a given ID. This is not as useful as it seems. Instead, you probably want to get specific columns from these tables, perhaps joined with other tables, to serve specific functions.
Well, your main problem is not OOP, but SQL.
To tell you truth, SQL is by no means a silly key-value storage you are taking it for. So, it makes your first function, that can be used only on too limited SQL subset, is totally useless.
Moreover, you are making a gibberish out of almost natural English of SQL. Compare these 2 sentences
SELECT * FROM products WHERE status = ?
quite comprehensible - isn't it?
products! enabled! status!
HUH?
Not to mention that this function is prone to SQL injection. So, you just have to get rid of it. If you want a one-liner, you can make something like this
function db_row($sql, $data = array(), $mode = PDO::FETCH_ASSOC) {
global $Database;
$stmt = $Database->prepare($sql);
$stmt->execute($data);
return $stmt->fetch($mode);
}
to be called this way:
$row = db_row("SELECT * FROM products WHERE id = ?",[14]);
Note that PDO is intelligent enough to report you errors without any intervention. All you need is set it into exception mode.
Speaking of second function, can be reviewed.
function _add_product($_name, $_price = 0)
{
global $Database;
$sql = "INSERT INTO products (name, price) VALUES (?,?)";
$Database->prepare($sql)->execute(func_get_args());
return $Database->lastInsertId();
}
is all you actually need.
I couldn't find an alternative to mysql_num_rows()
You actually never needed it with mysql and would never need with PDO either
I'm relatively new to php, and to this point I've been fine using the mysql_fetch_array function to echo values selected from the database. But now I want to be able to echo the results selected from multiple rows with the same username.
I was just wondering what the most efficient way of doing this was. I could manage to do it using a for loop and counting through each individual query, but I know there must be a more efficient way just using sql, or using a better oho function.
Thank you for the help.
Alex
while($row = mysql_fetch_array($result)) {
// process each row
}
I guess that's all you neeed - have a play and you should get your desired effect! It's best to do it in PHP..
Also you shouldn't use mysql_fetch_array anymore as it's deprecated. Use PDO or mysqli insted. More information you can find here
while($row = mysql_fetch_assoc($result)) {
} or
while($row = mysql_fetch_array($result)) {
}
and mysql_ functions are depreciated now onwards in mysql
SQL is used to query the database your using. PHP is used to format the output from the query. See the manual from PHP.net for more info php.net/manual/en/function.mysql-fetch-array.php . There is no way as far as I know to format the output in rows using SQL.
B.T.W. if this is new code I would advice you to use mysqli instead of mysql.
i am used to writing regular pdo statements into php how can i continue doing that without having to learn active records or use whatever else method there is in CI
i did something like this
$sql = "select column1,column2 from table where column_id = :column_id and column_2 = :something"
$query = $db->query($sql);
$query->bindParam(":column_id", $_GET['value'], PDO::PARAM_INT);
$query->bindParam(":something", $_GET['something'], PDO::PARAM_STR);
$query->execute();
while($row = $query->fetch(PDO::FETCH_OBJ)
{
print $row->data;
}
rather than using $_GET i can probably use $this->uri->segment()
which hopefully works with this...
I looked at active record and that looks like a huge bad idea, i dont know what Ellislab was thinking. no clue how complex queries can go into them. I am a newb learning from nettuts i can be wrong and please show me if i am. just speaking from what i have learned so far.
writing query statments the otherway such as
$query = $this->db->query("my sql statement") i would have to escape each value i am querying with codeigniters escape methods or just use mysql_real_escape_string. which is something i could of done to begin with before diving into the mvc world but i chose pdo because its something that already works well.
how can i implement what i am already used to?? I dont mind modifying core files , ill hopefully end up learning all the classes to reverse engineer it but until that day comes i'll have hopefully written my own mvc.
thanks
Sorry, I fail to see how this:
$query = $this->db->select('column1,column2')
->from('table')
->where('column_id',$this->input->get('value'))
->where('column_2',$this->input->get('something'))
->get();
return $query->results();
"looks like alot of extra work" rather than this:
$sql = "select column1,column2 from table where column_id = :column_id and column_2 = :something"
$query = $db->query($sql);
$query->bindParam(":column_id", $_GET['value'], PDO::PARAM_INT);
$query->bindParam(":something", $_GET['something'], PDO::PARAM_STR);
$query->execute();
Keep in mind that AR automatically escapes, so you don't worry about SQL injections.
If you're more used to query bindings, you can also do
$sql = "select column1,column2 from table where column_id = ? and column_2 = ?";
$query = $this->db->query($sql, array($this->uri->segment(3), $something);
and take advantage of parametrization, without using Active Record class.
Nothing prevents you from using PDO, or even mysql_* for what that matters, instead of Active Record class. And your query has nothing that prevents CI from using it - apart from the $_GET array which you must enable, but can easily subsitute with $this->input->get() or fetch manually the URI segment or have it passed automatically to the controller's method, as usually happens.
You say "am a newb learning from nettuts" , but still say that Ellislabs doesn't know what it's doing; altough lightweight and far from perfect CI has a solid community, is actively developed and its general consensus is quite high; and if it decides to have the Active Record the way it is, there's a reason.
Also, consider that other more proper and real ORMs, like Propel or Doctrine, use a similar style in running queries (and you can use them too, instead of AR if you like it), taking advantage of PHP5 concatenation. An example taken right from the frontpage of propel:
$books = BookQuery::create() // retrieve all books...
->filterByPublishYear(2009) // ... published in 2009
->orderByTitle() // ... ordered by title
->joinWith('Book.Author') // ... with their author
->find();
So I see nothing strange in the way CI's Active Record is implemented or structured. If your code is not running, please give more details, like error codes and so on, so we can actually understand why it's not working.
IMPORTANT:
I just read the changelog from the latest version; try downloading it (version 2.10), as they state:
Added a PDO driver to the Database driver.
You're not gaining anything by using CI's DB class if you're not using ActiveRecord or the other functions. Why not just use PDO natively?
By the way, you could do the exact same thing this way:
$result = $this->db->
select(array('column1', 'column2'))->
where(array(
'column1' => $this->input->get('value'),
'column2' => $this->input->get('something')
))->get('table')->result();
print_r($result);
Let's say I have something like this:
$db=new PDO($dsn);
$statement=$db->query('Select * from foo');
while ($result=$statement->fetch())
{
//do something with $result
}
How would I put another query inside of that while loop? Even if I make a new PDOStatement object, it seems that that overwrites the cursor for the topmost PDO statement. The only other solution I see is to either a) fetch the entire outer loop at once or b) open 2 different connections to the database. Neither of these seem like a good idea, are there any other solutions?
You should be able to do any other query you want inside your while loop, I'd say ; something like this :
$db=new PDO($dsn);
$statement=$db->query('Select * from foo');
while ($result=$statement->fetch())
{
$statement2 = $db->query('Select * from bar');
while ($result2=$statement2->fetch()) {
// use result2
}
}
Did you try that ? It should work...
Still, if you can (if it's OK with your data, I mean), using a JOIN to do only one query might be better for performances : 1 query instead of several is generally faster.
Sounds like what you are trying to accomplish is getting related data for the record you're looking at, why not just JOIN them in at the first query? The database will be better at connecting the dots internally than any amount of code can do externally.
But to answer your question, I don't see the harm in opening another connection to the same DSN, most likely thing to happen is that you get another instance of the PDO object pointing to the same actual connection. Also, but depending on the amount of data you're expecting you could just fetchAll and loop over a php array.