Error Using $this when not in object context - php

First post here so apologies in advance if this is an incorrect format. I am working with the Instagram API to pull images. The Instagram API only returns 1 page of images at a time, but offers pagination and next_url to grab the next page of images. When I use the function fetchInstagramAPI below, to grab only the first page, the php code works fine.
When I attempt to use the loopPages function together with the fetchInstagramAPI function, to try and grab all pages at once, I receive the error "Using $this when not in object context". Any idea? Thank you for the help in advance.
Function fetchInstagramAPI gets our data
<?php
function fetchInstagramAPI($url){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 20);
$contents = curl_exec($ch);
curl_close($ch);
return json_decode($contents);
}
Function loopPages uses pagination and next_url to grab all pages of images
function loopPages($url){
$gotAllResults = false;
$results = array();
while(!$gotAllResults) {
$result = $this->fetchInstagramAPI($url);
$results[] = $result;
if (!property_exists($result->pagination, 'next_url')) {
$gotAllResults = true;
} else {
$url = $result->pagination->next_url;
}
}
return $results;
}
This pulls, parses, then displays the images in a browser
$all_url = 'https://api.instagram.com/v1/users/{$userid}/media/recent/?client_id={$clientid}';
$media = loopPages($all_url);
foreach ($media->data as $post): ?>
<!-- Renders images. #Options (thumbnail, low_resoulution, standard_resolution) -->
<a class="group" rel="group1" href="<?= $post->images->standard_resolution->url ?>"><img src="<?= $post->images->thumbnail->url ?>"></a>
<?php endforeach ?>

In PHP and many object oriented languages $this is a reference to the current object (or the calling object). Because your code don't seem to be in any class $this doesn't exists. Check this link for PHP classes and objects.
Since you have just defined your functions in the file you can try calling the function with $result = fetchInstagramAPI($url); (without $this).
edit:
For foreach check if $media->data is in fact an array and try another syntax which i think is easier to read.
edit2:
Since you now know how your $media looks like you can wrap around another foreach loop that will iterate through the pages:
foreach ($media as $page){
foreach ($page->data as $post) {
echo '<!-- Renders images. #Options (thumbnail, low_resoulution, standard_resolution) -->';
echo '<a class="group" rel="group1" href="' . $post->images->standard_resolution->url . '"><img src="' . $post->images->thumbnail->url . '"></a>';
}
}

Related

How can you stream results from an API in PHP

is there a way in PHP, perhaps with an external library, to stream results from an API that responds with JSON data?
For instance I have the following code to get the data:
$resultsAPI = "https://www.example.com/api/results.json?
app_id=$app_id&token=$token&page=1&limit=10";
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $resultsAPI);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Accept: application/json;api_version=2' ));
$resp = curl_exec($curl);
curl_close($curl);
$results = json_decode($resp, true)['results'];
foreach ($results as $key=>$resultImage) {
$resultImage= "$resultImage[images]?app_id=$app_id&token=$token";
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $resultImage);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$resp = curl_exec($curl);
curl_close($curl);
$image = json_decode($resp, true);
$results[$key]['image1'] = $image['image1'];
}
echo '<div class="card"><ul>';
foreach ($results as $result) {
echo '<li>';
echo '<span><p>'.$result['title'].'</p></span>';
echo '<span><p>'.$result['description'].'</p></span>';
echo '<span><img src="'.$result['image1'].'"></span>';
echo '</li>';
}
echo '</ul></div>';
It can take some time to load all data because it is going to loop over some large files. Is it possible to start streaming the results when it has the first data?
In the image below it shows what I am trying to explain. The data is being loaded in to the skeleton one by one:
Any thoughts on this would be very helpful and or if it is possible at all.
I think you're run into the wrong direction.
HTML begin to render after load all the html. So fetch the html with stream is not work for you.
In the demo, it just load a simple html page. Then load the other parts of the page with something like ajax. Each time a part loaded then render it.
Why not merge the the foreach loops? I haven't tested this but items should be echoed very iteration.
echo '<div class="card"><ul>';
foreach ($results as $key=>$result) {
$resultImage= "$result[images]?app_id=$app_id&token=$token";
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $resultImage);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$resp = curl_exec($curl);
curl_close($curl);
$image = json_decode($resp, true);
$results[$key]['image1'] = $image['image1'];
echo '<li>';
echo '<span><p>'.$result['title'].'</p></span>';
echo '<span><p>'.$result['description'].'</p></span>';
if(isset($image['image1'])){
echo '<span><img src="'.$result['image1'].'"></span>';
}
echo '</li>';
}
echo '</ul></div>';
I hope that helps
As Kris Roofe said you may need ajax or axios call to output your data with some effects and animations exactly like the image that you attached in your question, your application need to be rendered first with all of it's HTML tags and assets like CSS and Javascript files then you can output some data and show it with animations by using ajax or axios and ofcurse you have more control over your data streaming in this case by using ajax or axios in client-side but you can also do it in your server-side but typically I prefer to do these things in client-side.
by the way if you insist to doing this in this way you can use flush() and ob_flush() to immediately output your data before the while loop ends.
Someone has already mentioned this in php official documentation link. You can check and read full documentation about output buffering and these methods.
You should merge your two foreach loops together and then add these two methods add the end of your loop so it will make it to output your data immediately after each loop iterate.
foreach($results as $key=>$resultImage){
//fetch images data such as title, description, and image itself in this loop
// and aslo echo your html tags in here.
// echo '<li>';
// echo '<span><p>'.$result['title'].'</p></span>';
// echo '<span><p>'.$result['description'].'</p></span>';
// echo '<span><img src="'.$result['image1'].'"></span>';
// echo '</li>';
}
I wrote some comments in your for loop to show you that you should merge your loops together, because you are trying to initialize $results variable in your first loop, and then after finishing that loop you are iterating in $results variable to show output data. so you can't output data immediately with two loops in here because your second loop depends on first one and it will not start iterating until the first one finishes. check this little code that I wrote to demonstrate the usage of these two methods:
$curl = curl_init();
for($i=0;$i<5;$i++){
curl_setopt($curl, CURLOPT_URL, 'example.com');
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$output = curl_exec($curl);
$output = json_decode($output);
foreach($output as $key=>$value){
echo 'key: '.$key;
echo '$value: '.$value;
ob_flush();
flush();
}
}
I would highly recommend you to read about output buffering to implement it correctly in your projects.
I hope this could help you.
HTML starts rendering when some of it arrives. It does not have to be complete source. In PHP you can "send what you already echoed" via ob_flush() and flush() calls. This way it will immediately display in the browser. This can be paired with JSON stream parsing using for example halaxa/json-machine, so the result can look something like this:
<?php
echo '<div class="card"><ul>';
foreach (JsonMachine::fromStream($jsonStreamResource) as $result) {
echo '<li>';
echo '<span><p>'.$result['title'].'</p></span>';
echo '<span><p>'.$result['description'].'</p></span>';
echo '<span><img src="'.$result['image1'].'"></span>';
echo '</li>';
ob_flush();
flush();
}
echo '</ul></div>';
Fetch limited records while rendering html first load. Once page load fully then call a ajax function which will fetch next page rows. Definitely it is the tested method.
<script>
var items = [{item1}, {item2}];
$(document).ready(function() {
$.each(items, function(index, item) {
$('.card').append('<li>'+ '<span><p>'+item['title']+'</p></span>' +
'</li>');
});
});`enter code here`
</script>
OR
You may call ajax function for first page records after html rendered fully.
How do I load a JSON object from a file with ajax?

Integrating Wordpress with Opencart

I have an opencart shop and wordpress installation running on the same server and I would like to grab a few articles and show them on the product page in opencart.
Here is the code I inserted on my product page template, however I'm having problems:
<?php
require('blog/wp-blog-header.php');
?>
<?php
$posts = get_posts('numberposts=3&order=ASC&orderby=post_title');
foreach ($posts as $post) : setup_postdata( $post ); ?>
<?php the_date(); echo "<br />"; ?>
<?php the_title(); ?>
<?php the_excerpt(); ?>
<?php
endforeach;
?>
I'm gettings this error
Notice: Constant DB_PASSWORD already defined in /home/admin/web/domain.com/public_html/blog/wp-config.php on line 29
ERROR ESTABLISHING A DATABASE CONNECTION
I know DB_PASSWORD is also used by the opencart config, is this the problem? And more importantly is there a solution to this problem?
i think there is a better way to fetch posts from WordPress.
use wp-api to get your posts in json format. then you can process on it as you want.
here is a simple function in php (i have used it as a helper in CodeIgniter.
function blog_posts($site_url = 'http://yoursite.com/', $cat_id = 1, $count = 5, $thumbnails = true)
{
$url = $site_url . 'wp-json/wp/v2/posts?';
$url_data = [
'categories' => $cat_id,
'per_page' => $count,
];
$url_data = http_build_query($url_data, 1, '&');
if ($thumbnails) {
$url_data = $url_data . '&_embed';
}
$final_url = $url . $url_data;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $final_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($ch);
return $result;
}
An even simpler way could be to use RSS.
Most blogs should produce an RSS feed containing the content you need - this will be quicker and easier to get than an API.
You can then see this answer about how the parse the RSS XML from PHP:
Best way to parse RSS/Atom feeds with PHP

Mulitple Instagram feeds on one page

I have successfully put an Instagram feed for a specific user on my website, but having very little experience with PHP I cannot figure out how to simply repeat the process. I'm looking to showcase two different users, side by side in one div.
<?php
// http://jelled.com/instagram/lookup-user-id/
$userid = "userid";
// http://instagram.com/developer/
$clientid = "clientid";
// http://jelled.com/instagram/access-token/
$accessToken = "token";
// number of photos to return
$count = "4";
// Gets our data
function fetchData($url){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 20);
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
// Pulls and parses data.
$result = fetchData("https://api.instagram.com/v1/users/{$userid}/media/recent/?access_token={$accessToken}&count={$count}");
$result = json_decode($result);
// cycles through the json tree and uses the low res url in the img tag
echo "<ul>";
foreach ($result->data as $photo) {
$img = $photo->images->{$display_size="thumbnail"};
echo "<li><a href='{$photo->link}'><img src='{$img->url}' /></a></li>";
}
echo "</ul>";
?>
If I just paste the code in again, the whole page stops working. I'm guessing this is something simple, but I don't know exactly what I'm looking for! Should this code be in a separate file that is linked into my website- rather than throwing some PHP inside an HTML Bootstrap site?
Thanks in advance.
EDIT
I was able to get this working by using the answer below. I wanted each account to have it's own div, and the only way I know how to do that is in the html file- which would mean I still need to link to two different files. I created one file with the correct code, and another with this:
<?php
// Set User ID here for different profile
//$userid = "idHere";
$userid = "296517730";
$result = fetchData("https://api.instagram.com/v1/users/{$userid}/media/recent/?client_id={$clientid}&count={$count}");
$result = json_decode($result);
// cycles through the json tree and uses the low res url in the img tag
echo "<ul>";
foreach ($result->data as $photo) {
$img = $photo->images->{$display_size="thumbnail"};
echo "<li><a href='{$photo->link}'><img src='{$img->url}' /></a></li>";
}
echo "</ul>";
?>
It was working just fine on my domain, but when I moved it to my client's domain I'm getting this error: Warning: Invalid argument supplied for foreach() in /home/savenors/savenorsmarket.com/bostoninsta.php on line 53
What happened? I'm guessing whatever I did to get this to work wasn't really working.. but it looked fine to me. Any ideas? This is the website: http://www.savenorsmarket.com
Here's code that is working on my machine pulling in twice. It pulls the same user pictures twice, but to fix this just reset the user id variable before making a second call to fetchData();
<?php
$userid = "idHere";
// http://instagram.com/developer/
$clientid = "IDhere";
// number of photos to return
$count = "4";
// Gets our data
function fetchData($url){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 20);
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
// Pulls and parses data.
$result = fetchData("https://api.instagram.com/v1/users/{$userid}/media/recent/?client_id={$clientid}&count={$count}");
$result = json_decode($result);
// cycles through the json tree and uses the low res url in the img tag
echo "<ul>";
foreach ($result->data as $photo) {
$img = $photo->images->{$display_size="thumbnail"};
echo "<li><a href='{$photo->link}'><img src='{$img->url}' /></a></li>";
}
echo "</ul>";
// Set User ID here for different profile
//$userid = "idHere";
$result = fetchData("https://api.instagram.com/v1/users/{$userid}/media/recent/?client_id={$clientid}&count={$count}");
$result = json_decode($result);
// cycles through the json tree and uses the low res url in the img tag
echo "<ul>";
foreach ($result->data as $photo) {
$img = $photo->images->{$display_size="thumbnail"};
echo "<li><a href='{$photo->link}'><img src='{$img->url}' /></a></li>";
}
echo "</ul>";
?>
Also note that I'm using the client_id over the access_token. It should work either way though.

Limit Instagram Feed in Php-Fetch

i am using the code below, to show some photos of my instagram-account on my website. it just fetches all the images of my account in the div. Is there a way to limit the fetched data to 10 Images or so ?
Cant figure out how to do that..
thanks for your help!
<div id="instagramfeed">
<?php
// Supply a user id and an access token
$userid = "123xy";
$accessToken = "123xy ";
// Gets our data
function fetchData($url){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 20);
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
// Pulls and parses data.
$result = fetchData("https://api.instagram.com/v1/users/{$userid}/media/recent/?access_token={$accessToken}");
$result = json_decode($result);
?>
<?php foreach ($result->data as $post): ?>
<!-- Renders images. #Options (thumbnail,low_resoulution, high_resolution) -->
<a class="group" rel="group1" href="<?= $post->images->standard_resolution->url ?>"><img src="<?= $post->images->thumbnail->url ?>"></a>
<?php endforeach ?> <br><br><br><br>
</div>
You could use the count parameter.
https://api.instagram.com/v1/users/{$userid}/media/recent/?access_token={$accessToken}&count=10
It was a problem in Instagram Developer Console. max_id and min_id doesn't work there.
For anyone interested - i found a solution for this problem:
it doesnt work with: {$accessToken}&count=10
But it works with:
?access_token=123456789101112131415123123111&count=10

Get artist image from last.fm xml (api artist.getinfo)

I wanted to ask you help I have an xml source (http://livefmhits.6te.net/nowplay.xml) it gives me the source of the song and I wanted to remove the cover through the lastfm (artist.getinfo) in echo I tried as follows:
<?php
$xml = simplexml_load_file('http://livefmhits.6te.net/nowplay.xml');
$artist = urlencode($xml->TRACK["ARTIST"]);
$url = 'http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&artist='.$artist.&api_key=b25b959554ed76058ac220b7b2e0a026;
$xml2 = #simplexml_load_file($url);
if ($xml2 === false)
{
echo("Url failed"); // do whatever you want to do
}
else
{
if($xml2->track->album->image[3])
{
echo '<img src="';
echo((string) $xml2->track->album->image[3]);
echo '">';
}
else
{
echo "<img src='http://3.bp.blogspot.com/-SEsYAbASI68/VZ7xNuKy-GI/AAAAAAAAA3M/IWcGRDoXXms/s1600/capaindisponivel.png'"; // do whatever you want to do
}
}
I'm not able to extract the source must be wrong echo, I like to remove the image that says "mega". I present to you the complete link
http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&lang=ru&artist=COLDPLAY&api_key=ae9dc375e16f12528b329b25a3cca3ee and yet I was to do a post yours but I could not (Get large artist image from last.fm xml (api artist.getinfo))
I came to ask your help in this work from the outset thanks for availability
Here is how I'm doing it in json. It's pretty much the same in XML.
First, we define the API KEY:
define('YOUR_API_KEY', 'b25b959554ed76058ac220b7b2e0a026');
It's better to separate it from the code, it makes things easier if you need to reuse it somewhere else in your code. (for eg. in another function)
Then, we create the 2 functions we need to make the magic happen.
1) To query Lastfm's API and get its content, we will use CURL:
function _curl($url)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);
if(strtolower(parse_url($url, PHP_URL_SCHEME)) == 'https')
{
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,1);
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,1);
}
curl_setopt($ch, CURLOPT_URL, $url);
$data = curl_exec($ch);
curl_close($ch);
return $data;
}
2) Lastfm offers many options. Personally, I find it's easier to separate main queries into functions. But as you simply target images, here is the function I'd use:
function lfm_img($artist)
{
$url = "http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&artist=$artist&api_key=".YOUR_API_KEY."&format=json";
$json = _cul($url);
$data = str_ireplace("#text", "text", $json);
$list = json_decode($data);
//If an error occurs...
if($list->error)
return 'ERROR.'. $list->error;
//That's where we get the photo. We try to get the biggest size first, if not we try smaller sizes. Returns '0' if nothing is found.
if($list->artist->image[4])
$img = $list->artist->image[4]->text;
else if($list->artist->image[3])
$img = $list->artist->image[3];
else if($list->artist->image[2])
$img = $list->artist->image[2];
else if($list->artist->image[1])
$img = $list->artist->image[1];
else if($list->artist->image[0])
$img = $list->artist->image[0];
else
$img = 0;
return $img;
}
And finally, use them:
$artist_query = 'Nirvana';
$artist_image = lfm_img($artist);
//display image
echo '<img src="'. $artist_image .'" alt="'. $artist_query .'" />';
I think it's self explanatory here. ;)
Hope it helped!

Categories