So I am making a PHP app that asks for the users Facebook (in those exact terms) I want it to be able to handle the copy and past Facebook URL as well as well as simply just their user name. I found this:
function GetUsernameFromFacebookURL($url) {
$correctURLPattern = '/^https?:\/\/(?:www|m)\.facebook.com\/(?:profile\.php\?id=)?([a-zA-Z0-9\.]+)$/';
if (!preg_match($correctURLPattern, $url, $matches)) {
throw new Exception('Not a valid URL');
}
return $matches[1];
The above code is really good at handling:
https://www.facebook.com/JohnDoe
https://m.facebook.com/sally.struthers
https://www.facebook.com/profile.php?id=24353623
But I would like it to return the input value if no URL is inserted, how do I do this? In addition, I notice a lot of Facebook URLs have additional arguments, such as; https://www.facebook.com/johndoe?fref=ufi - how do I compensate for that?
Related
Having an issue with the Facebook PHP API/SDK, let me begin by describing:
I made a website where you can enter 'quotes' (short messages) and then after saving the quote in the website (read; too a mysql db behind it) you can decide to share the quote with Facebook to be able to win stuff.
The flow (how it should work) is this:
User opens my site, PHP gets a login url from the Facebook PHP API/SDK
PHP reads & memorizes the 'state' url variable from the login url from the above step (which several sites mention would be a valid way to identify users)
A user saves a quote, I store the state variable from above in the db record of that quote so I can use it again later to match returning users with saved quotes.
The user decides to want to win, so he/she clicks the Facebook share button, which points their browser too the Facebook login url from step 1
The user's browser is now looking at some Facebook pages where they have to allow access for the app and allow that it can post to their wall
Once the user has given said access, they return to the callback url of my site (which happens to be the same as the 'origin url' from step 4)
PHP on my site finds the state variable in the returned url variables(?), goes trough the database to find a matching quote record, and if found, it stores some Facebook user data (userid and path to avatar) in the related db record.
PHP continues to post their earlier saved quote to the user's Facebook wall.
In essence, things work, but the most important bit, step 7, identifying who comes back via the state variable, does not. The problem is that I just get some lengthy 'code' GET variable back, and not the 'state' GET variable, and nowhere in the API docs or on StackOverflow or via Google do I find how to change it so I do get the 'state' GET variable returned again...?
So to recap, basically what I'm looking for is an ability to send some sort of identifier to Facebook that then gets included in the callback-url, and to my knowledge, that's what the 'state' variable seems best for, if it would work that is.
I'm using the currently latest API (facebook-php-sdk-v4-5.0.0.zip from this morning) Below I've shared all relevant code I use to interface with the Facebook PHP API/SDK, all this code resides in the index.php in public_html dir of my site, the callback url of my app is this same index.php
This code is pieced together from several examples, and essentially works, I just don't get the needed state variable back.
require_once __DIR__ . '<PATH-TOO-FB-API>/src/Facebook/autoload.php';
session_start();
$fbStateCode = ""; // used to memorize state code
$fbLoginUrl = ""; // user to memorize login url
// Init the API
// If you go end up testing this, dont forget too change <APP-ID> & <APP-SECRET>
$fb = new Facebook\Facebook([
'app_id' => '<APP-ID>',
'app_secret' => '<APP-SECRET>',
'default_graph_version' => 'v2.4',
'default_access_token' => isset($_SESSION['facebook_access_token']) ? $_SESSION['facebook_access_token'] : '<APP-ID>|<APP-SECRET>'
]);
// login helper
$helper = $fb->getRedirectLoginHelper();
// try get an accesstoken (wich we only have if user returned from facebook after logging in)
try {
$accessToken = $helper->getAccessToken();
} catch(Facebook\Exceptions\FacebookResponseException $e) {
//echo 'Graph returned an error: ' . $e->getMessage(); // When Graph returns an error
} catch(Facebook\Exceptions\FacebookSDKException $e) {
//echo 'Facebook SDK returned an error: ' . $e->getMessage(); // When validation fails or other local issues
}
if (isset($accessToken)) {
// User is logged in!
try {
// Now we look up some details about the user
$response = $fb->get('/me?fields=id,name');
$facebook_user = $response->getGraphUser();
exit; //redirect, or do whatever you want
} catch(Facebook\Exceptions\FacebookResponseException $e) {
//echo 'Graph returned an error: ' . $e->getMessage();
} catch(Facebook\Exceptions\FacebookSDKException $e) {
//echo 'Facebook SDK returned an error: ' . $e->getMessage();
}
// if facebook_user has an id, we assume its a user and continue
if(isset($facebook_user['id'])) {
$avatarUrl = "http://graph.facebook.com/".$facebook_user['id']."/picture";
// THE BELOW 8 LINES HANDLE LOADING A QUOTE FROM DB WITH MATCHING STATE AND SAVING
// ADDITIONAL DATA TOO IT, THE ONLY ISSUE HERE IS THAT $_GET['state'] DOESNT EXIST
// THE REST OF THIS PROCESS HAS ALREADY BEEN TESTED AND PROOFED TO BE WORKING
$curr_quote = Quotes::getQuoteByFbStateCode($_GET['state']);
$curr_quote_data = $curr_quote->getData();
$curr_quote->updateData(array(
"fb_access_token" => $accessToken,
"fb_uid" => $facebook_user['id'],
"fb_avatar_path" => $avatarUrl
));
// Save it
if($curr_quote->save()) { // Success! quote in db was updated
// Now that we are logged in and have matched the returned user with a saved quote, we can post that quote too facebook
$_SESSION['facebook_access_token'] = (string) $accessToken; // storing the access token for possible use in the FB API init
// This is the data we post too facebook
$msg_data = array (
'message' => $curr_quote_data['quote']
);
$response = $fb->post('/me/feed',$msg_data,$accessToken); // do the actual post (this, like everything else besides state variable, works)
} else { // Fail! quote in db was NOT updated?!
// handle errors
}
}
} else {
// User is NOT logged in
// So lets build up a login url
$permissions = ['public_profile','publish_actions']; // we want these permissions (note, atm im the only tester, so while the app still needs to be reviewed for the 'publish_actions' permission, it works cuz i own the app and test with same fb account)
$fbLoginUrl = $helper->getLoginUrl('http://<WEBSITE-URL>/index.php', $permissions); // get the login url from the api providing callback url and permissions array
$fbLoginUrlParams = array();
parse_str($fbLoginUrl, $fbLoginUrlParams); // store the url params in a new array so that we can (read next comment below)
$fbStateCode = $fbLoginUrlParams['state']; // read out and store the state url variable
}
Below here is logic for saving a new quote to database based on user interaction, and making use of $fbStateCode, this part of the process functions fine as well, quotes get saved with their own unique state values like they should.
So that's the story, I'm trying to do something which I'm pretty sure isn't anything special, it's just poorly documented or something?
Ended up rewriting the lot, now it works fine, not sure whats different now vs what i had, so cant really provide an awnser for others running into similair issues, sorry bout that.
#Cbroe; forwarded the headsup you gave me too the customer, got literally told 'not our problem, but the problem of the company that made the concept', so time will tell if this ever even goes online lol, still, thanks for the headsup :P
Read the docs about the state variable here:
The state parameter is a value which is provided by the client prior to the login wen redirecting to the login url. If it's available then, it get's send back in the callback url.
So, unless you provide any state variable in your step1, you won't get any from FB (and any other oAuth2 implementing API). There will not be any "magic" making that appear other than providing it with a feasable state of your PHP app in step 1.
Actually, the state parameter is to give any client the ability to restore a context, whenever the callback "happens". So the content of the state variable may be a session id, a user id or any other value which helps restoring the (php)apps context again after receiving a callback
EDIT
I assume, that the state variable needs to be added somewhere in this function here:
$helper = $fb->getRedirectLoginHelper();
We're interested about using Google Custom Search / Google in our project, mostly due to the fact that it's amazing at conjugation & correcting misspelled words.
We know that it can return data in JSON or XML, and we're fine with that. But finding an answer to question:
Can we use that conjugation and mistake correction and search our own database/api?
If you would type drnks with no alcohol it would automatically correct to drinks with no alcohol, and then search our database like this:
http://example.com?search=drinks&alcohol=0, and it could respond like this:
{
"coke": {
"alcohol": 0,
"calories": 300,
"taste": "awesome"
},
"pepsi": {
"alcohol": 0,
"calories": 300,
"taste": "meh"
}
}
And then it would return these two results, in some form.
Solutions using the paid version are fine.
If it's possible to do this, could you provide me with a simple example?
Google provides a REST API for their custom search, you can query it from your server to determine whether there is a better spelling for the search terms or not, and then use that to query your internal database.
In my code I'm using Guzzle, a REST client library to avoid suffering with cURL's ugly and verbose code, but feel free to use cURL if you really need to.
// Composer's autoloader to load the REST client library
require "vendor/autoload.php";
$api_key = "..."; // Google API key, looks like random text
$search_engine = "..."; // search engine ID, looks like "<numbers>:<text>"
$query = "drnks with no alcohol"; // the original search query
// REST client object with some defaults
// avoids specifying them each time we make a request
$client = new GuzzleHttp\Client(["base_url" => "https://www.googleapis.com", "defaults" => ["query" => ["key" => $api_key, "cx" => $search_engine, "fields" => "spelling(correctedQuery)"]]]);
try {
// the actual request, with the search query
$resp = $client->get("/customsearch/v1", ["query" => ["q" => $query]])->json();
// whether Google suggests an alternative spelling
if (isset($resp["spelling"]["correctedQuery"])) {
$correctedQuery = $resp["spelling"]["correctedQuery"];
// now use that corrected spelling to query your internal DB
// or do anything else really, the query is yours now
echo $correctedQuery;
} else {
// Google doesn't have any corrections, use the original query then
echo "No corrections found";
}
} catch (GuzzleHttp\Exception\TransferException $e) {
// Something bad happened, log the exception but act as if
// nothing is wrong and process the user's original query
echo "Something bad happened";
}
Here are some instructions to obtain your API key, and the custom search engine ID can be obtained from the control panel.
If you look carefully you can see I've specified the fields query parameter to request a partial response with only the eventual spelling suggestions, to (hopefully) get better performance as we don't need anything else from the response (but feel free to change/remove it if you do need the complete response).
Note that Google has no clue about what's in your database so the spelling corrections will only be based on the public data Google has about your website, I don't think there is a way to make Google know about your internal DB, not that it's a good idea anyway.
Finally, make sure to handle rate-limits and API failures gracefully by still giving the user the possibility to search using their original query (just act like nothing wrong happened, and only log the error for later review).
I am building a website where I need to retrieve Facebook shares and likes of numerous links and URLs from different sites.
The problem is, for some URLs it is impossible to get what I wanted. For example, when I look for data about links that look like http://www.example.com/?a=1&b=2&c=3 all I get is wrong data about http://www.example.com/?a=1 and the rest of the URL (&b=2&c=3) is simply ignored by Facebook.
Here at StackOverflow, a lot of people are looking for an answer and many questions are simply unanswered. So, once I did it right, I'm back to tell how I did it.
P.S. : This works only for non-Facebook URLs. If you're looking for shares and likes counts of an internal Facebook link (image, video ...), this won't work for you. I'll be using PHP to answer the question.
To get likes and shares counts, I use FQL instead of the Graph API (even though I am actually using the Graph API to send the query).
But this is not enough : to be able to do so, I had call the rawurlencode() function on the URL I want to get data about. Otherwise, I'll keep getting errors.
So, this likes(), the function I am using to have the counts :
function likes($url) {
$url = rawurlencode($url);
$json_string = file_get_contents("http://graph.facebook.com/fql?format=json&q=SELECT%20share_count,%20like_count%20FROM%20link_stat%20WHERE%20url='$url'");
$json = json_decode($json_string, true);
if (key_exists("data", $json)) {
if (is_array($json["data"])) {
if (array_key_exists("0", $json["data"])) {
return intval($json["data"]["0"]["share_count"]) + intval($json["data"]["0"]["like_count"]);
} else {
echo "Error : '0' is no key<br/>";
return 0;
}
} else {
echo "Error : data is no table <br/>";
return 0;
}
} else {
echo "Error : No data key <br/>";
return 0;
}
}
I hope this will help someone someday :)
is any method to validate Youtube video link with Zend-framework ?
If user inputs not valid link, for example http://www.youtube.com/watch?00zzv=nel how can I check it before inserting into site ?
I'm pretty sure that there is no built in validator for this, but writing custom validators is super easy:
class My_Validate_Youtube extends Zend_Validate_Abstract{
public function isValid($value){
// check url here
if (no_good($value)){
$this->_error("Explain the error here");
return false;
}
return true;
}
}
Just put whatever checks you need in that class, and run the validator on any Youtube links to be checked.
edit:
From Laykes, you might want to consider using the validator to check if the video actually exists, instead of determining if it fits a pattern. Depends on your use cases though- eg how much latency do you want to introduce by making a call to the Youtube API?
I don't know if it is possible, however, I would take a different approach and try and see if the link has comments on it.
Take this for example. From here:
http://framework.zend.com/manual/en/zend.gdata.youtube.html
$yt = new Zend_Gdata_YouTube();
$commentFeed = $yt->getVideoCommentFeed('abc123813abc');
foreach ($commentFeed as $commentEntry) {
echo $commentEntry->title->text . "\n";
echo $commentEntry->content->text . "\n\n\n";
}
If you use the video id in the VideoCommentFeed argument, you will be able to get the value in $commentFeed. If you then get an error, you know that the video does not exist.
I am sure if you try other methods you will probably find example what you want.
This may be a stupid question, but is it possible to capture what a user typed into a Google search box, so that this can then be used to generate a dynamic page on the landing page on my Web site?
For example, let's say someone searches Google for "hot dog", and my site comes up as one of the search result links. If the user clicks the link that directs them to my Web site, is it possible for me to somehow know or capture the "hot dog" text from the Google search box, so that I can call a script that searches my local database for content related to hot dogs, and then display that? It seems totally impossible to me, but I don't really know. Thanks.
I'd do it like this
$referringPage = parse_url( $_SERVER['HTTP_REFERER'] );
if ( stristr( $referringPage['host'], 'google.' ) )
{
parse_str( $referringPage['query'], $queryVars );
echo $queryVars['q']; // This is the search term used
}
This is an old question and the answer has changed since the original question was asked and answered. As of October 2011 Google is encrypting this referral information for anyone who is logged into a Google account: http://googleblog.blogspot.com/2011/10/making-search-more-secure.html
For users not logged into Google, the search keywords are still found in the referral URL and the answers above still apply. However, for authenticated Google users, there is no way to for a website to see their search keywords.
However, by creating dedicated landing pages it might still be possible to make an intelligent guess. (Visitors to the "Dignified charcoal sketches of Jabba the Hutt" page are probably...well, insane.)
Yes, it is possible. See HTTP header Referer. The Referer header will contain URL of Google search result page.
When user clicks a link on a Google search result page, the browser will make a request to your site with this kind of HTTP header:
Referer: http://www.google.fi/search?hl=en&q=http+header+referer&btnG=Google-search&meta=&aq=f&oq=
Just parse URL from request header, the search term used by user will be in q -parameter. Search term used in above example is "http header referer".
Same kind of approach usually works also for other search engines, they just have different kind of URL in Referer header.
This answer shows how to implement this in PHP.
Referer header is only available with HTTP 1.1, but that covers just about any somewhat modern browser. Browser may also forge Referer header or the header might be missing altogether, so do not make too serious desicions based on Referer header.
This is an old question but I found out that google no more gives out the query term because it by default redirects every user to https which will not give you the "q"parameter. Unless someone manually enters the google url with http (http://google.com) and then searches, there is no way as of now to get the "q" parameter.
Yes, it comes in the url:
http://www.google.com/search?hl=es&q=hot+dog&lr=&aq=f&oq=
here is an example:
Google sends many visitors to your site, if you want to get the keywords
they used to come to your site, maybe to impress them by displaying it
back on the page, or just to store the keyword in a database, here's the
PHP code I use :
// take the referer
$thereferer = strtolower($_SERVER['HTTP_REFERER']);
// see if it comes from google
if (strpos($thereferer,"google")) {
// delete all before q=
$a = substr($thereferer, strpos($thereferer,"q="));
// delete q=
$a = substr($a,2);
// delete all FROM the next & onwards
if (strpos($a,"&")) {
$a = substr($a, 0,strpos($a,"&"));
}
// we have the results.
$mygooglekeyword = urldecode($a);
}
and we can use <?= $mygooglekeywords ?> when we want to output the
keywords.
You can grab the referring URL and grab the search term from the query string. The search will be in the query as "q=searchTerm" where searchTerm is the text you want.
Same thing, but with some error handling
<?php
if (#$_SERVER['HTTP_REFERER']) {
$referringPage = parse_url($_SERVER['HTTP_REFERER']);
if (stristr($referringPage['host'], 'google.')) {
parse_str( $referringPage['query'], $queryVars );
$google = $queryVars['q'];
$google = str_replace("+"," ",$google); }
else { $google = false; }}
else { $google = false; }
if ($google) { echo "You searched for ".$google." at Google then came here!"; }
else { echo "You didn't come here from Google"; }
?>
Sorry, a little more
Adds support for Bing, Yahoo and Altavista
<?php
if (#$_SERVER['HTTP_REFERER']) {
$referringPage = parse_url($_SERVER['HTTP_REFERER']);
if (stristr($referringPage['host'], 'google.')
|| stristr($referringPage['host'], 'bing.')
|| stristr($referringPage['host'], 'yahoo.')) {
parse_str( $referringPage['query'], $queryVars );
if (stristr($referringPage['host'], 'google.')
|| stristr($referringPage['host'], 'bing.')) { $search = $queryVars['q']; }
else if (stristr($referringPage['host'], 'yahoo.')) { $search = $queryVars['p']; }
else { $search = false; }
if ($search) { $search = str_replace("+"," ",$search); }}
else { $search = false; }}
else { $search = false; }
if ($search) { echo "You're in the right place for ".$search; }
?>