Issue With SimpleXML

Hey all! I’m actually new to PHP – I just started learning recently in order to integrate my website with an API. So far it’s gone very well, however I’ve been unable to find information relating to my problem.

The goal: to use an external API to pull “Orders,” “Products” and “Packages.” After this, allow exporting a list of the logged in user’s orders (past and active), along with all important information.

What works: it pulls the information and posts it.

What doesn’t: the API uses “pagination” and I’m unable to get past that limitation. As an example, there are currently 22 orders. If I call the API it will send the first 10, and they are output flawlessly. To get more I can append “per_page” and “page=#” to the end. But I’m only able to do this manually. For example if I hardcode the address with “per_page=20” it will show all 20. But the problem is I won’t always know how many to pull and if I try to pull 23 (1 more than there are) it just errors out and doesn’t load anything at all.

To show the code I currently use (it’s been shortened considerably to show the important parts):

[php]<?php
$packages = ‘http://[email protected]/packages.xml’;
$products = ‘http://[email protected]/products.xml’;
$orders = ‘http://[email protected]/orders.xml’;

$packagelist = new SimpleXMLElement($packages,null,true);
$productlist = new SimpleXMLElement($products,null,true);
$orderslist = new SimpleXMLElement($orders,null,true);

foreach($productlist->children() as $child) {
echo $child->getName().":
";

foreach($child->children() as $subchild) {
echo “
—>”.$subchild->getName().": “.$subchild.”
";
}
}

foreach($orderslist->children() as $child) {
echo $child->getName().":
";

foreach($child->children() as $subchild) {
echo “
—>”.$subchild->getName().": “.$subchild.”
";
}
}
?>[/php]

Along with this, I’m curious as to if my iteration method is efficient. As it is, I use the following (it’s set to read in the order list and compare the site’s email address and name to the list. If it hits, it takes the purchase ID number and parses the package and product lists to pull the names of the purchases):

[php]foreach($orderslist as $child) {
$purchaser = $child->{‘buyer-name’};
$email_addy = $child->{‘buyer-email’};
$download_url = $child->{‘download-url’};
$valid = $child->{‘valid-until’};
$expires = date(“F j, Y”, strtotime("$valid"));
$product_id = $child->{‘product-id’};
$package_id = $child->{‘package-id’};
if ($email_addy == “$activeEmail” && $purchaser == “$usersName” && ($child->state == “complete” || $child->state == “free”)){
foreach($productlist as $testing){
if ($product_id == “{$testing->id}”){
echo “

{$testing->name} <a href=”$download_url">Download $expires
";
}
}[/php]

Lastly, a concern I have with the setup is that as the system gets more purchases, the list being read in will keep getting longer and longer. As it is, every time someone visits their account page it pulls in that list to get the most up-to-date information. Is there a more efficient way to handle this?

API Documentation: http://www.digitaldeliveryapp.com/developers/api/introduction

Thanks in advance! I’m very new to this, as you can see, but this has been a great learning experience so far, :).

An update!

At the suggestion of someone else I’ve now set things up to be parsed into SQL, but I don’t quite understand how it would work:

When the XML is parsed, it’s added to the XML. But the issue is that to take only “new” items means if someone did a chargeback or something it would not be updated on my end. Along with this, I’m unsure how to parse only the new items.

Furthermore, I am still having problems figuring out how the pagination would work. I contacted the creator of the API I’m using and he said to set the script to parse the xml file (appending ?per_page=50) and then iterate through the pages while counting how many items are received. If less than 50 are received, we’ve reached the end of the list and can stop. The problem is I don’t get how to set something like that up in PHP…

I’m also all for newer/better ways of handling what I’m trying to do - I’m pretty much learning as I go so I have no idea what best practices are or anything.

Thanks!

I may be completly off here but just something for you to think about.

If your looking just to get orders that have not been looked at yet (this is a guess as i for not know what the order xml outputs ) does it have forfilled / not forfilled ?

You could setup a page for just new orders if new order xml output new order = 1 or make the page a $var per_page = $number_per_page count with the code how many there are, if more than 20 say $orders = $number_of_orders / 20 $pages = $orders page = $pages but guessing that will be a long page in the end.

If your looking to make a pagination instead then I guess using a mysql database would be the right idea but isn’t the xml just a flatfile database already so why make another database unless the xml get to large.

I hope this makes sence maybe put a false entry from the order xml to see the output it has.

Thanks for the response! To help illustrate what’s sent (this is digital items), here are the product and an example order XML response:

[php]order:
—>access-allowed: true
—>affiliate-system:
—>buyer-address1:
—>buyer-address2:
—>buyer-city:
—>buyer-country:
—>buyer-email: [email protected]
—>buyer-name: Name Here
—>buyer-postcode:
—>buyer-region:
—>can-market-to-buyer: true
—>created-at: 2012-01-02T16:52:36Z
—>dispatched-at:
—>gateway:
—>id: 11111
—>settled-affiliate-fee:
—>settled-currency: USD
—>settled-gateway-fee:
—>settled-gross:
—>settled-handling:
—>settled-shipping:
—>settled-tax:
—>state: free
—>updated-at: 2012-01-02T16:52:39Z
—>valid-until: 2012-06-30T16:52:38Z
—>download-url: (LINK REMOVED)
—>discount: 0.00
—>product-id: 30[/php]

[php]product:
—>created-at: 2011-07-09T01:48:13Z
—>id: 111
—>license-fetch-url:
—>license-type: generated
—>name: DigitalItemName
—>pdf-stamping: true
—>product-type: digital
—>sales-limit:
—>self-hosted-url:
—>test-mode: false
—>updated-at: 2011-12-27T06:52:21Z
—>price: 1.11
—>instant-buy-url: PurchaseURL.com
—>add-to-cart-url: PurchaseURL.com[/php]

Those are both received by simply pinging the xml files, but both will only show the last 10 results. To get more, the text ?per_page=50&&page=X must be appended to the address.

For the Orders listing, the following can be appended as well: from=2011-01-01&to=2011-01-07 which would pull orders only from the first week of 2011. An issue with this method, though is that it does not include the time, so I’m not sure how that would benefit.

All of the orders I have are for digital items, so what I plan to display on login pages is the following:

Item Name | Download Link | Last Update | User Last Downloaded | Expiration Date

and these will be in a table format so as to keep up with all purchases they’ve made. For items that are expired, there will be a separate table that will list the expired downloads, as well as links to renew them.

hmmm quick and ruff try something like might need a loop in it to get max id

[php]
// get the order id
$id = $child->{‘id’};
// get max id
//sort by heighest number
arsort $id;
// divide the max number by 20 as we want 20 = per page
$max = $id / 20;
//result $pages = the number of pages as a var
$max = $pages;
[/php]

Sadly, the ID’s are mixed between all people who have accounts with DDA. As an example, one ID for a sale today may be 13192 and tomorrow’s could be 19,193 (if others got a lot of sales). That won’t work, =/.

An idea I have (that I’m working on trying to figure out how to do now) is to do a while loop and append the page number to the end of the URL, take in all of the information and append it to the previous run. The loop would stop when the input array returns an empty string (which means there’s nothing else to add).

Not quite sure how to do it yet but that’s my new idea, :).

Here’s what I came up with, but it keeps coming out with empty strings:

[php]$orders = ‘http://[email protected]/orders.xml?per_page=50&&page=’;

$j = 1;

$orderslist = new SimpleXMLElement($orders . $j,null,true);

do {
++$j;
$orderstoappend = new SimpleXMLElement($orders . $j,null,true);
$orderslist .= $orderstoappend;
} while ($orderstoappend);[/php]

If I remove the “Do while” loop it will pull the first 50 like it should, so something in that loop is what’s causing the problem.

My mindset in creating it was: pull first 50 into $orderslist. Then pull the next 50 into $orderstoappend. Concatenate the two and then pull in the next page to $orderstoappend and keep looping until it comes up empty. But that doesn’t seem to be working…

I just want to ask you how many items do you think you will sell a month ?

Just want to put this to you not trying to put you off but make your life easier if this os all you are doing is selling digital downloads.

There pricing plan is a little high I think you could have a ecommerce for less money a month with out the hassle of it all.

You could use xcart gold say and pay some silly amount for hosting like $3.99 or less a month and just add the products save your self a lot of time and effort and money in the long run.
plenty of ecommerce scripts out there that do everything already.

Do you get the other numbers in the $j in the do loop can you echo dump the vars
need to try and get some error messages going to give yourself feedback

[php]

$orderslist .= $orderstoappend;
var_dump($orderslist);

} while ($orderstoappend < 200);
[/php]

It’s hard to really tell - it’s going to be a pretty large project over time for sure. I was planning to go with another ecommerce solution (I’d love to do self-hosting) but being able to properly “stamp” the documents was an important factor (DDA appends identifiable information to the footer of documents as you download).

I did the var dump and it came up with:

[php]string ’

’ (length=16)[/php]

Alright, I got my issue resolved (I’m unsure how “efficient” it is but it works). In case anyone else is looking to do something similar or wants to have a go at making it better, here’s the method I went with:

[php]<?php
$j = 1;

do {
$orders = ‘http://[email protected]/orders.xml?per_page=50&&page=’;
$orderslist = new SimpleXMLElement($orders . $j,null,true);
$j++;

foreach ($orderslist as $child)
{
//Do whatever you want here for each iteration
}
} while ($orderslist);
?>[/php]

Pretty much what it does is pull in the first page of the list -> parse it -> do whatever (print to the screen, add to SQL, whatever) -> pull in page 2 and keep cycling until it’s out of pages. When it gets to an empty page, $orderslist comes up empty and causes the loop to end.

Nice to see you got it sorted out but will say that the stamp will mean nothing really if some one wants to give out the work then they will just edit the file and remove the stamp.

you would be better off making your own code and having an inviable stamp say the same color as the backgound.
Then you know is in the file and you could then see who it was that passed it around and they would not know.
If people can see the stamp they will get rid of it some how if they wanted to just a thought, its like zend and ioncube people wanted to encrypt there work people got around it and unencrypted it.
It does not matter what you have people will want to copy nd share it for free if its good.

Sponsor our Newsletter | Privacy Policy | Terms of Service