I am hoping to remove duplicate entries from an array that I am calling from a stored procedure with a while loop.
// Prepare stored procedure call
$sth = $dbh->prepare('CALL sp_get_recipes()');
// Call the stored procedure
$res = $sth->execute();
if ($res){
while( $row = $sth->fetchObject() ){
echo $row->Recipe; // I would like to echo this row just once.
echo '<ul class="recipe-body"><li>'.$row->Ingredient." ".$row->Quantity." ".$row->UoM.'</li></ul>';
}
// Close connection
$dbh = null;
}else{
$arr = $sth->errorInfo();
echo "Execution failed with MYSQL: " . $arr[0] . "\n";
die();
}
My understanding is my echo $row->Recipe; has to exist on it's own somehow. I've being looking into array_unique to echo the value just once but I can't seem to figure it out exactly. If someone could point me in the right direction it would be great.
UPDATE
Thanks for all the responses I have fixed up the stored procedure to return unique rows.
Create a temporary array before the while and store every Recipe in it which have been echoed. Before the echo check the temporary array for the current Recipe (if it contains don't echo it otherwaise echo & store it in the temporary array).
If you cannot change the database structure, which I would recommend, you could first store the information you get from the database query into objects (e.g. some kind of Recipe objects with an array of Ingredient objects) and then build your actual output.
If you can change the database structure or the way you query (if the latter already gives you what I'm about to recommend) you can have a table (assuming the database is relational) for the recipes with some kind of ID and another table for the ingredients of the recipes where each ingredient row also stores the ID of the recipe it belongs to.
Related
I am working on an android app which uses APIs made with php. Here, i am dynamically creating columns and their values.
I am verifying the API via postman and a strange thing happens every time, While looping through the Json Object what i am doing is first creating column and then inserting its values.
The problem is only the 1st iteration saves the element and rest of them only creates the column but does not insert the values. I don't know if i am doing anything wrong, below is my php code.
<?php
include("connection.php");
$data = file_get_contents('php://input');
$json_data = json_decode($data);
foreach($json_data as $key => $val) {
$column_name = $key ;
$c_column_name = preg_replace('/[^a-zA-Z]+/', '', $column_name);
$column_value = $val ;
$table_name = "test2";
$email = "ht#t.com";
$result = mysqli_query($conn,"SHOW COLUMNS FROM $table_name LIKE '$c_column_name'");
$exists = (mysqli_num_rows($result))?TRUE:FALSE;
if($exists) {
$query1 = "INSERT INTO $table_name($c_column_name)VALUES('$column_value') ";
$data0=mysqli_query($conn,$query);
if($data0)
{
echo json_encode(array("success"=>"true - insertion","message"=>"Column existed, Successfully data sent."));
}
else{
echo json_encode(array("success"=>"false - insertion","message"=>"Column existed, data not inserted."));
}
}
else{
$query2="ALTER TABLE $table_name ADD COLUMN `$c_column_name` varchar(50) NOT NULL";
$data1=mysqli_query($conn,$query2);
if($data1){
$query3="INSERT INTO $table_name($c_column_name)VALUES('$column_value')";
$data2=mysqli_query($conn,$query3);
if($data2)
{
echo json_encode(array("success"=>"true - insertion","message"=>"Successfully data sent."));
}
else{
echo json_encode(array("success"=>"false - insertion","message"=>"Column created but data not inserted."));
}
}
else
{
echo json_encode(array("success"=>"false - column creation","message"=>"Failed to create column.'$column_name', '$table_name', '$conn'"));
}
}
}
?>
Here is the Json Object through postman.
{"Shape":"rewq","Trans.No.":"yuuiop","Color":"qwert"}
Please help me with this, any help or suggestions are highly appreciated.
The second column name is Trans.No. which contains a dot, this is why it fails, probably you have an error as a result which prevents further columns from being created.
I think it would be much better to have a table with this structure:
attributes(id, key, value)
and whenever a key-value pair is received, you just insert/update it, depending on the logic you need to be executed. Your current model will create a separate row for each attribute, which is probably not what you want to achieve.
EDIT
Based on the information received in the comment section I reached the following conclusion:
You could create the missing columns first and then generate the insert statement with all the columns, having a single insert.
But it would be better to not create a separate column for each value, as the number of columns could quickly get out of hand. Instead you could have a table:
myentity(id, name)
for storing the entities represented by the JSON and
attributes(id, myentity_id, key, value)
for storing its attributes. This would be a neat schema with all the dinamicity you could want.
Lets say I have a database full of info, and I want the user to find his info by inputting his ID. I collect the input of the user with:
'$_POST[PID]'
And want to put it into a resource variable like:
resource $result = '$_POST[PID]';
In order to print out their information like :
while($row = mysql_fetch_array($result))
{
echo all their information
echo "<br>";
}
However I cannot create the resource variable because it is telling me that it is a boolean. How can I fetch that resource in order to print the list?
Several problems with this
First, a resource is something like a database result set, a connection (like fsockopen), etc. You can't just declare or typecast a variable into a result set
Second, you need to do something like SQL to fetch the data based on that ID. That involves connecting to the DB, running your query and then doing your fetch_array
Third, mysql_ functions are depreciated. Consider using mysqli instead.
I think you're having problems displaying the result set.
Try this
$id = $_POST['PID'];
$result = "SELECT * FROM table WHERE id ='.$id.'";
while($row = mysqli_query($result))
{
echo $row[0]; //or whichever column you want to display.
//$row[0] will display your
// PK
}
How do I use the data returned by a SQL WHERE IN(x,y) statement with PHP?
$sqlquery = "SELECT * FROM schedules WHERE userid IN ('35','101','45')";
if ($test_stmt=$mysqli->prepare($sqlquery)) { //Get all data in schedule row
$test_stmt->execute(); //Execute the prepared query
$test_stmt->store_result(); //Store result
$test_stmt->fetch();
do something...
}
else {
return null;
}
}
The SQL query returns the correct three table rows, I'm just not sure how to access them with PHP.
How do I create an array to store the values the query returns? Or is there a better way to store this data to later be manipulated?
Thanks
The most common way to do this is through a loop akin to the following:
$results=array();
while($row=$test_stmt->fetch())
{
$results[]=$row;
}
This inserts the row into the results variable, which is an array. At the end of the loop, the array will contain a copy of everything the query returned.
You can also pick and choose what you do with particular columns in the results like this:
$results=array();
while($row=$test_stmt->fetch())
{
$results[]['ID']=$row['ID'];
}
This assumes there is a column called "ID" in the results though.
//$test_stmt->store_result(); //not needed
$rows = $test_stmt->fetchAll(PDO::FETCH_ASSOC); //or other fetch mode
print_r($rows); //$rows is an array of rows you can loop through
I seem to be having trouble understanding the concept of how to properly use the information in a MySQL database using PHP/MySQLi. As I understand it, you generate a variable representing the connection object:
$connectionObject = mysqli_connect('serverString', 'userString', 'passString', 'databaseString');
then, generate a variable representing the query string you want to use:
$queryString = "SELECT rowName FROM tableName";
then, generate a variable representing the result object returned from a successful query:
$resultObject = mysqli_query($connectionObject, $queryString);
then, you use the fetch_assoc() function to generate an array from the result object and assign it to a variable:
$resultArray = myqli_fetch_assoc($resultObject);
then, you can use a while loop to (I have trouble with this one) to sort through the array and use the content of the row somehow:
while ($resultArray) {
echo $resultArray["rowName"];
}
Do I have this concept the wrong way, somehow, because its just not working for me, even to output the text content of a text-based CHAR(10) field with the contents of no more than: "BLAH".
The need to loop through the array to pick out the array item by name in the end anyway seems moot to me to begin with, but no matter where I look, I find the same concept.
My script code, minus a few key details, is:
if ($connectionObject=mysqli_connect("host0", "username0", "password0", "mysqldatabase0")) {
echo "Con";
}
if ($queryString="SELECT 'testdata' FROM 'testtable'") {
echo "Query";
}
if ($resultObject=mysqli_query($connectionObject, $queryString)) {
echo "Result";
}
if ($resultArray=mysqli_fetch_assoc($resultObject)) {
echo "Array";
}
while ($row=$resultArray) {
echo $row["testdata"];
print_r ($row);
}
mysqli_fetch_assoc returns an associate array of string representing the fetched row in the result set which is your $resultObject.
The problem is where you're using the while loop. You want to capture the returned associative array in a variable and access your data via that variable like follows:
while ($row = $resultArray) {
echo $row["rowName"];
}
To sort by rowName you can use the mysql order by clause in your query like follows which returns your results sorted by rowName:
$queryString = "SELECT rowName FROM tableName order by rowName";
Update after OP posted full code:
In your first if statement what would happen if the connection failed? You want to add some error handling there:
$connectionObject=mysqli_connect("host0", "username0", "password0", "mysqldatabase0"));
if (!$connectionObject) {
// exist out of this script showing the error
die("Error connecting to database " . mysqli_error($connectionObject));
} else {
// Don't really need this else but I'll keep it here since you already had it
echo "Con";
}
The problem is here You are using single quotes for column name and table name which are mysql identifiers. MySQL identifiers quote character is backtick not single quote.
Basically you need to use backticks if one of these identifiers are one of mysql reserved words (MySQL Reserved words), for other cases you don't need to use them.
Update your query:
if ($queryString="SELECT `testdata` FROM `testtable`") {
echo "Query"; // Leaving as is, not required
}
Lastly, an improvement. You want to add error handling here too:
if ($resultObject=mysqli_query($connectionObject, $queryString)) {
echo "Result"; // Leaving as is, not required
} else {
echo "Error executing Query " . mysqli_error($connectionObject);
}
Please note that when you use this script the error messages will be printed at the client i.e. when you use this script in a web application the errors will be shown in the user's browser. So you want to look into implementing logging and not printing them directly.
mysqli_fetch_assoc() returns one row as an associative array, of a mysqli_result object. Each time it is called, it returns the next row of results automatically and when used with a while loop, can be used to fetch an unknown number of result rows.
The $row['columnName'] is used to refer to the column. For example, if you had a person object with columns firstName, lastName, dateOfBirth, you could iterate through each person with a while loop as such:
while($row=mysqli_fetch_assoc($resultObject)){
$fname = $row['firstName'];
$lname = $row['lastName'];
$dob = $row['dateOfBirth'];
echo $fname . ' ' . $lname . ' ' . $dob;
}
This will echo details for a result returning an unknown amount of people.
Remember, calling the
if ($resultArray=mysqli_fetch_assoc($resultObject)) {
echo "Array";
}
before the while loop will skip the first result, so make sure the query returns multiple results when testing, as if you are only providing a resultObject containing one result, this might be why it isn't returning anything.
A better way to check if any results are returned is with the mysqli_num_rows($resultObject) function.
if(mysqli_num_rows($resultObject) > 0){
echo "Array";
}
Also not sure if it was just a typo but just to be sure, in your query you are selecting columnName not rowName:
$queryString = "SELECT columnName1(eg. firstName), columnName2(eg. lastName) FROM tableName";
I just recently started learning PHP, and the mysqli_fetch_assoc function confused me too, so I hope this helps!
I have two dynamic tables (tabx and taby) which are created and maintained through a php interface where columns can be added, deleted, renamed etc.
I want to read all columns simulataneously from the two tables like so;-
select * from tabx,taby where ... ;
I want to be able to tell from the result of the query whether each column came from either tabx or taby - is there a way to force mysql to return fully qualified column names e.g. tabx.col1, tabx.col2, taby.coln etc?
In PHP, you can get the field information from the result, like so (stolen from a project I wrote long ago):
/*
Similar to mysql_fetch_assoc(), this function returns an associative array
given a mysql resource, but prepends the table name (or table alias, if
used in the query) to the column name, effectively namespacing the column
names and allowing SELECTS for column names that would otherwise have collided
when building a row's associative array.
*/
function mysql_fetch_assoc_with_table_names($resource) {
// get a numerically indexed row, which includes all fields, even if their names collide
$row = mysql_fetch_row($resource);
if( ! $row)
return $row;
$result = array();
$size = count($row);
for($i = 0; $i < $size; $i++) {
// now fetch the field information
$info = mysql_fetch_field($resource, $i);
$table = $info->table;
$name = $info->name;
// and make an associative array, where the key is $table.$name
$result["$table.$name"] = $row[$i]; // e.g. $result["user.name"] = "Joe Schmoe";
}
return $result;
}
Then you can use it like this:
$resource = mysql_query("SELECT * FROM user JOIN question USING (user_id)");
while($row = mysql_fetch_assoc_with_table_names($resource)) {
echo $row['question.title'] . ' Asked by ' . $row['user.name'] . "\n";
}
So to answer your question directly, the table name data is always sent by MySQL -- It's up to the client to tell you where each column came from. If you really want MySQL to return each column name unambiguously, you will need to modify your queries to do the aliasing explicitly, like #Shabbyrobe suggested.
select * from tabx tx, taby ty where ... ;
Does:
SELECT tabx.*, taby.* FROM tabx, taby WHERE ...
work?
I'm left wondering what you are trying to accomplish. First of all, adding and removing columns from a table is a strange practice; it implies that the schema of your data is changing at run-time.
Furthermore, to query from the two tables at the same time, there should be some kind of relationship between them. Rows in one table should be correlated in some way with rows of the other table. If this is not the case, you're better off doing two separate SELECT queries.
The answer to your question has already been given: SELECT tablename.* to retrieve all the columns from the given table. This may or may not work correctly if there are columns with the same name in both tables; you should look that up in the documentation.
Could you give us more information on the problem you're trying to solve? I think there's a good chance you're going about this the wrong way.
Leaving aside any questions about why you might want to do this, and why you would want to do a cross join here at all, here's the best way I can come up with off the top of my head.
You could try doing an EXPLAIN on each table and build the select statement programatically from the result. Here's a poor example of a script which will give you a dynamically generated field list with aliases. This will increase the number of queries you perform though as each table in the dynamically generated query will cause an EXPLAIN query to be fired (although this could be mitigated with caching fairly easily).
<?php
$pdo = new PDO($dsn, $user, $pass, array(PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION));
function aliasFields($pdo, $table, $delim='__') {
$fields = array();
// gotta sanitise the table name - can't do it with prepared statement
$table = preg_replace('/[^A-z0-9_]/', "", $table);
foreach ($pdo->query("EXPLAIN `".$table."`") as $row) {
$fields[] = $table.'.'.$row['Field'].' as '.$table.$delim.$row['Field'];
}
return $fields;
}
$fieldAliases = array_merge(aliasFields($pdo, 'artist'), aliasFields($pdo, 'event'));
$query = 'SELECT '.implode(', ', $fieldAliases).' FROM artist, event';
echo $query;
The result is a query that looks like this, with the table and column name separated by two underscores (or whatever delimeter you like, see the third parameter to aliasFields()):
// ABOVE PROGRAM'S OUTPUT (assuming database exists)
SELECT artist__artist_id, artist__event_id, artist__artist_name, event__event_id, event__event_name FROM artist, event
From there, when you iterate over the results, you can just do an explode on each field name with the same delimeter to get the table name and field name.
John Douthat's answer is much better than the above. It would only be useful if the field metadata was not returned by the database, as PDO threatens may be the case with some drivers.
Here is a simple snippet for how to do what John suggetsted using PDO instead of mysql_*():
<?php
$pdo = new PDO($dsn, $user, $pass, array(PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION));
$query = 'SELECT artist.*, eventartist.* FROM artist, eventartist LIMIT 1';
$stmt = $pdo->prepare($query);
$stmt->execute();
while ($row = $stmt->fetch()) {
foreach ($row as $key=>$value) {
if (is_int($key)) {
$meta = $stmt->getColumnMeta($key);
echo $meta['table'].".".$meta['name']."<br />";
}
}
}