OK I hope this isn't too specific. I have a database driven CMS that a coworker uses with many categories in it. Here's how it echoes some products we have now:
$offers = get_offers('category1','none','compare');
foreach ($offers as $row) {
$offername = $row['name'];
$offerlogo = $row['logo'];
$offera=$row['detailA'];
$offerb=$row['detailB'];
$offerc=$row['detailC'];
echo "you can have $offername, it's logo looks like <img src='$offerlogo'>" it's characteristics are $offera, offerb, offerc, etc";}
This works fine. My the problem is I want to get offera, offerb and offerc from another category, category 2. I tried going like this:
$offers = get_offers('category1','none','compare');
foreach ($offers as $row) {
$offername = $row['name'];
$offerlogo = $row['logo'];
$offers = get_offers('category2','none','compare');
$offera=$row['detailA'];
$offerb=$row['detailB'];
$offerc=$row['detailC'];
echo "you can have $offername, it's logo looks like <img src='$offerlogo'>" it's characteristics are $offera, offerb, offerc, etc";}
But of course that doesn't work. I don't want my coworker to have to go through the CMS and copy all the information over, is there a way to make this work?
Assuming the ordering of the results from both calls to get_offers matches up, I believe this might work for you:
$offers['cat1'] = get_offers('category1', 'none', 'compare');
$offers['cat2'] = get_offers('category2', 'none', 'compare');
$numberOfOffers = count($offers['cat1']);
for ($i = 0; $i < $numberOfOffers; $i++)
{
$offername = $offers['cat1'][$i]['name'];
$offerlogo = $offers['cat1'][$i]['logo'];
$offera = $offers['cat2'][$i]['detailA'];
$offerb = $offers['cat2'][$i]['detailB'];
$offerc = $offers['cat2'][$i]['detailC'];
echo "you can have $offername, its logo looks like <img src='$offerlogo'> its characteristics are $offera, $offerb, $offerc, etc\n";
}
I agree with ngm. If the categories match up then you could bring the results from the different call with the following:
$offersCat1 = get_offers('category1','none','compare');
$offersCat2 = get_offers('category2','none','compare');
foreach ($offers as $key=>$row) {
$offera=$offersCat2[$key]['detailA'];
$offerb=$offersCat2[$key]['detailB'];
$offerc=$offersCat2[$key]['detailC'];
echo "you can have {$row['name']}, it's logo looks like <img src='{$row['logo']}'> it's characteristics are $offera, offerb, offerc, etc";
}
This example will do the same thing, but you keep it in the foreach loop. By using the $key=>$row you are able to access the key of the array. I also took the liberty to echo your variables directly rather than putting them in variables. If you put {} around an array variable (or class variable) you can use them within an echo, print or <<<. This makes my life easier.
Example: echo "This variable {$variable['test']}";
Related
I started mixing XML with PHP today and I'm pretty bad at it, even though it looks super simple.
Right now, I'm trying to make something that sounds very easy but I can't understand how it works. I'm basically trying to create a fake mailbox for a game.
So I stored my emails in an XML file, classed by categories (received, sent, etc.). I managed to get the list of emails depending on the category, but I can't get to the part where I click on an email and it shows the content of this particular email.
Here is my simplified code:
XML :
<mailbox>
<received>
<expediter>James</expediter>
<content>Blah blah blah</content>
</received>
<received>
<expediter>Paul</expediter>
<content>Bluh bluh bluh</content>
</received>
<sent>
<expediter>Jack</expediter>
<content>Blah blah blah</content>
</sent>
<sent>
<expediter>John</expediter>
<content>Bluh bluh bluh</content>
</sent>
</mailbox>
XML;
?>
PHP :
<?php
include 'emails.php';
$emails = new SimpleXMLElement($xmlstr);
$cat = $_GET['cat'];
if(!isset($_GET['id'])){
$i = 0;
foreach($emails->$cat as $mailbox){
echo ''.$mailbox->expediter.'<br />';
$i++;
}
}
else{
$id = $_GET['id'];
echo $emails->$cat[$id]->content;
}
?>
So if there is no ID in the url, it shows the list of expediters with links to the email and if there is an ID in the url, it should show the content of the email designed by this number.
It works if I write manually :
echo $emails->received[1]->content;
But of course, I want that part to be dynamic and it doesn't work with :
echo $emails->$cat[$id]->content;
Is there any way to do that?
Thank you!
Camille
Try this:
$a = new stdClass();
$b = new stdClass();
$b->field = 5;
$a->list = array(
1 => $b
);
print_r($a);
$param = 'list';
$id = 1;
print_r($a->list[1]->field); // outputs 5;
print_r($a->{$param}[$id]->field); // outputs 5;
The key is:
$a->{$param}[$id]->field // notice the curly brackets.
Adapting to your question, you should use:
echo $emails->{$cat}[$id]->contenu;
As a good practice, you might want to check if it exists first:
if(isset($emails->{$cat}[$id])){
// echo it here, after you know it exists
}
You can see it online at 3v4l example
Sorry if the title is slightly confusing, I couldn't find the correct words to formulate it correctly.
A little bit of context: I'm trying to get data from 2 classes and echo them into 1 line.
Here's my code:
foreach ($site->find('.version a') as $source) {
foreach ($site->find('.version_numb') as $pwGetFrame) {
$pwFrame = $pwGetFrame->innertext;
$getURL = $source->href;
$pwVersion = $source->plaintext;
echo '<div class="linkFrame">'.$pwVersion.'<div>'.$pwFrame.'</p></div>';
}
}
This code made each linkframe be inside the previous linkframe making it somewhat like inception.
What can I do to make this work correctly?
Although it's not very clear to understand what you're after from your question, I believe you're looking for something like the following:
$source = $site->find('.version a');
$pwGetFrame = $site->find('.version_numb');
for ($i=0; $i < sizeof($source); $i++) {
$pwFrame = $pwGetFrame[$i]->innertext;
$getURL = $source[$i]->href;
$pwVersion = $source[$i]->plaintext;
echo '<div class="linkFrame">'.$pwVersion.'<div>'.$pwFrame.'</p></div>';
}
Are you aware that there are two open <div> tags and no open <p> tags in that snippet?
Maybe you are looking for
echo '<div class="linkFrame">'.$pwVersion.'<p>'.$pwFrame.'</p></div>';
I'm working on a WordPress site and am using a plugin called 'Simple Fields', to add data to repeatable fields. I've entered data into three fields: (audioinfo, audiofile, audiocomposer).
I would now like to create a post that displays that information in the following way:
Audio Info 1
Audio File 1
Audio Composer 1
~~~
Audio Info 2
Audio File 2
Audio Composer 2
I've been trying to figure this out with foreach. Here's the closest I can arrive at (thought I know it's invalid). Can anyone make any suggestions of how to handle this?
<?php
$audioinfo = simple_fields_values("audioinfo");
$audiofile = simple_fields_values("audiofile");
$audiocomposer = simple_fields_values("audiocomposer")
foreach ($audioinfo as $audioinfos, $audiofile as $audiofiles, $audiocomposer as $audiocomposers){
echo $audioinfos;
echo $audiofile;
echo $audiocomposer;
}
?>
(Just as a side note, in case it's important, the first three lines appear to all be valid - that is, if I do a "foreach" on $audiocomposer alone, I successfully get: Bach Handel Beethoven.)
Is there something I can do to apply "foreach" to all three at the same time?
Thanks!
Assuming all the arrays of same length, making use of a normal for loop.
<?php
$audioinfo = simple_fields_values("audioinfo");
$audiofile = simple_fields_values("audiofile");
$audiocomposer = simple_fields_values("audiocomposer");
for($i=0;$i<count($audioinfo);$i++)
{
echo $audioinfo[$i];
echo $audiofile[$i];
echo $audiocomposer[$i];
}
?>
One more pretty solution:
<?php
$audioinfo = simple_fields_values("audioinfo");
$audiofile = simple_fields_values("audiofile");
$audiocomposer = simple_fields_values("audiocomposer");
foreach ($audioinfo as $k => $val){
echo $val;
echo $audiofile[$k];
echo $audiocomposer[$k];
}
?>
Assuming there are always going to be the same number of items in all 3 arrays, you could do something like this:
$items = count($audioinfo);
for ($i = 0; $i < $items; $i++)
{
echo $audioinfo[$i];
echo $audiofile[$i];
echo $audiocomposer[$i];
}
here i gave one example how to handle the 3 array value in single foreach , hope it will much help to you
$audioinfo =array('popsong','rocksong','molodysong');
$audiofile=array('jackson','rahman','example');
$audiocomposer =array('first','second','third');
foreach($audioinfo as $key => $value)
{
echo $value."</br>";
echo $audiofile[$key]."</br>";
echo $audiocomposer[$key]."</br>";
}
I'm trying to sort out a web portfolio but can't get my head around how I can implement it, if it can!
Basically what I'm after is...
On the portfolio page, list details of the client with their name, description, TAGS (html, css, photoshop, jquery etc), COLOURS USED (black, white, blue, green etc) and services used etc.
At the moment in my client table i have:
"ID title description tags services colours client"
With this current system I have to state all the colours and services all in one row, meaning I can't separate the contents to style it with css (see below).
**I'd like to be able to show the colours used by each project as 16x16 colour blocks and the services as a <ul><li></li></ul> list.
Is this possible?
My current script can be found here:
http://davidpottrell.co.uk/paste/portfolio.txt
What I'm after (found on right of image)
http://davidpottrell.co.uk/paste/todo.png
$db = new PDO('mysql:host=localhost;dbname=testdb;charset=utf8', 'username', 'password');
$query = $db->query('SELECT * FROM client');
foreach($query as $row) {
// I assume you're storing colours as a delimited string? (red,green,yellow)
$colours = explode(',', $row['colours']);
if (count($colours)) {
foreach ($colours as $colour) {
echo '<div class="colour_block" id="'.$colour.'"></div>';
}
}
// Same thing with services
$services = explode(',', $row['services']);
if (count($services)) {
echo '<ul>';
foreach ($services as $service) {
echo '<li id="'.$service.'">'.$service.'</div>';
}
echo '</ul>';
}
}
How are you saving the services and colors at the moment? Do you write strings like service1;service2;service3 into the service column? If so, use PHPs explode() function
$var = "service1;service2;service3";
$result = explode(";", $var);
var_dump($result)
Now you can iterate through the array and replace each service with some image/list item or whatever. It should work like that, although I didn't test it:
while($row = mysql_fetch_array($result)) {
$service_array = explode(",", $row[services]);
echo "<div class='portfolio_block'><h3>Services</h3>";
if(count($services)) {
echo "<ul>";
foreach($service_array as $service) {
echo "<li>" . $service . "</li>";
}
echo "</ul>"
}
echo "</div>";
}
I would also recommend taking Jamies advice and switch from mysql_* functions to PDO. And for "styling" the list items add some class tags :)
I'm having a some trouble accessing attributes in my XML. My code is below. Initially I had two loops and this was working with no problems.
I would first get the image names and then use the second loop to get the story heading and story details. Then insert everything into the database. I want to tidy up the code and use only one loop. My image name is store in the Href attribute. ()
Sample XML layout (http://pastie.org/1850682). The XML layout is a bit messy so that was the reason for using two loops.
$xml = new SimpleXMLElement('entertainment/Showbiz.xml', null, true);
// Get story images
//$i=0;
//$image = $xml->xpath('NewsItem/NewsComponent/NewsComponent/NewsComponent/NewsComponent/NewsComponent/ContentItem');
// foreach($image as $imageNode){
// $attributeArray = $imageNode->attributes();
// if ($attributeArray != ""){
// $imageArray[$i] = $attributeArray;
// $i++;
// }
//}
// Get story header & detail
$i=0;
$story = $xml->xpath('NewsItem/NewsComponent/NewsComponent/NewsComponent');
foreach($story as $contentItem){
//$dbImage = $imageArray[$i]['Href'];
foreach($contentItem->xpath('ContentItem/DataContent/nitf/body/body.head/hedline/hl1') as $headline){
$strDetail = "";
foreach($contentItem->xpath('ContentItem/DataContent/nitf/body/body.content/p') as $detail){
$strDetail .= '<p>'.$detail.'</p>';
foreach($contentItem->xpath('NewsComponent/NewsComponent/ContentItem') as $imageNode){
$dbImage = $imageNode->attributes();
}
}
$link = getUnique($headline);
$sql = "INSERT INTO tablename (headline, detail, image, link) VALUES ('".mysql_real_escape_string($headline)."', '".mysql_real_escape_string($strDetail)."', '".mysql_real_escape_string($dbImage)."', '".$link."')";
if (mysql_query($sql, $db) or die(mysql_error())){
echo "Loaded ";
}else{
echo "Not Loaded ";
}
}
$i++;
}
I think I'm close to getting it. I tried putting a few echo statements in the fourth nested foreach loop, but nothing was out. So its not executing that loop. I've been at this for a few hours and googled as well, just can't manage to get it.
If all else fails, I'll just go back to using two loops.
Regards,
Stephen
This was pretty difficult to follow. I've simplified the structure so we can see the parts of the hierarchy we care about.
It appears that the NewsComponent that has a Duid attribute is what defines/contains one complete news piece. Of its two children, the first child NewsComponent contains the summary and text, while the second child NewsComponent contains the image.
Your initial XPath query is for 'NewsItem/NewsComponent/NewsComponent/NewsComponent', which is the first NewsComponent child (the one with the body text). You can't find the image from that point because the image isn't within that NewsComponent; you've gone one level too deep. (I was tipped off by the fact I got a PHP Notice: Undefined variable: dbImage.) Thus, drop your initial XPath query back a level, and add that extra level to your subsequent XPath queries where needed.
From this:
$story = $xml->xpath('NewsItem/NewsComponent/NewsComponent/NewsComponent');
foreach($story as $contentItem){
foreach($contentItem->xpath('ContentItem/DataContent/nitf/body/body.head/hedline/hl1') as $headline){
foreach($contentItem->xpath('ContentItem/DataContent/nitf/body/body.content/p') as $detail){
foreach($contentItem->xpath('NewsComponent/NewsComponent/ContentItem') as $imageNode){ /* ... */ }}}}
to this:
$story = $xml->xpath('NewsItem/NewsComponent/NewsComponent');
foreach($story as $contentItem){
foreach($contentItem->xpath('NewsComponent/ContentItem/DataContent/nitf/body/body.head/hedline/hl1') as $headline){
foreach($contentItem->xpath('NewsComponent/ContentItem/DataContent/nitf/body/body.content/p') as $detail){
foreach($contentItem->xpath('NewsComponent/NewsComponent/NewsComponent/ContentItem') as $imageNode){ /* ... */ }}}}
However, the image still doesn't work after that. Because you're using loops (sometimes unnecessarily), $dbImage gets reassigned to an empty string. The first ContentItem has the Href attribute, which gets assigned to $dbImage. But then it loops to the next ContentItem, which has no attributes and therefore overwrites $dbImage with an empty value. I'd recommend modifying that XPath query to find only ContentItems that have an Href attribute, like this:
->xpath('NewsComponent/NewsComponent/NewsComponent/ContentItem[#Href]')
That should do it.
Other thoughts
Refactor to clean up this code, if/where possible.
As I mentioned, sometimes you are looping and nesting when you don't need to, and it just ends up being harder to follow and potentially introducing logical bugs (like the image one). It seems that the structure of this file will always be consistent. If so, you can forgo some looping and go straight for the pieces of data you're looking for. You could do something like this:
// Get story header & detail
$stories = $xml->xpath('/NewsML/NewsItem/NewsComponent/NewsComponent');
foreach ($stories as $story) {
$headlineItem = $story->xpath('NewsComponent/ContentItem/DataContent/nitf/body/body.head/hedline/hl1');
$headline = $headlineItem[0];
$detailItems = $story->xpath('NewsComponent/ContentItem/DataContent/nitf/body/body.content/p');
$strDetail = '<p>' . implode('</p><p>', $detailItems) . '</p>';
$imageItem = $story->xpath('NewsComponent/NewsComponent/NewsComponent/ContentItem[#Href]');
$imageAtts = $imageItem[0]->attributes();
$dbImage = $imageAtts['Href'];
$link = getUnique($headline);
$sql = "INSERT INTO tablename (headline, detail, image, link) VALUES ('".mysql_real_escape_string($headline)."', '".mysql_real_escape_string($strDetail)."', '".mysql_real_escape_string($dbImage)."', '".$link."')";
if (mysql_query($sql, $db) or die(mysql_error())) {
echo "Loaded ";
} else {
echo "Not Loaded ";
}
}