multiple SQL tables with PHP to generate sitemap - php

I have a sitemap that's generated with PHP and actually its calling only the table retailers as below:
$query = "select * from retailers WHERE status='active' ORDER BY added DESC";
and construct as:
while ($row = mysql_fetch_array($result))
{
$i_url = SITE_URL.'loja/'.$row['slug_title'];
$year = substr($row['added'],0,4);
$month = substr($row['added'],5,2);
$day = substr($row['added'],8,2);
$i_date = ''.$year.'-'.$month.'-'.$day.'';
// you can assign whatever changefreq and priority you like
// changefreg - optional
// priority - optional
echo
'
<url>
<loc>'.$i_url.'</loc>
<lastmod>'.$i_date.'</lastmod>
<changefreq>daily</changefreq>
<priority>0.8</priority>
</url>
';
}
The problem is, only retailers page its coming, i need to get some more 3 tables, but i can't think on a way to call and construct more things inside that, maybe a PHP condition?
Thanks to everyone for your time!

I suggest you to create a function to handle the queries or subqueries you need
Like
Main Code
while ($row = mysql_fetch_array($result))
{
$i_url = SITE_URL.'loja/'.$row['slug_title'];
$year = substr($row['added'],0,4);
$month = substr($row['added'],5,2);
$day = substr($row['added'],8,2);
$i_date = ''.$year.'-'.$month.'-'.$day.'';
$data = subquery('what i need here', 'another param');
echo
'
<url>
<loc>'.$i_url.'</loc>
<lastmod>'.$i_date.'</lastmod>
<changefreq>daily</changefreq>
<priority>0.8</priority>
</url>
';
}
function subquery($firstparam, $secondparam)
{
$myquery = "SELECT * FROM ".$firstparam;
//more code
$result = 'my query result';
return $result;
}
With this you can call a subquery based on the main query, you can create more funcionts or create only one with different types that, can able you to do different queries in one function.

Since the tables all have the same fields we need (slug_name and added), we can just loop through each table with the same procedure, then output to sitemap.xml file.
// Our Echo Buffer
$buffer = array();
// Table Names
$tables = array( 'retailers', 'table2', 'table3', 'table4' );
// Using MySQLi, cause it's Improved.
$conn = new MySqli( 'localhost', 'user', 'pass', 'database' );
// Iterate over $tables
foreach( $tables as $table )
{
// Build Query
$query = "SELECT `slug_name`, `added` FROM $table" .
" WHERE status='active' ORDER BY added DESC";
// Get Result
$result = $conn->mysqli_query( $query );
// Iterate over Result
while( $row = $result->fetch_assoc() )
{
// Chop up the Date
$date = substr($row['added'],0,4) . '-' .
substr($row['added'],5,2) . '-' .
substr($row['added'],8,2);
// Add page details to $buffer
$buffer[] = '<url>' .
'<loc>' . SITE_URL . 'loja/' . $row['slug_title'] . '</loc>' .
'<lastmod>' . $date . '</lastmod>' .
'<changefreq>daily</changefreq>' .
'<priority>0.8</priority>' .
'</url>';
}
// Free MySQLi Result
$result->close();
}
// Output the Buffer to view. Make sure it looks good.
echo implode( "\r\n", $buffer );
// Remove the echo above and uncomment below if it looks good.
// if( ( $xml = fopen( 'sitemap.xml', "w" ) ) !== FALSE )
// {
// fwrite( $xml, implode( "\r\n", $buffer ) );
// }

Related

Query produces data, but the export is blank

I was recently tasked to update some older sites from MySQL to MySQLi.
Though slow and steady, the update has been ok until I ran into an issue when exporting some data to an excel document.
This code was written by a previous developer. There's a lot going on in the file, and I hope I'm grabbing the part that is supposed to be creating the excel document:
<?php
$export = mysqli_query ( $session->connDB(),$sql ) or die ( "Sql error : " . mysqli_error( ) );
$fields = mysqli_num_fields ( $export );
$num_rows = mysqli_num_rows( $export );
$pattern = '/[A-Z0-9][A-Z0-9._-]+#[A-Z0-9][A-Z0-9.-]{0,61}[A-Z0-9]\.[A-Z.]{2,6}/i'; //email
$phonpat = '/(\(?([0-9]{3})+\)?[\-\s\.]?([0-9]{3})+[\-\s\.]?([0-9]{4})(( |-|\.)?[ext\.]+ ?\d+)|\(?([0-9]{3})+\)?[\-\s\.]?([0-9]{3})+[\-\s\.]?([0-9]{4}))/i'; //telephone
$phPat = '/([0-9]{3})([0-9]{3})([0-9]{4})/';
$vippatt = '/VIP/i';
for($f=0; $f<$fields; $f++){
$header.='"'.mysqli_fetch_fields($export, $f).'"'."\t";
}
for($i=0; $i<$num_rows; $i++){
for($x=0; $x<$fields; $x++){
$email = mysqli_fetch_assoc($export,$i,"EMAIL");
$phone = mysqli_fetch_assoc($export,$i,"PHONE");
$viprm = mysqli_fetch_assoc($export,$i,"VIP");
preg_match ($pattern, $email, $matches);
preg_match ($phonpat, $phone, $phoneno);
preg_match ($vippatt, $viprm, $vpmatch);
if(isset($matches[0])) {$emal=strtolower($matches[0]);} else {$emal="";}
if(isset($vpmatch[0])) {$vips=strtoupper($vpmatch[0]);} else {$vips="";}
if(isset($phoneno[0])) {$phne=preg_replace($phPat,'($1) $2-$3 ',formatPhone($phoneno[0],false,false));} else {$phne="";}
if(mysqli_fetch_fields($export, $x)=='EMAIL'){
$fld=$emal;
} else {
if(mysqli_fetch_fields($export, $x)=='PHONE'){
$fld=$phne;
} else {
if(mysqli_fetch_fields($export, $x)=='VIP'){
$fld=$vips;
} else {
if(mysqli_fetch_fields($export, $x)=='UNITS'){
$fld=1;
} else {
$fld = mysqli_fetch_assoc($export,$i,mysqli_fetch_fields($export, $x));
}
}
}
}
$data.= '"'.$fld.'"'."\t";
}
$data.="\n";
}
?>
Here is where the code checks if the data is blank or not, and then exports the spreadsheet:
<?php
if ($data == "") {
$data = "\nNo records found for your search parameters.\n\n".$sql;
} else {
echo "should show data";
}
global $time;
$time = time();
header("Content-Disposition: attachment; filename=CargoManagementCustomReport-$time.xls");
header("Pragma: no-cache");
header("Expires: 0");
print "$header\n$data";
?>
When the spreadsheet gets exported, I see "should show data". This tells me the $data variable obviously has data. It's just not getting into the spreadsheet.
If you'll notice in the above, I'm using mysqli_fetch_fields. This was used to replace mysql_field_name (in my attempt to update to MySQLi).
I also tried mysqli_fetch_field, but got the same results.
I am getting no errors, but the spreadsheet is still blank.
I can echo $sql to get the query, and I can run the query in the database and it returns data.
What am I doing wrong and how can I fix it?
That whole code is gibberish, so I hope I understood what it is that it was meant to do.
Here are the main problems:
mysqli_fetch_fields() takes only 1 argument and returns an array of objects. You can't cast an array to a string. I assume you wanted to get the field name.
mysqli_fetch_assoc() takes only 1 argument and returns an array of data in an associative array as the name suggests. It also moves the internal pointer to the next row every time it is called. You are trying to use it as if it was mysql_result().
Your nested loops are very messy. I replaced them with simple foreach loops and replaced the nested if statements with a switch. While I would normally stay away from such constructs, this is the easiest way to migrate this code.
After removing all the mysqli nonsense, the code is now readable. It iterates over every field of every row, applying some transformations to some fields and concatenating the result into a string.
Fixed code:
$conn = $session->connDB();
$export = mysqli_query($conn, $sql);
$pattern = '/[A-Z0-9][A-Z0-9._-]+#[A-Z0-9][A-Z0-9.-]{0,61}[A-Z0-9]\.[A-Z.]{2,6}/i'; //email
$phonpat = '/(\(?([0-9]{3})+\)?[\-\s\.]?([0-9]{3})+[\-\s\.]?([0-9]{4})(( |-|\.)?[ext\.]+ ?\d+)|\(?([0-9]{3})+\)?[\-\s\.]?([0-9]{3})+[\-\s\.]?([0-9]{4}))/i'; //telephone
$phPat = '/([0-9]{3})([0-9]{3})([0-9]{4})/';
$vippatt = '/VIP/i';
foreach (mysqli_fetch_fields($result) as $field) {
$header .= '"' . $field->name . '"' . "\t";
}
$data = '';
foreach ($export as $row) {
foreach ($rows as $fieldName => $value) {
switch ($fieldName) {
case 'EMAIL':
preg_match($pattern, $value, $matches);
$data .= '"' . (isset($matches[0]) ? strtolower($matches[0]) : '') . '"' . "\t";
break;
case 'PHONE':
preg_match($phonpat, $value, $phoneno);
$phne = "";
if (isset($phoneno[0])) {
$phne = preg_replace($phPat, '($1) $2-$3 ', formatPhone($phoneno[0], false, false));
}
$data .= '"' . $phne . '"' . "\t";
break;
case 'VIP':
preg_match($vippatt, $value, $vpmatch);
$data .= '"' . (isset($vpmatch[0]) ? strtolower($vpmatch[0]) : '') . '"' . "\t";
break;
case 'UNITS':
$data .= '"1"' . "\t";
break;
default:
$data .= '"' . $value . '"' . "\t";
break;
}
}
$data .= "\n";
}

SQL Query returns null?

I want to get all names of my products and push them into an array. If I use the SQL Query (SELECT name FROM wp_all_import_xml GROUP BY name) in phpmyadmin I get this:
But if I use the query in my script I get this array:
array (
0 => NULL,
1 => NULL,
2 => NULL,
3 => NULL,
4 => NULL,
...)
So, the query must return null. But why? - Everything is correct!
I do not get any connection error or query error... Where is my error?
I already tried to decode the strings and I also tried $myTitles[] = $tmp. But it also doesn't work... Any ideas?
And because everything in the $myTitles array is null, the script always enters the if(!(in_array($title, $myTitles) condition and I cannot execute what I actual want... I can only execute this, if the array and the condition is really true!
<?php
if ( ! defined('ABSPATH') ) {
// Set up WordPress environment
require_once( dirname( __FILE__ ) . '/wp-load.php' );
}
unlink('deleteOldProducts.txt');
$myfile = fopen('deleteOldProducts.txt', "w");
$database_gk = new mysqli("localhost", "censored", "censored", "censored");
$database_jt = new mysqli("localhost", "censored", "censored", "censored");
$myTitles = array();
$string = "";
if($database_jt->connect_errno){
$string .= "+++Couldn't connect to database_jt!+++\n\n");
}
if($database_gk->connect_errno){
$string .= "+++Couldn't connect to database_gk!+++\n\n");
}
$values_jt = $database_jt->query("SELECT name FROM `wp_all_import_xml` GROUP BY name");
$string .= $database_jt->error . "\n";
while($rowj = $values_jt->fetch_assoc()){
$tmp = utf8_encode($row["name"]);
array_push($myTitles, $tmp);
$tmp = null;
}
$values_gk = $database_gk->query("SELECT `post_title` FROM `fWR6qIN_posts` where post_type = 'product' AND post_status = 'publish' GROUP BY `post_title`");
$string .= $database_gk->error . "\n";
$string .= "+++ Start of Check +++\n\nMein Array:\n" . var_export($myTitles, true) . "\n\n";
$i = 1;
while($row = $values_gk->fetch_assoc()){
$title = utf8_decode($row["post_title"]);
if(!(in_array($title, $myTitles))){
$string .= $i . ":\t" . $title . "\n";
$i = $i + 1;
}
$title = null;
}
$string .= "\n +++ End of Check! +++";
fwrite($myfile, $string);
fclose($myfile);
?>
Greetings and Thank You!
Your while isn't correct. On while you are using $rowj but on array_push you are using $row. You can try the following code instead:
while($row = $values_jt->fetch_assoc()) {
$myTitles[] = utf8_encode($row["name"]);
}
Note: If you use array_push() to add one element to the array it's better to use $array[] = because in that way there is no overhead of calling a function.
http://php.net/manual/en/function.array-push.php

Insert XML to MySQL db whilst making sure it is UTF8 and just in plain text (no symbols - é and such)

I'm learning PHP or trying to by messing around with this small project.
I receive an XML weekly that I need to put into a mysql db, here's a small sample of what it looks like (It's usually a 35 children per Offer 50,000 Offer file.)
<?xml version="1.0" encoding="iso-8859-1"?>
<Offers>
<Offer>
<ProductName>10073482</ProductName>
<Manufacturer>Random Brand</Manufacturer>
<Description>Loerm ipsum....100-3000characters</Description>
<ModelNumber>5191181</ModelNumber>
<Price>29.99</Price>
</Offer>
<Offer>
<ProductName>10073482</ProductName>
<Manufacturer>Random Brand</Manufacturer>
<Description>Loerm ipsum....100-3000characters</Description>
<ModelNumber>5191181</ModelNumber>
<Size>Large</Size>
<Price>29.99</Price>
</Offer>
</Offers>
I guess ideally I want to:
import the XML make sure its all websafe
make it UTF-8
strip all symbols such as é
find all the used fields per product
make a table with that info
force that massive XML into the table
After import I should have 48,000 items yet playing with different encode's like urlencode sometimes I get 26,000 and another time 52,000.
Here's what I've got so far: (Be gentle)
<?php
ini_set('display_errors','On');
ini_set('max_execution_time', 300);
// Establish connection to database
$con2 = mysql_connect("localhost","root","root");
if (!$con2) {
die('Could not connect: ' . mysql_error());
}
$selectdb = mysql_select_db("f1", $con2);
if (!$selectdb) {
die('Database not used: ; ' . mysql_error());
}
// Vars
$name = $_GET['name'];
$filename = $name . ".xml";
$tableCreateQuery = "CREATE TABLE $name ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,";
// Load XML
if (file_exists($filename)) {
$xml = simplexml_load_file($filename);
foreach ($xml->children()->children() as $child){
$currentAttrib = $child->getName();
// Create query to create mysql table
$tableCreateQuery .= " `$currentAttrib` TEXT,";
}
$tableCreateQuery = rtrim($tableCreateQuery, ",");
$tableCreateQuery .= ") CHARACTER SET utf8";
// Create mysql table
mysql_query($tableCreateQuery);
// Loop through adding XML to new mysql table
$pCount = 0;
foreach ($xml->children() as $child){
$pCount++;
$theColumnsArr = array();
$theColumnsStr = "";
$theDataArr = array();
$theDataStr = "";
$i = 0;
foreach ($child->children() as $attrib){
$attrName = $attrib->getName();
$theColumnsArr[$i] = $attrName;
$theDataArr[$i] = urlencode(utf8_encode($attrib));
$i++;
}
$k = 0;
foreach ($theColumnsArr as $value) {
$colname = $theColumnsArr[$k];
$coldata = $theDataArr[$k];
$theColumnsStr .= "`$colname`,";
$theDataStr .= "'$coldata',";
$k++;
}
$theColumnsStr = rtrim($theColumnsStr, ",");
$theDataStr = rtrim($theDataStr, ",");
$theRow = "INSERT INTO $name ($theColumnsStr) VALUES ($theDataStr)";
mysql_query($theRow) or die(mysql_error());
}
echo $pCount . " products added to database";
} else {
exit("Failed to open $filename");
}
mysql_close($con2);
?>

How to avoid repetition of one of several items in array (category name)

I know there are similar questions here and I have read some of the posts and answers, experimented with some of them, but whether it is my limited knowledge of PHP or the peculiarity of my case, I need to ask this.
I am building a dictionary (id, english, bulgarian, theme_id) and would like to group the search results according to theme_id. I am using ORDER BY theme_id, id in my query but I end up displaying the theme with each of the results, while I would like to categorize them as follows:
THEME 1
- result 1
- result 2
THEME 2
- result 3
- result 4
.....
Here is the relevant part of my code:
while($row = mysql_fetch_array($result)) {
//$id = $row['id'];
$english = $row['english'];
$bulgarian = $row['bulgarian'];
$theme_id = $row['theme_id'];
$theme_name = "theme_".$lang;
$theme_query= mysql_query("SELECT theme_id,".$theme_name." FROM ".DICTIONARY_THEMES." WHERE theme_id = ".$theme_id."");
$theme_row = mysql_fetch_array($theme_query);
$theme = $theme_row[$theme_name];
if($source == "english") {
foreach($keywords as $keyword) {
$english = preg_replace("|($keyword)|Ui", "<span style=\"color:#780223\">".$keyword."</span>", $english);
}
$print .= "<li class=\"results-row\">".$theme.": ".$english." = ".$bulgarian."</li>";
}
elseif($source == "bulgarian") {
foreach($keywords as $keyword) {
$bulgarian = preg_replace("|($keyword)|Ui", "<span style=\"color:#780223;\">".$keyword."</span>", $bulgarian);
}
$print .= "<li class=\"results-row\">".$theme.": ".$bulgarian." = ".$english."</li>";
}
}//end while
EDIT: SOLVED, a friend has helped improve my code.
while($row = mysql_fetch_array($result)) {
$english = $row['english'];
$bulgarian = $row['bulgarian'];
$theme_id = $row['theme_id'];
$theme_name = "theme_".$lang;
$theme_query= mysql_query("SELECT theme_id,".$theme_name." FROM ".DICTIONARY_THEMES." WHERE theme_id = ".$theme_id."");
$theme_row = mysql_fetch_array($theme_query);
$theme = $theme_row[$theme_name];
// add all results to an array
$results[] = array(
'english' => $english,
'bulgarian' => $bulgarian,
'theme' => $theme
);
}//end while
$theme = null;
foreach ($results as $result) {
if ($theme != $result['theme']) {
$theme = $result['theme'];
$print .= "<h3>" . $result['theme'] . "</h3>";
}
if ($source == "english") {
foreach ($keywords as $keyword) {
$result['english'] = preg_replace("|($keyword)|Ui", "<span style=\"color:#780223\">" . $keyword . "</span>", $result['english']);
}
$print .= "<li class=\"results-row\">" . $result['english'] . " = " . $result['bulgarian'] . "</li>";
} elseif ($source == "bulgarian") {
foreach ($keywords as $keyword) {
$result['bulgarian'] = preg_replace("|($keyword)|Ui", "<span style=\"color:#780223;\">" . $keyword . "</span>", $result['bulgarian']);
}
$print .= "<li class=\"results-row\">" . $result['bulgarian'] . " = " . $result['english'] . "</li>";
}
}
Based on your code, you should first add all items to an array and afterwards print that array in a separate function/block.
Right after your second MySQL query, put something like
$output[$theme_id] = mysql_fetch_array( $theme_query );
and move all the following code out of the outer result-while-loop (while($row = mysql_fetch_array($result))).
But in fact I would try to put a MySQL query together, to have an ordered, grouped result with all the selected themes in all languages and without querying the database inside a loop.
Or you use something existing, for example this singleton Lexicon class.

PHP function Absolute URL Display Problem

I'm trying to get my function to display my categories absolute url address for example http://www.example.com/cat/sub-1/sub-2/sub-3/ But I keep getting http://www.example.com/cat//sub-3/ can some one help me correct this problem. Please be detailed as possible since I'm farily new to PHP.
Here is my PHP function
function allCategories(){
global $parent_url;
global $url;
$nodeList = array();
$tree = array();
$query = mysqli_query(database(),"SELECT * FROM categories ORDER BY parent_id, category LIKE '%more%', category ASC");
while($row = mysqli_fetch_assoc($query)){
$nodeList[$row['id']] = array_merge($row, array('children' => array()));
}
mysqli_free_result($query);
foreach($nodeList as $nodeId => &$node) {
if(!$node['parent_id'] || !array_key_exists($node['parent_id'], $nodeList)){
$tree[] = &$node;
$url = $parent_url . $node['url'];
$url = str_replace('?cat=', '', $url);
echo '<li>' . strip_tags($node['category']) . '';
} else {
$nodeList[$node['parent_id']]['children'][] = &$node;
$url = $parent_url . $node['url'];
$cat_num = array('?cat=','&sub1=','&sub2=');
$url = str_replace($cat_num, '/', $url);
echo '<li>' . strip_tags($node['category']) . '';
}
echo '</li>';
}
echo '</ol>';
unset($node);
unset($nodeList);
}
allCategories();
I suspect your query is erroring out at the MySQL level, and you don't have anything set up to tell you so (especially if warnings are turned off in the php.ini file).
Try adding something like this to the line that starts with $query:
or die( "<h1>SELECT query failed!</h1> <p>Error: " . mysqli_error( $dbc ) . "</p>" );
$dbc needs to be replaced with whatever variable holds your database connection.
Obviously, this is for debugging only. You would replace die with some error-handling function on a production server.

Categories