Rearranging logic that uses multipe foreach conditions - php

I have some code that takes an rss feed url, expands the rss link and gets the individual links inside that feed xml. After checking if a link exists, i insert it to a table if it does not exist and do nothing if it does. However my code is becoming more unreadable and one more check that requires another foreach it shall be even more unreadable.
This is the code
public function links_cron_job(){
//Get Rss Links
$this->db->select("the_link_itself");
$query = $this->db->get_where("search_engine_links", array("link_type" => "rss"));
foreach ($query->result() as $row){
$url = $row->the_link_itself;
$rss = Feed::loadRss($url);
foreach ($rss->item as $item) {
$this->db->where('the_link_itself',$item->link);
$query3 = $this->db->get('search_engine_links');
if ($query3->num_rows() > 0){
echo 'duplicates are there';
}else{
$data = array(
'link_country' => 'usa',
'the_link_itself' => $item->link,
'link_category' => 'news_website',
'link_added_by' => 'admin',
'link_type' => 'ordinary_link',
'link_local_type' => 'news',
'link_region' => 'countrywide',
'link_city' => 'washington',
'date_added' => $item->timestamp,
'last_updated' => time()
);
$this->db->insert('search_engine_links', $data);
echo 'no duplicates are there';
}
}
}
}
What would be another approach in doing what i am doing?

Normally I would say, just enter a return. But in this case you still might have
work to do in the extra iterations. So in this case at least we know that we are
done with this iteration, so at least we can add a continue statement:
<?php
foreach ($rss->item as $item) {
$this->db->where('the_link_itself',$item->link);
$query3 = $this->db->get('search_engine_links');
if ($query3->num_rows() > 0) {
echo 'duplicates are there';
continue;
}
$data = array(
'link_country' => 'usa',
'the_link_itself' => $item->link,
'link_category' => 'news_website',
'link_added_by' => 'admin',
'link_type' => 'ordinary_link',
'link_local_type' => 'news',
'link_region' => 'countrywide',
'link_city' => 'washington',
'date_added' => $item->timestamp,
'last_updated' => time()
);
$this->db->insert('search_engine_links', $data);
echo 'no duplicates are there';
}

Related

update batch in codeigniter

I have data on db_temporary here I will update based on id_service, but why doesn't the update work?
public function updateUpload() {
$db = $this->M_order->db_temporary_service(); //db_temporary
$data = array();
foreach($db AS $key => $val){
$data[] = array(
"id_service" => $_POST['id_service'][$key],
"id_destination" => $_POST['id_destination'][$key],
"id_sub_destination" => $_POST['id_sub_destination'][$key],
"charges_order" => $_POST['charges_order'][$key],
"weight_order" => $_POST['weight_order'][$key],
"jenis_service" => $_POST['jenis_service'][$key],
"service_order" => $_POST['service_order'][$key],
"charges_order" => $_POST['charges_order'][$key],
);
echo '<pre>', print_r($data);
//update to db_service where id_service
$this->db->update_batch('service', $data, 'id_service');
redirect('backend/.....');
}
}
The data doesn't seem to be updated because you've used update_batch as well as redirect inside foreach loop, I'm writing the rectified code below, comments are mentioned wherever necessary. See if it resolves your issue.
public function updateUpload(){
$db = $this->M_order->db_temporary_service(); //db_temporary
$data = array();
foreach($db AS $key => $val){
$data[] = array(
"id_service" => $_POST['id_service'][$key],
"id_destination" => $_POST['id_destination'][$key],
"id_sub_destination" => $_POST['id_sub_destination'][$key],
"charges_order" => $_POST['charges_order'][$key],
"weight_order" => $_POST['weight_order'][$key],
"jenis_service" => $_POST['jenis_service'][$key],
"service_order" => $_POST['service_order'][$key],
"charges_order" => $_POST['charges_order'][$key],
);
}
// echo '<pre>', print_r($data); // all the data should be here
$this->db->update_batch('service', $data, 'id_service'); // update the table with all the data
redirect('backend/.....');
}

How to display the value of array as string or text not as index value

I have two table one for sections where each section has many questions when i echo i got the section text but the questions as index value 0 1 2
<?php
$result = mysql_query($query);
if ($result) {
$data = array();
while ($row = mysql_fetch_assoc($result)) {
$data[($row['SECTION_NAME'])][][($row['QUES_TEXT'])][] = array(
'SECTION' => $row['SECTION_NAME'],
'QUESTION' => $row['QUES_TEXT']
);
}
foreach ($data as $SECTION => $QUESTIONS) {
echo '<h2>',htmlentities($SECTION),'</h2>';
foreach ($QUESTIONS as $QUESTIONS_TEXT => $TEXT) {
echo '<h2>',($QUESTIONS_TEXT),'</h2>';
}
}
}
?>
You are creating extra nested arrays and also the parens are unneeded:
$data[$row['SECTION_NAME']][][$row['QUES_TEXT']][] = array(
'SECTION' => $row['SECTION_NAME'],
'QUESTION' => $row['QUES_TEXT']
);
Should be:
if (empty($data[$row['SECTION_NAME']]) {
$data[$row['SECTION_NAME']] = array();
}
$data[$row['SECTION_NAME']][$row['QUES_TEXT']] = array(
'SECTION' => $row['SECTION_NAME'],
'QUESTION' => $row['QUES_TEXT']
);
Also please see the comments to your original question, this is no longer a safe way to use MySQL from PHP.

Dynamic variables in looper

This is my simple looper code
foreach( $cloud as $item ) {
if ($item['tagname'] == 'nicetag') {
echo $item['tagname'];
foreach( $cloud as $item ) {
echo $item['desc'].'-'.$item['date'];
}
} else
//...
}
I need to use if method in this looper to get tags with same names but diferent descriptions and dates. The problem is that I dont know every tag name becouse any user is allowed to create this tags.
Im not really php developer so I'm sory if it's to dummies question and thanks for any answers!
One possible solution is to declare a temporary variable that will hold tagname that is currently looped through:
$currentTagName = '';
foreach( $cloud as $item ) {
if ($item['tagname'] != $currentTagName) {
echo $item['tagname'];
$currentTagName = $item['tagname'];
}
echo $item['desc'] . '-' . $item['date'];
}
I presume that your array structure is as follows:
$cloud array(
array('tagname' => 'tag', 'desc' => 'the_desc', 'date' => 'the_date'),
array('tagname' => 'tag', 'desc' => 'the_desc_2', 'date' => 'the_date_2'),
...
);
BUT
This solution raises a problem - if your array is not sorted by a tagname, you might get duplicate tagnames.
So the better solution would be to redefine your array structure like this:
$cloud array(
'tagname' => array (
array('desc' => 'the_desc', 'date' => 'the_date'),
array('desc' => 'the_desc_2', 'date' => 'the_date_2')
),
'another_tagname' => array (
array('desc' => 'the_desc_3', 'date' => 'the_date_3'),
...
)
);
and then you can get the data like this:
foreach ($cloud as $tagname => $items) {
echo $tagname;
foreach($items as $item) {
echo $item['desc'] . '-' . $item['date'];
}
}

How to loop multidimensional array from mysql table with php

After reading muiltiple stackoverflow questions I'm still confused on why I am not able to get this to work. I am attempting to take all of the rows of a mysql table and put them into a multidimensional array. I was hoping to just find a simple example but so far I'm not fully understanding.
The examples I've seen on google and stack is mostly about parsing or making it iterate on the page. I am attempting to have the mysql rows iterate into their arrays. The example code I started working with was similiar to this:
// This will hopefully get all of the categories
case 'get_all_categories' :
$query = '
SELECT `id`,`category_name`, `category_spam`
FROM `category`
';
if (!$go = #mysql_query($query)) {
$results = Array(
'head' => Array(
'status' => '0',
'error_number' => '604',
'error_message' => 'Select Failed. '.
'Probably wrong name supplied.'
),
'body' => Array ()
);
} else {
$fetch = mysql_fetch_row($go);
$return = Array($fetch[0],$fetch[1]);
$results = Array(
'body' => Array (
'id' => $return[0],
'category_name' => $return[1]
)
);
}
break;
This obviously provides me with the result of just ONE as that is what I'm asking it to do with fetch_row.
i.e.
//outputs
{"body":{"id":"1","category_name":"Star Wars"}}
I've attempted to use mysql_fetch_assoc and then do a foreach loop?
I"ve also tried doing a mysql_fetch_all($go) and then attempt to put the rows into it.
if (!$go = #mysql_query($query)) {
$results = Array(
'head' => Array(
'status' => '0',
'error_number' => '604',
'error_message' => 'Select Failed. '.
'Probably wrong name supplied.'
),
'body' => Array ()
);
} else {
while($myrow = mysql_fetch_row($go)){
Array(
'body' => Array(
'id' => $myrow[o],
'category_name' => $myrow[1],
'category_spam' => $myrow[2]
)
}
);
}
break;
I am attempting to make an api call where the body holds all of the categories and their id's (the point I believe is then for the categories to pull and show the lists...which I'm hoping is the right away to make an api(not a question just rambling)
So: how do I make the query take all of the mysql rows and loop them into arrays for the body array. (note: I'm new to API's if my terminology is wrong to what my overall goal is which is to get an api call to show my whole mysql array then please let me know).
EDIT Just adding more info from the comments
The output is JSON encoded (sorry I should have explained that)
switch ($_GET['format']) {
case 'xml' :
#header ("content-type: text/xml charset=utf-8");
$xml = new XmlWriter();
$xml->openMemory();
$xml->startDocument('1.0', 'UTF-8');
$xml->startElement('callback');
$xml->writeAttribute('xmlns:xsi','http://www.w3.org/2001/XMLSchema-instance');
$xml->writeAttribute('xsi:noNamespaceSchemaLocation','schema.xsd');
function write(XMLWriter $xml, $data){
foreach($data as $key => $value){
if(is_array($value)){
$xml->startElement($key);
write($xml, $value);
$xml->endElement();
continue;
}
$xml->writeElement($key, $value);
}
}
write($xml, $results);
$xml->endElement();
echo $xml->outputMemory(true);
break;
case 'json' :
#header ("content-type: text/json charset=utf-8");
echo json_encode($results);
break;
case 'php' :
header ("content-type: text/php charset=utf-8");
echo serialize($results);
break;
}
$res = mysql_query($query);
$results = array();
$i = 0;
while($row=mysql_fetch_array($res)) {
$results['body'][$i]['id'] = $row[o];
$results['body'][$i]['category_name'] = $row[1];
$results['body'][$i]['category_spam'] = $row[2];
$i++;
}
if(empty($results['body'])){
$results['head'] = Array(
'status' => '0',
'error_number' => '604',
'error_message' => 'Select Failed. '.
'Probably wrong name supplied.'
);
}
break;
Try the above code it will create $result array for your json response.
Rest everything is fine!

Relationship in php array

I am using Gdata API to get Youtube video and comments. The reply is in XML which contains an array inside it.
For video ID and comments the XML response are different. For example I am getting array ID as video ID array and for one ID one or many comments in array.
Array of both video ID and comments is as follow:
foreach ($array as $entry)
{
$videoid = basename($entry);
$video[] = $videoid;
$logger->info('Response From Youtube:videoid=>' . $videoid);
}
$this->view->videoid = $video;
$author = array();
$content = array();
$arraycnt = array();
foreach ($video as $id)
{
$comment = "http://gdata.youtube.com/feeds/api/videos/".$id."/comments";
$sxml1 = simplexml_load_file($comment);
$entries = $sxml1->entry;
foreach ($entries as $a)
{
$author[] = $a->author->name;
$content[] = $a->content;
}
}
And the particular view as follow:
<table>
<tr>
<td>
<?php
for($i=0;$i<$length;$i++)
{
?>
<embed
width="420" height="345"
src="http://www.youtube.com/v/<?php echo $videoid[$i];?>"
type="application/x-shockwave-flash">
</embed>
<?php
}
?>
</td>
<td>
<?php
foreach($content as $cont)
{
?>
<p>Comment:<?php echo $cont;?></p>
<?php
}
?>
</td>
<td>
<?php
foreach($author as $auth)
{
?>
<p>Commented By:<?php echo $auth;?></p>
<?php
}
?>
</td>
</tr>
</table>
How can I show the video and comments in the view like:
videoA1 commentA1 commentA2
videoB1 commentB1 commentB2 commentB3
You can keep the id of the video in $author and $content arrays.
foreach ($video as $id)
{
foreach ($entries as $a)
{
$author[$id][] = $a->author->name;
$content[$id][] = $a->content;
}
}
So you can get comment's authors from specific video id:
foreach ($video as $id)
{
echo $id;
foreach($author[$id] as $auth) {
echo ' ', $auth;
}
}
The same goes with comment's content.
Of course you can extend this solution if you want to have just one array for comment's authors and content, but the logic stays the same.
What you actually have here is that you first iterate over the videos and then per each video you iterate over the comments.
So you have a nested iteration: Level 1: Videos, Level 2: Comments.
As I commented earlier you can create a data-structure that is able to have data that can be iterated that way in a multi-dimensional array. Let's take two Youtube videos here in the following example:
-FRm3VPhseI: The Clean Code Talks - "Global State and Singletons"
RlfLCWKxHJ0: The Clean Code Talks - Don't Look For Things!
So if you would want to create a multi-dimenstional array over these two videos with all their comments, you could choose the following format:
$videos = array(
'-FRm3VPhseI' => array(
'id' => '-FRm3VPhseI',
'title' => 'The Clean Code Talks - "Global State and Singletons"',
'href' => 'http://www.youtube.com/watch?v=-FRm3VPhseI&feature=youtube_gdata',
'comments' => array(
array(
'author' => 'Nelson ThePrimate',
'content' => 'There is a cost for r...',
),
array(
'author' => 'dennisdegreef',
'content' => 'That is also a global...',
),
array(
'author' => 'MorleyCode',
'content' => 'State is unavoidable,...',
),
// ...
array(
'author' => 'Jacob Jensen',
'content' => 'I don\'t quite underst...',
),
array(
'author' => 'unity20000',
'content' => 'Testing is not the on...',
),
array(
'author' => 'drummist180',
'content' => 'Turing machine > line...',
),
),
),
'RlfLCWKxHJ0' => array(
'id' => 'RlfLCWKxHJ0',
'title' => 'The Clean Code Talks - Don\'t Look For Things!',
'href' => 'http://www.youtube.com/watch?v=RlfLCWKxHJ0&feature=youtube_gdata',
'comments' =>
array(
array(
'author' => 'Nikolai Paul',
'content' => 'this guy sometimes so...',
),
array(
'author' => 'Madrid Softwaree',
'content' => 'Learn Selenium , QTP ...',
),
array(
'author' => 'Roger Keulen',
'content' => 'Di: Great as a FXCop ...',
),
// ...
array(
'author' => 'michaeldeng1981',
'content' => 'if I do outsourcing p...',
),
array(
'author' => 'Rico Lelina',
'content' => 'How about loggers? Is...',
),
array(
'author' => 'twistedbydsign99',
'content' => '11:55 it should defin...',
),
),
),
);
It first contains all videos keyed/indexed by the Youtube ID and then inside all the comments. To output this, you only have to nest two foreach clauses:
foreach ($videos as $videoId => $video)
{
printf("%s: %s\n", $videoId, $video['title']);
printf(" Comments (%d):\n", count($video['comments']));
foreach ($video['comments'] as $i => $comment)
{
printf(" #%d %s: %s\n", $i + 1, $comment['author'], $comment['content']);
}
echo "\n";
}
Which will create the following output:
-FRm3VPhseI: The Clean Code Talks - "Global State and Singletons"
Comments (6):
#1 Nelson ThePrimate: There is a cost for r...
#2 dennisdegreef: That is also a global...
#3 MorleyCode: State is unavoidable,...
#4 Jacob Jensen: I don't quite underst...
#5 unity20000: Testing is not the on...
#6 drummist180: Turing machine > line...
RlfLCWKxHJ0: The Clean Code Talks - Don't Look For Things!
Comments (6):
#1 Nikolai Paul: this guy sometimes so...
#2 Madrid Softwaree: Learn Selenium , QTP ...
#3 Roger Keulen: Di: Great as a FXCop ...
#4 michaeldeng1981: if I do outsourcing p...
#5 Rico Lelina: How about loggers? Is...
#6 twistedbydsign99: 11:55 it should defin...
Note that in this output the number of comments are limited to 6 each time because I reduced the amount of comments for the example array. Now compare closely how the structure of the nested, multi-dimensional array is read from with the nested foreach clauses. The outer foreach is reading the video, the inner foreach is reading the comments.
This btw. is the same with building that array, it works as well with two nested iterations. To make this more simple I first create a caching variable and some helper functions:
$gdataFetchCache = [];
$gdataFetch = function ($url) use (&$gdataFetchCache)
{
if (!isset($gdataFetchCache[$url]))
{
$gdataFetchCache[$url] = simplexml_load_file($url);
}
return $gdataFetchCache[$url];
};
$gdataNamed = function ($pattern) use ($gdataFetch)
{
return function ($value) use ($pattern, $gdataFetch)
{
return $gdataFetch(sprintf($pattern, $value));
};
};
$ytVideo = $gdataNamed('http://gdata.youtube.com/feeds/api/videos/%s');
$ytComments = $gdataNamed('http://gdata.youtube.com/feeds/api/videos/%s/comments');
These functions allow to fetch Youtube data more easily inside the nested foreach-es:
$videoIds = ['-FRm3VPhseI', 'RlfLCWKxHJ0'];
$videos = [];
foreach ($videoIds as $videoId)
{
$video = $ytVideo($videoId);
$videoArray = [
'id' => (string)$videoId,
'title' => (string)$video->title,
'href' => (string)$video->link['href'],
'comments' => [],
];
$videos[$videoId] = $videoArray;
foreach ($ytComments($videoId)->entry as $comment)
{
$videos[$videoId]['comments'][] = [
'author' => (string)$comment->author->name,
'content' => (string)$comment->content,
];
}
}
If you compare closely again, it has the same structure as the output code.
This is how you can read and create multi-dimensional arrays for which the count is not known in advance. By iterating you create the code for one element but use it as often as you have elements.
This also works nested.

Categories