I want to upgrade my code from mysql to pdo. When I am changing mysql_name_field to equivalent pdo. I stuck off. Check my old code.
This is in manage data class:
$result=$this->query($query);
$x=$this->cols_count($result);
$heading[]=$this->column_name($result);
print_r($heading);die();
and column_name function in data class. Manage data class inherits data class. See the column name function.
function column_name($result) {
$row=$this->stmt->getColumnMeta($result);
return $row;
}
it returns only one column name while I want all column names from the table.
The getColumnMeta() returns metadata for a column in a result set (the 0-indexed column from your result). Also, from the documentation:
Warning
This function is EXPERIMENTAL. The behaviour of this function, its name, and surrounding documentation may change without notice in a future release of PHP. This function should be used at your own risk.
Warning
Not all PDO drivers support PDOStatement::getColumnMeta()
What makes it not a very good approach. Instead, you can use query "SHOW COLUMNS from table" and retrieve all columns information. Alternatively, if you still want to use the getColumnMeta():
function column_name() {
$results = $this->query('SELECT * FROM table LIMIT 0');
for ($i = 0; $i < $results->columnCount(); $i++) {
$col = $results->getColumnMeta($i);
$columns[] = $col['name'];
}
return columns;
}
Not able to test now, but I think it will give some idea. Hope it helps,
Related
The function searches the $variable named table using SQL as showed here:
class Search{
`public function query(){`
`SELECT * FROM $tableName`
`}`
}
$object = new Search();
$object->query('tableName');
Is this a good practice or a door to SQL Inyection?
The short answer is NO, don't do this.
That said it may be perfectly safe depending on where your parameter is coming from.
consider mapping a variable to the table names, so you can verify that you are only building a query with a valid table name and not open-ended text.
A simple solution could look something like this:
public function query($tableName){
$allowedTables = ['accounts', 'items', 'products'];
$table = in_array($tableName, $allowedTables) ? $tableName : null;
if(empty($table)){
return false;
}
$sql = "Select * FROM " . $table;
...
}
You can do it in the safe way by "whitelisting" allowed tables. There are many different implementations depends on your needs. For example, get full or filtered list of your tables with:
SHOW TABLES;
BTW, PHP has a function for this. Then check if input table is in the list.
I think it's safe way to do this.
I have a query with a dynamic field, how do I access this field without knowing its name?
define('FIELD_NAME',"name");
$stmt = $connexion->query('SELECT '.FIELD_NAME.' from mytable);
while ($rs=$stmt->fetch(PDO::FETCH_OBJ)){
echo $rs->FIELD_NAME; // DOESN'T WORK
echo $rs->name; // WORK
}
Wrap the constant in {} to create dynamic variables.
echo $rs->{FIELD_NAME};
You can see some example from the documentation.
Curly braces may also be used, to clearly delimit the property name.
Demo: http://3v4l.org/sgvV4
There are lot of approaches to this. If it's not important that the variable name match the column_name, you could assign an alias to the expression in the SELECT statement
For example:
SELECT whateverexpression AS mycol FROM mytable LIMIT 1;
Then, you'd "know" the name of the variable in the object is $mycol
echo $rs->mycol;
I'm thinking this approach might be good in the more general case, when you're dealing with tables that have column names that were assigned by syphilitic idiot developers who had a good reason to
CREATE TABLE t (`Hey!$I (can)^name.\my->column Wh#tever` INT);
INSERT INTO t VALUES (42);
SELECT `Hey!$I (can)^name.\my->column Wh#tever` FROM t;
Obviously, there are lots of other approaches, like avoiding PDO::FETCH_OBJ and using PDO::FETCH_NUM instead. If you want to stick with PDO::FETCH_OBJ, I'm thinking assigning an alias would be workable.
Retrieving the metadata from the resultset is an approach I would consider, if getColumnMeta wasn't still experimental.
define('FIELD_NAME',"name");
$stmt = $connexion->query('SELECT '.FIELD_NAME.' from mytable');
while ($rs=$stmt->fetch(PDO::FETCH_NUM)){
echo $rs[0];
}
Using this approach, if FIELD_NAME is defined to something like *, you will still be able to get the first column.
If you're only trying to get a single value from each row, you can use PDOStatement::fetchColumn()
define('FIELD_NAME',"name");
$stmt = $connexion->query('SELECT '.FIELD_NAME.' from mytable');
while ($col = $stmt->fetchColumn()) {
echo $col;
}
Also note, you were missing a '.
I am trying to retrieve a specific field from the first row of my query results. The following works just fine...
$result = $db->query($query);
$firstrow = $result->fetch();
$desired_field = $firstrow["field"];
My question is, can i do this in one step without storing the first row of results in a variable? Thanks in advance!
You can use fetchColumn() to return a single column from the next row in the result set. If there is only one column in the result set, do:
$desired_field = $result->fetchColumn();
If there are multiple columns in the result set, specific the numeric index of the one you want:
$desired_field = $result->fetchColumn(1);
Take notice of the warning provided in the fetchColumn() documentation:
There is no way to return another column from the same row if you use PDOStatement::fetchColumn() to retrieve data.
You can use something like $firstrow = $db->query($query)->fetch() but this is not good practice to do with functions that aren't guaranteed to return an object.
The query() function can return FALSE on error, and the dynamic call to fetch() would be a fatal error. You can't call ->fetch() on a scalar FALSE value.
For example, try the following and your script will explode:
$firstrow = $db->query("SELECT * FROM table_that_does_not_exist")->fetch();
PDO does support a mode to throw exceptions instead of returning FALSE, so in that case you are guaranteed either query()->fetch() works, or else query() will throw an exception, so you will never reach the fatal error. But you might not be using PDO's exception mode.
The answer from #GeorgeCummins points out that there's a fetchColumn() method that you can use once you have a PDOStatement object, that's a good way to get a single column. If you only need one column, name that column as the only column in your select-list, and then always use fetchColumn(0):
$oneValue = $db->query("SELECT oneColumn FROM table")->fetchColumn(0);
Otherwise if you use fetch(), this returns an array. PHP 5.4 supports array dereferencing:
$oneValue = $db->query("SELECT oneColumn FROM table")->fetch()[0];
But if you're using PHP 5.3 or earlier this is not supported. And I've never tried it with the array returned by PDOStatement so if it's actually returning an ArrayObject or something this might not work anyway.
This is guarantee to work if and only if your query is correct and there is at least one row data.
$db->query($query)->fetch(PDO::FETCH_OBJ)->field;
In zend framework 1, we had used mysql rand() function like below or using zend_db_expr(). I have tried this in ZF2, but this is not working. Somebody please help me to use this in Zend Framework 2
$select = $this->db()->select()
->from('TABLE')
->order('RAND()');
Thanks,
Looking at the API it appears that the order function accepts a string or array of parameters order(string | array $order). My first thought was to use a key/val array. However, as I look at the actual code of the Db\Sql\Select, the string or array that you are passing gets quoted (see here). Assuming that your Db platform is Mysql, this is the function that quotes the fields (see here). It appears to iterate through each of the fields, and add these quotes, rendering your rand() function a useless string.
Getting to the point, the solution is up to you, but it does not appear that you can do it the way you want with this current version of ZF2.
You will need to extend the Db\Sql\Select class, OR extend the Db\Adapter\Platform\Mysql class, OR change the code in these classes, OR execute your query as a full select statement, OR change up your logic.
By changing up your logic I mean, for example, if your table has an Integer primary key, then first select the MAX(id) from the table. Then, choose your random numbers in PHP prior to executing your query like $ids[] = rand(1, $max) for as many results as you need back. Then your sql logic would look like SELECT * FROM table WHERE id IN(453, 234, 987, 12, 999). Same result, just different logic. Mysql's rand() is very "expensive" anyways.
Hope this helps!
Here you can use \Zend\Db\Sql\Expression. Example function from ModelTable:
public function getRandUsers($limit = 1){
$limit = (int)$limit;
$resultSet = $this->tableGateway->select(function(Select $select) use ($limit){
$select->where(array('role' => array(6,7), 'status' => 1));
$rand = new \Zend\Db\Sql\Expression('RAND()');
$select->order($rand);
$select->limit($limit);
//echo $select->getSqlString();
});
return $resultSet;
}
Little question: With the following code...
<?php
$statement = "SELECT * FROM TABLE";
$query_unfetched = mysql_query($statement);
$query_num = mysql_num_rows($query_unfetched);
if ($query_num !== 1) {
exit;
}
$query_fetched = mysql_fetch_object($query_unfetched);
$fielname = "ID";
echo $query_fetched->$fiedname;
?>
With this code, there is no output, because PHP somehow does not check that in $fieldname is an existing name of a field in the selected Table.
Why doesn't it work, have I made a mistake? Or are there any other ways to select a field whose name is saved in a var?
Thanks for the help!
Instead of using mysql_fetch_object, you could use mysql_fetch_assoc. It will return the result as an array, after which you can simply use your variable as a key.
I'd suggest using var_dump on the $query_fetched. Some OS's and DB's will return different capitalizations. Oracle, for one, will always return the column names as capital. I've seen MySQL only return lower in one circumstance.
You can also use the fetch_assoc as suggested by Cpt. eMco and that will give you warnings if the array key is not set. (Remember to turn warnings off in production though).
(I do need to put in an obligatory plug for the PDO classes. I find them far more intuitive and clearer.)