I am working on a project to display select Instagram photos in an album by hashtag, since the Instagram API limits 35 images per API call I figured out I either had to use AJAX (which I am very poor at) or a mixture of PHP and AJAX. I decided on the latter because I didn't want my access token and user ID made available in the code on my gallery.
<?PHP
function jsongram($next=null){
$userid = "xxx";
$accessToken = "xxx";
$url = ("https://api.instagram.com/v1/users/{$userid}/media/recent/?access_token={$accessToken}");
if($url !== null) {
$url .= '&max_id=' . $next;
}
//Also Perhaps you should cache the results as the instagram API is slow
$cache = './'.sha1($url).'.json';
//unlink($cache); // Clear the cache file if needed
if(file_exists($cache) && filemtime($cache) > time() - 60*60){
// If a cache file exists, and it is newer than 1 hour, use it
$jsonData = json_decode(file_get_contents($cache));
}else{
$jsonData = json_decode((file_get_contents($url)));
file_put_contents($cache,json_encode($jsonData));
}
?>
<html>
<head>
</head>
<body>
<?php
$data_array = array();
foreach ($jsonData->data as $data){
if (stripos($data->caption->text,'egypt') === false) {
}
else{
$data_array[] = $data;
$data = (str_split($data->caption->text));
$data = (array_filter($data));
}
}
foreach ($data_array as $data):{
$igimglow = $data->images->low_resolution->url;
$igimgstd = $data->images->standard_resolution->url;
$igimgthumb = $data->images->thumbnail->url;
$igcaption = str_replace('#', '', (preg_replace('/(?:#[\w-]+\s*)+$/', '', $data->caption->text)));
$igtime = date("F j, Y", $data->caption->created_time);
$iglikes = $data->likes->count;
$igcomments = $data->comments->count;
$iglong = $data->location->longitude;
$iglat = $data->location->latitude ;
$igusername = $data->user->username;
$igfullname = $data->user->full_name;
$iglink = $data->link;
$igfilter = $data->filter;
$igtags = implode(',',$data->tags);
?>
<img src="<?php echo ($igimglow);}?>">
<?php endforeach ?>
<?php
if(isset($jsonData->pagination->next_max_id)) {
$result .= '<div>Next</div>';
}
return $result;
}
?>
<div id="container">
<?=jsongram(#$_GET['next']);?>
<div id="result"></div>
</div>
</body>
</html>
Here's a live example of the above code:
http://johnricedesign.com/examples/pn.php
As shown above on the 2nd page photos tagged with "egypt" are displayed. I would like to replace the "Next" link to automatically load on the same page with a "Load More" button - to the best of my knowledge using AJAX is the only way of doing so. However I do not know how to do so, or even where to start. The second obvious problem I have is that even though I am removing the photos that don't contain the caption of "egypt" I am still getting a lot of blank spaces, I presume that will be rather simple to fix once AJAX is being used.
I have been pulling my hair out for the last 5 days trying to do this. You help, advice, wisdom, are much appreciated in advance.
I changed the the api to work with client_id rather than access_token. You can change it back it will have no effect.
Demo: https://tjay.co/l/instagrampagination
ajax.php
<?php
function jsongram($next = null)
{
$userid = "xxx";
$accessToken = "xxx";
$url = ("https://api.instagram.com/v1/users/{$userid}/media/recent/?client_id={$accessToken}");
if ( !empty($next) ) {
$url.= '&max_id=' . $next;
}
// Also Perhaps you should cache the results as the instagram API is slow
$cache = './' . sha1($url) . '.json';
// unlink($cache); // Clear the cache file if needed
// If a cache file exists, and it is newer than 1 hour, use it
if (file_exists($cache) && filemtime($cache) > time() - 60 * 60) {
$jsonData = json_decode(file_get_contents($cache));
} else {
$jsonData = json_decode(file_get_contents($url));
file_put_contents($cache, json_encode($jsonData));
}
return $jsonData;
}
function instaFormat($jsonData)
{
$data_array = array();
$response = array();
foreach($jsonData->data as $data) {
if ( !empty($data->caption->text) && stripos($data->caption->text, 'egypt') !== false ) {
$data_array[] = $data;
$data = (str_split($data->caption->text));
$data = (array_filter($data));
}
}
$response['next'] = $jsonData->pagination->next_max_id;
foreach($data_array as $data) {
$igimglow = $data->images->low_resolution->url;
// $igimgstd = $data->images->standard_resolution->url;
// $igimgthumb = $data->images->thumbnail->url;
// $igcaption = str_replace('#', '', (preg_replace('/(?:#[\w-]+\s*)+$/', '', $data->caption->text)));
// $igtime = date("F j, Y", $data->caption->created_time);
// $iglikes = $data->likes->count;
// $igcomments = $data->comments->count;
// $iglong = $data->location->longitude;
// $iglat = $data->location->latitude;
// $igusername = $data->user->username;
// $igfullname = $data->user->full_name;
// $iglink = $data->link;
// $igfilter = $data->filter;
// $igtags = implode(',', $data->tags);
$response['data'][] = '<img src="'.$igimglow.'">';
}
return $response;
}
if ( isset($_POST['next']) ) {
echo json_encode(instaFormat(jsongram($_POST['next'])));
die();
}
index.php
<!doctype html>
<html>
<body>
<div data-pictures></div>
<div><button type="button" data-get-next>Next</button></div>
<script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
<script>
jQuery(function($) {
$(document).on('get-feed', function(e, next_id) {
var data = {
next: next_id
};
$.post('ajax.php', data, function(response) {
var container = $('[data-pictures]');
response = $.parseJSON(response);
container.html('');
$('[data-get-next]').attr('data-get-next', response.next);
$.each(response.data, function(i, val) {
$(val).appendTo(container);
});
});
});
$('[data-get-next]').click(function() {
var next_id = $(this).attr('data-get-next');
$.event.trigger('get-feed', next_id);
});
$.event.trigger('get-feed', 0);
});
</script>
</body>
</html>
Related
I developed my own PHP classes and used composer to manage all the dependencies between them. But whenever I include "vendor/autoload" on top of any PHP script, the page does not POST. None of the post data from any of the input elements is recognized or received by the script. The following script 'call.php' posts onto itself and nothing happens.
try
{
//------Page url
$url = 'call';
//------Set page timeout parameters
session_start();
if(isset($_SESSION['timeout']) && ((time() - (int)$_SESSION['timeout']) > 600)):
session_destroy();
header('Location: '.$url);
die();
endif;
$_SESSION['timeout'] = time();
//------Add required methods and classes
require dirname(__FILE__).'/../includes/vendor/autoload.php';
//------Get encrypted user id & device id
if(isset($_GET['id']) || isset($_GET['device'])):
//-----Decrypt user id and device id
$decrypt = new decryption();
$user_id = $decrypt->mc_decrypt($_GET['id']);
$device_id = $decrypt->mc_decrypt($_GET['device']);
//-----Validate decrypted data
$check = new validation();
$c_id = $check->check_number($user_id ,'n');
$c_device = $check->check_number($device_id ,'y');
if($c_id==1 && $c_device==1)
{
//-----Create a service object
$service = new service($user_id);
$status = $service->get_user_status();
//-----Check if the user has a valid status
if($status != 100)
{
header('Location: logout?logout&message='.$status.'#re101');
die();
}
else
{
$user_name = $decrypt->mc_decrypt($service->get_user_name());
//-----Check for previous service requests
$details = $service->get_service_call();
if($details)
{
$completed = false;
if($details['b'] == 'pending' )
{
$message = '<h2>Your request has been placed...</h2>';
$image = '<h2><img src="images/call_in.png alt="" height="100px" width="300px"/></h2>';
}
else if($details['b'] == 'processing' )
{
$message = '<h2>Your request is under process...</h2>';
$image = '<h2><img src="images/call_up.png" alt="" height="100px" width="300px"/></h2>';
}
else
{
$completed = true;
$service_id = $details['a'];
$message = '<h2>Your request has been fulfilled...</h2>';
$image = '<h2><img src="images/call_out.png" alt="" height="100px" width="300px"/></h2>';
}
$dated = $details['c'];
}
else
{
//-----Create a new service request
if($service->create_service_call($device_id))
echo "Service created";
$dated = date('d-m-Y', time());
}
}
}
endif;
//-----Once fulfilled, close the service by accepting user rating and feedback
if(isset($_POST['submit'])&&!empty($_POST['submit'])):
$id = !empty($_POST['service'])?$_POST['service']:'';
$rating = !empty($_POST['rate'])?$_POST['rate']:'';
$feedback = !empty($_POST['feed'])?$_POST['feed']:'';
$check = new validation();
$c_text = $check->check_textarea($feedback, 'y');
$feed = new service(0);
if(($rating == 10 || $rating == 5 || $rating == 1) && $c_text == 1)
{
if($feedback == '')
$feedback = 'nil';
if ($feed->give_service_feedback($id, $rating, $feedback))
$give = 'Thank you for your feedback!';
else
$give = 'Sorry, could not post your feedback.';
}
else
$give = 'Sorry, there was an error.';
endif;
}
catch(Exception $e)
{
$log = new misc();
$log->handle_ex($url, $_SESSION['account'], $e->getMessage(), $e->getFile(), $e->getLine());
header('Location: '.SITE.'404.shtml');
die();
}
Post via ajax
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<!-- button to send form post -->
<button id="sendforms">Submit forms</button>
<div id="result"><!-- result of post page goes here --></div>
<script type="text/javascript">
$(document).ready(function () {
$("#sendforms").click(function() {
var combinedFormData = $("#form1").serialize();
$.post(
"test.php",
combinedFormData
).done(function(data) {
//alert("Successfully submitted!");
$("#result").html(data);
}).fail(function () {
//alert("Error submitting forms!");
})
});
});
</script>
so all the code post is made in the test.php file you can check if is set with php and also return it your form must have a id="form1" and don't need
action="page.php" method="post" please remove this from your form
also the button must be
<button id="sendforms">Submit forms</button>
If you did't understand I can make a implementation for your you if send all code the form and the php part
I know I should be more specific about the problem but I don't know what it is but once I have an answer I fix the post.
Here is the problem simple ajax script but somehow it isn't working. I can't see any error on the code =/
jQuery part:
$(document).ready(function()
{
var addFavPhp = '../functions/addfav.php';
var orange = 'orange';
var favLinkError = false;
var favNameError = false;
$('#addFavButton').click(function()
{
var favLink = $('.favLinkInput').val();
var favName = $('.favNameInput').val();
var fileName = $('.file').val();
if(favLink=="")
{
$('.favLinkInput').css('border-color',orange);
favLinkError = true;
}
if(favName=="")
{
$('.favNameInput').css('border-color',orange);
favNameError = true;
}
if((favLinkError==false) && (favNameError==false))
{
$.post(addFavPhp,{favLink:favLink,favName:favName,fileName:fileName},function(addFav)
{
$('.favLinkInput,.favNameInput').val('').css('border-color','');
$('.file option[value=""]').attr("selected", "selected");
location.reload();
});
}
});
});
and php part:
<?php session_start();
include('../functions/connect.php');
if(!empty($_SESSION['username']))
{
$username = $_SESSION['username'];
}else
if(!empty($_COOKIE['PHPCOOKID']))
{
$cookie = htmlspecialchars(trim($_COOKIE['PHPCOOKID']));
$explode = explode('-', $cookie);
$username = $explode['0'];
}
$favLink = htmlspecialchars(trim($_POST['favLink']));
$favName = htmlspecialchars(trim($_POST['favName']));
$fileName = htmlspecialchars(trim($_POST['fileName']));
$d = array($username,$favLink,$favName,$fileName);
$req = $DB->prepare('INSERT INTO favs (username,favLink,favName,favFile) VALUE (? , ? , ? , ?)');
$req->execute($d);
?>
What I figure out is that it stop working around $.post but I can't figure out why. And it works find on local server.
Thanks for any help.
looks like the line var addFavPhp = '../functions/addfav.php'; is wrong. you have to use http urls when doing ajax. somthing like /path/to/addfav.php
I have this php code to return many arrays to javascript through ajax.
<?php
ini_set('display_errors', 1);
error_reporting(E_ALL);
function get_events_data() {
// load SimpleXML
$nodes = new SimpleXMLElement('my_events.xml', null, true);
$event_id = array();
$channel_id = array();
$channel_name = array();
$channel_onclick = array();
$event_site = array();
$event_url = array();
$start_date = array();
$start_time = array();
$end_date = array();
$end_time = array();
$event_notes = array();
$n = 0;
foreach($nodes as $node)
{
$event_id[$n] = $node['id'];
$channel_id[$n] = $node->channel['id'];
$channel_name[$n] = $node->channel->name;
$channel_onclick[$n] = $node->channel->onclick;
$event_site[$n] = $node->event_site->name;
$event_url[$n] = $node->event_site->url;
$start_date[$n] = $node->start_date;
$start_time[$n] = $node->start_time;
$end_date[$n] = $node->end_date;
$end_time[$n] = $node->end_time;
$event_notes[$n] = $node->notes;
$n++;
}
$return['event_id'] = $event_id;
$return['channel_id'] = $channel_id;
$return['channel_name'] = $channel_name;
$return['channel_onclick'] = $channel_onclick;
$return['event_site'] = $event_site;
$return['event_url'] = $event_url;
$return['start_date'] = $start_date;
$return['start_time'] = $start_time;
$return['end_date'] = $end_date;
$return['end_time'] = $end_time;
$return['event_notes'] = $event_notes;
echo json_encode($return);
}
echo get_events_data();
?>
On the javascript side I have this code to access the arrays.
$.ajax({
url: "get_events_data.php",
type: "POST",
dataType : 'json',
data: { },
cache: false,
async: false,
success: function (rdata) {
var alert_data = 'event_id '+rdata.event_id[0]+'<br/>'+
'channel_id '+rdata.channel_id[0]+'<br/>'+
'channel_name '+rdata.channel_name[0]+'<br/>'+
'channel_onclick '+rdata.channel_onclick[0]+'<br/>'+
'event_site '+rdata.event_site[0]+'<br/>'+
'event_url '+rdata.event_url[0]+'<br/>'+
'start_date '+rdata.start_date[0]+'<br/>'+
'start_time '+rdata.start_time[0]+'<br/>'+
'end_date '+rdata.end_date[0]+'<br/>'+
'end_time '+rdata.end_time[0]+'<br/>'+
'event_notes '+rdata.event_notes[0]+'<br/>';
alert (alert_data);
},
error: function (request, status, error) {
alert ("status "+status+" error "+error+"responseText "+request.responseText);
},
});
When I print out the first element of each array on the javascript side, it shows as "object" doesn't show the value in that array. What is the right way of accessing the array data on the javascript side?
In JavaScript, an associative array is pretty much an object. Your script is working correctly. Do a console.log() with your data and explore how it prints out in the console, then use that to access the data. You could also post up the JSON data in question and probably get more detailed answers.
The answer to this question showed me how to do this. Reading a json encoded array in javascript
The json encoded rdata object returned from the PHP function could be read like this rdata.event_id[i]["0"]. Here is sample code for the objects within rdata.
var event = rdata.event_id[i]["0"]+' '+
rdata.channel_name[i]["0"]+' '+
rdata.channel_onclick[i]["0"]+' '+
rdata.event_site[i]["0"]+' '+
rdata.event_url[i]["0"]+' '+
rdata.event_onclick[i]["0"]+' '+
rdata.start_date[i]["0"]+' '+
rdata.start_time[i]["0"]+' '+
rdata.end_date[i]["0"]+' '+
rdata.end_time[i]["0"]+' '+
rdata.event_notes[i]["0"]+' ';
$('#event_list').append(event);
Use this instead of your 'similar' code:
foreach($nodes as $node)
{
$event_id[] = $node['id'];
$channel_id[] = $node->channel['id'];
$channel_name[] = $node->channel->name;
$channel_onclick[] = $node->channel->onclick;
$event_site[] = $node->event_site->name;
$event_url[] = $node->event_site->url;
$start_date[] = $node->start_date;
$start_time[] = $node->start_time;
$end_date[] = $node->end_date;
$end_time[] = $node->end_time;
$event_notes[] = $node->notes;
}
you need to either echo
echo json_encode($return);
or
echo get_events_data();
better:
echo json_encode($return);
} // end of function
then next line
get_events_data();
I have a javascript function which makes an ajax request to php controller method which returns a JSON encoded array.
function initGallery(offset) {
if(offset === undefined)
{
var request_url = url+'avatar/gallery';
} else {
var request_url = url+'avatar/gallery/'+offset;
}
$('#avatar_gallery').html('')
$.get(request_url,function(data) {
var dat = jQuery.parseJSON(data);
//Build gallery
$('#avatar_gallery').html('<div class="gallery_box"></div>');
$('.gallery_box').append('<div class="gallery_header">Your Avatar Gallery</div>');
$('.gallery_box').append('<div class="gallery_container"></div>');
$.each(dat.avatars,function(index,item)
{
$('.gallery_container').append(
'<div class="gallery_item">'+
'<img src="'+item.avatar_src+'" id="'+item.avatar_id+'" onclick="avatar.view_avatar(this.id)"/>'+
'</div>'
);
});
$('.gallery_box').append('<div class="gallery_footer"></div>');
$('.gallery_footer').html('<div class="gallery_pagination"><div>');
});
}
And this is my controller method
function gallery($offset= 0)
{
$limit = 12;
$user_id = $this->session->userdata('user_id');
$data = $this->avatar_model->user_avatars($user_id,$limit,$offset);
$avatars = array();
$count = $this->avatar_model->count_user_avatars($user_id);
$pages = ceil($count/$limit);
foreach($data as $key => $avatar)
{
$dat['avatar_id'] = $avatar->avatar_id;
$dat['avatar_src'] = $avatar->avatar_small;
$dat['create_date'] = time("d-m-Y",$avatar->create_date);
$avatars[] = $dat;
}
$server_response['avatar_count'] = $count;
$server_response['avatars'] = $avatars;
echo json_encode($server_response);
}
I dont really have an idea on how to paginate the data returned from the reques.
Please point me in the right direction
It's easy. Add a class to your pagination link (you can use full_tag_open and full_tag_close config variable: <p class="pagination> and </p>).
After that you can redefine the .pagination a click event (I'm using JQuery):
function () {
$(".pagination a").click(function(event){
event.preventDefault();
YourJSFunction($(this).attr("href"));
});
}
I hope this helps you.
Just wondering if someone can assist me with the following issue. I have come across the following code which pulls in latest Twitter posts and displays them on a site:
//Handle the scrolling of the tweets in the footer
$(function () {
var tweetVP = $("#footerTweetsViewport");
arrTweetNav = ECC.tweetArray();
thisTweetID = arrTweetNav[0];
$("ul#tweetControls > li").bind("click", function(e) {
e.preventDefault();
var thisPos = $.inArray(thisTweetID, arrTweetNav);
if ($(this).hasClass("tweetPrev")) {
nextPos = thisPos - 1;
} else {
nextPos = thisPos + 1;
}
nextID = arrTweetNav[nextPos];
//If that tweet exists in the DOM...
if ($("#listOfTweets > #" + nextID).length) {
//Reset the inactive buttons
$("ul#tweetControls > li").removeClass("inactive");
//Scroll to the destination
tweetVP.scrollTo("#" + nextID, 200);
//Set the thisID to the value of the nextID
thisTweetID = nextID;
}
//Disable the controls if we're on the first or last tweet
if (nextPos == arrTweetNav.length-1) {
$("ul#tweetControls > li.tweetNext").addClass("inactive");
} else if (nextPos == 0) {
$("ul#tweetControls > li.tweetPrev").addClass("inactive");
}
}).bind("mousedown", function() {
$(this).closest("li").addClass("click");
}).bind("mouseup", function() {
$(this).closest("li").removeClass("click")
});
});
//Search the dom for twitter containers that need tweets loaded for
$(function() {
$(".globalTweetWrapper").each(function() {
var thisUsername = $(this).attr("class").replace("globalTweetWrapper ", "");
var tweetContainer = $(this);
var loadTweets = tweetContainer.find(".loadTweets");
//Detect if we're going to flush the tweets
var flushTweets = $.getUrlVar("flushTweets");
if (flushTweets != 1) {
flushTweets = 0;
}
$.getJSON("get-tweets.cfm?username=" + thisUsername + "&flushTweets=" + flushTweets, function(data) {
if (data.length && loadTweets.length) {
loadTweets.remove();
$.each(data, function(i,item) {
if (tweetContainer.attr("id") == "listOfTweets") {
tweetContainer.append("<li class='tweetContainer' id='" + item.ID + "'>" + item.TWEET + "<small class='darkGray'>" + item.DATE + "</small></li>");
} else {
tweetContainer.append("<p class='tweetContainer'>" + item.TWEET + "</p><small class='darkGray'>" + item.DATE + "</small>");
if (i == 1) return false;
}
});
//Rebuild the tweet array
arrTweetNav = ECC.tweetArray();
thisTweetID = arrTweetNav[0];
}
});
});
});
This is the HTML
container for the Tweets on the site is as follows:
<div class="footerItem posRelative">
<h3>Follow us on Twitter</h3>
<ul id="tweetControls">
<li class="tweetPrev inactive">Previous Tweet</li>
<li class="tweetNext">Next Tweet</li>
</ul>
<div id="footerTweetsViewport">
<ul id="listOfTweets" class="globalTweetWrapper">
</ul>
My site is not coldfusion; therefore I simply want to modify the get-tweets.cfm and would like some assistance please. I have come across the following:
//initialize a new curl resource
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'twitter url goes here/statuses/user_timeline/twitterusername.json?count=10');
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$content = curl_exec($ch);
curl_close($ch);
if($content === FALSE) {
//Content couldn't be retrieved... Do something
} else {
//Content was retrieved do something with it.
}
So I would really like to rebuild the get-tweets.cfm to a PHP script get-tweets.php; however, I'm not sure what exactly I need this to do to get this to work as per the coldfusion script as everything else is fine?
Many thanks
A new get_tweets script to get tweets, filter to the columns you wanted, cache (in case of Twitter fail whale) and echo results.
<?php
$username = "danielgwood";
$num = 5;
$feed = "http://search.twitter.com/search.json?q=from:" . $username . "&rpp=" . $num;
$cachefile = dirname(__FILE__)."/twitter.json";
// Get new contents
$newTweets = #file_get_contents($feed);
// Filter columns
$tweets = array();
if($newTweets !== null) {
$newTweetsObj = json_decode($newTweets);
foreach($newTweetsObj->results as $tweet) {
$tweets[]['ID'] = $tweet->id;
$tweets[]['TWEET'] = $tweet->text;
$tweets[]['DATE'] = $tweet->created_at;
}
$newTweets = json_encode($tweets);
}
// Cache result
if($newTweets !== null) {
#file_put_contents($cachefile, $newTweets);
}
$tweets = #file_get_contents($cachefile);
echo $tweets;
?>
Twitter provides tweets in JSON format via the API. You need to retrieve these, cache them on your server (write out to a file outside of the web tree) in case Twitter goes down as it regularly does, then echo the JSON out for the Javascript to pick up.
I haven't tested this, but its definitely along the right lines. See bavotasan.com
$username = "your-user-name";
$num = 5;
$feed = "http://search.twitter.com/search.json?q=from:" . $username . "&rpp=" . $num;
$newfile = dirname(__FILE__)."/twitternew.json";
$file = dirname(__FILE__)."/twitter.json";
copy($feed, $newfile);
$oldcontent = #file_get_contents($file);
$newcontent = #file_get_contents($newfile);
if($oldcontent != $newcontent) {
copy($newfile, $file);
}
$tweets = #file_get_contents($file);
echo $tweets;
I should note the above solution is designed to replace the coldfusion script entirely. To use the PHP excerpt you already have, just add the caching to file, and echo parts. That should get you most if not all of the way there.