Using the php sdk, I check if a user inside a tab likes the corresponding page.
If i put the following code inside index.php and use that page as my page-tab-url,
<?php
require_once("facebook/facebook.php");
// Create our application instance
// (replace this with your appId and secret).
$facebook = new Facebook(array(
'appId' => '1399475990283166',
'secret' => 'mysercret',
'cookie' => true
));
$signed_request = $facebook->getSignedRequest();
echo $signed_request['page']['liked'];
?>
it outputs '1'.
I would like to achieve this asynchronously instead, so I put the php in a separate file and try to access it using ajax instead
$http.post('/facebook/likes.php').
success(function(data){
console.log(data);
}).error(function(data){
console.log(data);
}
);
This sample is using angular, but what javascript library i'm using probably doesn't matter.
When I access the info with javascript Facebook doesn't seem to get the info that I liked the page. Adding a print_r($facebook); on the page I'm retreiving the same values as if i'm not in a facebook-tab:
(
[sharedSessionID:protected] =>
[appId:protected] => 1399475990283166
[appSecret:protected] => 679fb0ab947c2b98e818f9240bc793da
[user:protected] =>
[signedRequest:protected] =>
[state:protected] =>
[accessToken:protected] =>
[fileUploadSupport:protected] =>
[trustForwarded:protected] =>
)
Can I access theese values asynchronosly somehow?
That's because you're only logged as a Facebook application if you can access the signed_request token. This token is sent with the initial request (as a POST parameter), but isn't inside a cookie of anything.
The easiest thing with your actual code would be to re-send this signed request parameter with every ajax request you make so the server and Facebook SDK has access to that information.
But just to check if the user liked the current page. I'd suggest you print the data on the page directly so it is available from the start. Pseudo example:
<script>
window.data = {};
window.data.page_liked = <?= encode_json((boolean)$signed_request['page']['liked']) ?>;
</script>
To know if a user liked the page while he is on the splash page, you place a listener on a facebook event:
FB.Event.subscribe("edge.create", function( response ) {`
if ( response.match(/* RegExp matching your FB page url */) ) {
// user liked!
}
});
response is the URL liked, so you just have to compare it to your page url (facebook.com/MyPage) and then you know if a user clicked the like button in your application.
On a side note, generally the cleanest way to request user information is to login the user (OAuth), and pass requests directly from JS to the Open Graph (you use Angular anyway, so your app must be frontend based already). Your server shouldn't be used as a middle step between the Open Graph and your app, you'll duplicate code for without advantages.
This does not apply to the page.liked property, as it is a page property (not a user one) sent with the signed_request on app loading.
Related
In my Laravel project's app.js, I have this:
let isModalShown = sessionStorage.getItem('book_modal_has_shown');
if(!isModalShown) {
sessionStorage.setItem("book_modal_has_shown", "true");
$('#show_nudge_modal').modal('show');
This acts like a client-side check to stop the modal from coming out if the modal has already appeared (in the previous requests).
In my Controller, I have this:
$unreadBook = Book::getRandomUnreadBook();
return view('home')->with(['book' => $unreadBook]);
The problem is even if the modal does not appear on the client side, Book::getRandomUnreadBook() causes the database fetch operation. I want to add a server side check also to stop this useless database access.
I'm not so much of a framework fan but I have been made to use it because I am working on a project that others may edit later.
I am using the CodeIgniter framework (I'm kinda new on it).
I am using jquery $.post(url, function() {}) to asynchronously call a login parser that is in the root directory under a folder called php-parser I realized this folder does not make use of any of the CodeIgniter's ready made class. I decided to move the folder php-parser into application/libraries but when I tried to use jQuery to call it referencing the full path /application/libraries/php-parser/the-script.php, it return a 403 forbidden error
What do you think I can do? Some people said I could make the script a controller but here is what is going on, It's a popup modal login page. From any page if you click the login / register button, the modal pops up, how can I make a controller and a model for that (if I'm to follow that procedure).
Added: I put the modal content at the end of the footer which is included on all pages, how do I get to create a controller for that kind of modal? Any help!
When dealing with MVC (at least the way you are using it) you have three parts:
The Model - in this case this is the code which interacts with your database.
The View - the code which formats the data you are sending back to the browser
The Controller - the code which connects the two together and might have some business logic in it.
You also have some routing code which maps a URL onto the right controller for that URL.
Browsers (and other clients) only interact with web servers through URLs.
So you absolutely need to have a Controller set up to handle the request from the browser.
If you are doing this the quick and dirty way, then your controller will just get the username and password from the POST request, check it against the database with the model, and then squirt either "Success!" or "Fail!" into the view (which is probably best written as something that returns JSON formatted back to the browser).
If you are being sensibly robust about this then the view will have logic something along the lines of:
Does the browser explicitly include JSON in the accept header?
If so, send back a bit of JSON saying "success" or "failure" (or true / false, or whatever makes sense for you).
Does it not? Then either return a "Sorry, you failed to login!" HTML document or a redirect back to the page they came from (so it will reload in the logged in state).
That way, if the JavaScript fails for any reason, the plain HTML form which was progressively enhanced with the Ajax JavaScript will still function. (NB: You have to write it that way!).
jQuery will automatically include a JSON friendly Accept header if you say dataType: "json" in the Ajax options.
Yes, you will need to put your file inside the libraries folder(if the class is separate from codeigniter or is shared among many controllers, if not a Model would suffice), then create a controller for it.
class Ajax_Controller extends CI_Controller
{
public $statusCode = 200;
public $response = array();
public function __construct()
{
parent::__construct();
if(!$this->is_ajax_request()){
return; // direct access not allowed
}
$this->response = array(
'error' => false,
'text' => "",
'fields' => array()
);
}
public function sendResponse()
{
return $this->output
->set_status_header($this->statusCode)
->set_content_type('application/json')
->set_output(json_encode($this->response));
}
}
class Auth extends Ajax_Controller
{
public function __construct()
{
parent::__construct();
$this->load->library('php-parser/script', 'authentication');
}
public function login()
{
if(!$this->form_validation->run()){
$this->response = array(
'error' => true,
'text' => "The form has some errors",
'fields' => array(
'username' => form_error('username'),
'password' => form_error('password')
)
);
return $this->sendResponse();
}
$username= $this->input->post('username');
$password= $this->input->post('password');
if(!$this->authentication->login($username, $password)){
$this->response = array(
'error' => true,
'text' => "incorrect username/password combination",
'fields' => array()
);
$this->statusCode = 401;
return $this->sendResponse();
}
}
}
I use a common httpRequest to login, so I could use Redirect::intended(); to lead the user to a url before them being lead to the login page. That all works well.
Now I've changed login to ajax request I can only redirect the url in javascript now. So I've to pass the intended url to front end then do the window.location=url
The problem is I can't get the intended/original url. Can any kind laravel expert help me out ?
In your controller action use:
$url = Redirect::intended( ... )->getTargetUrl();
(Where ... is the fallback url)
Then return it in the JSON response, and use window.location or other to do the redirect.
When you are showing the form foe log in, you can grab the intended url from session if available and pass it to the view then redirect using window.location.
So. how to grab the intended url ?
$intended_url = Session::get('url.intended', url('/'));
Session::forget('url.intended');
Here, first argument is intended url if available in the session and default is set to home page using url('/') helper method, so the $intended_url will always contain a url, intended or defaulr. Then when you are loading the view, pass the $intended_url using this:
return View::make('login')->with('intended_url', $intended_url);
Then use it from the view like:
window.location = $intended_url;
Alternatively, you may setup a View Composer so whenever the login view/form is displayed the intended url will be available in that view and you can do it using this:
View::composer('login', function($view){
$intended_url = Session::get('url.intended', url('/'));
Session::forget('url.intended');
return $view->with('intended_url', $intended_url);
});
Here, login is the view name for login page, if this is something else in your case then change it to the appropriate name of your login view. You can keep this code in your app/start folder inside the 'global.php' file or keep it in a separate file and include this fie inside global.php file using this (at the end):
require 'view_composer.php';
Assumed that, file name would be view_composer.php, present in the app/start folder.
In Laravel 5.7:
$url = redirect()->intended()->getTargetUrl();
I am using the following approach with a custom login controller and middleware for Laravel 5.7, but I hope that works in any of laravel 5 versions
inside middleware
if (Auth::check()){
return $next($request);
}
else{
return redirect()->guest(route('login'));
}
if you are not passing the intented url to client side use the following inside controller login method
if (Auth::attempt(['email' => $email, 'password' => $password])) {
return redirect()->intended('/default');
}
If you need to pass the intented url to client side, you can try the following
if (Auth::attempt(['username' => $request->username, 'password' => $request->password])) {
$intended_url= redirect()->intended('/default')->getTargetUrl();
$response = array(
'status' => 'success',
'redirectUrl' => $intended_url,
'message' => 'Login successful.you will be redirected to home..', );
return response()->json($response);
} else {
$response = array(
'status' => 'failed',
'message' => 'username or password is incorrect', );
return response()->json($response);
}
Redirect to the intented url from clientside
success: function (data) {
if(data.redirectUrl){
window.location.href = data.redirectUrl;
}
},
how can i execute facebook ajax link like https://www.facebook.com/ajax/bookmark/groups/leave/?group_id=XXXXXXX (which can only be executed using a mouse click) using PHP. So far i can get all my groups ID via the graph api. Found this outdated code on google: http://bpaste.net/show/76918/
You should do it via Facebook API, instead of mocking AJAX request
$facebook = new Facebook(array(
'appId' => 'YOUR_APP_ID',
'secret' => 'YOUR_APP_SECRET',
));
$feed = $facebook->api('YOUR_GRAPH_API_CALL');
you can use graph api in facebook developper space :
check this and replace your-id by your id:
https://developers.facebook.com/tools/explorer/?method=GET&path=you-id%3Ffields%3Dgroups.fields%28id%29
I'm creating a custom affiliate program. I want my links to be as SEO friendly as possible, so I will use a Javascript hash appended to the URL to send the affiliate id, read the affiliate id, store the click, and then 301 re-direct to the page they were linked too. That way we have no canonical issues whatsoever, and every affiliate link passes link juice!
Now, how would I read the following URL?
www.mydomain.com/seo-friendly-url#ref=john
After getting the hash value for ref and adding the click, how would I then 301 re-direct the user back to
www.mydomain.com/seo-friendly-url
Any help is greatly appreciated!
Fragment identifiers (the part after the #) are not sent to the server, so they cannot be read by anything that could then emit an HTTP response (which you need for a 301 redirect).
The "hash" portion of a URL is not passed to the server, so you will not be able to utilize this data for any server-side redirection or processing directly. However, it is possible to grab the hash on page load and pass it on to the server via AJAX or redirection:
To immediately redirect a user from www.mydomain.com/seo-friendly-url#ref=john to www.mydomain.com/seo-friendly-url/ref/john
if (window.location.hash.match(/#ref=/))
window.location = window.location.href.replace('#ref=', '/ref/')
... but then, why not have just used www.mydomain.com/seo-friendly-url/ref/john to begin with and save the extra leg work? The other route, through AJAX, involves reading the value of the hash after the page has loaded and sending that off to the server to be recorded.
(note: this code uses a generic cross-browser XMLHTTPRequest to send an AJAX GET request. replace with your library's implementation [if you are using a library])
window.onload = function () {
// grab the hash (if any)
var affiliate_id = window.location.hash;
// make sure there is a hash, and that it starts with "#ref="
if (affiliate_id.length > 0 && affiliate_id.match(/#ref=/)) {
// clear the hash (it is not relevant to the user)
window.location.hash = '';
// initialize an XMLRequest, send the data to affiliate.php
var oXMLHttpRequest = new XMLHttpRequest;
oXMLHttpRequest.open("GET", "record_affiliate.php?affiliate="+affiliate_id, true);
oXMLHttpRequest.onreadystatechange = function() {
if (this.readyState == XMLHttpRequest.DONE) {
// do anything else that needs to be done after recording affiliate
}
}
oXMLHttpRequest.send(null);
}
}