I want to have a fake URL for the yii2 advanced application
below is the sample I want to achieve
Home Page
www.example.com/er45se5t
Users page
www.example.com/er45se5t/users/index
Explanation:
Here er45se5t is a token or an identifier. I need this token to be present in URL for every request.
Solutions tried:
I tried to save token in session and set it and added it with all URLs
added these rules
'<token:\w+>' => 'site/index',
'<token:\w+>/<controller:\w+>' => '<controller>/index'
Problem
When I logout this session got cleared and cannot add this token to URL.
so after logging out, I want the URL to look like this
www.example.com/er45se5t
or
www.example.com/er45se5t/site/login
You can add component named CustomUrlManager with content:
namespace frontend\components;
use yii\web\UrlManager;
class CustomUrlManager extends UrlManager
{
public function createUrl($params)
{
$defaultToken='er45se5t';
if( isset($params['token']) ){
//you can add whatever here
$token=$params['token'];
unset($params['token']);
} else {
//you can add whatever here
$token=$defaultToken;
}
$url = parent::createUrl($params);
if( $url == '/' ){
return '/'.$token;
}else{
return '/'.$token.$url;
}
}
}
And in config file as component:
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'class'=>'frontend\components\CustomUrlManager',
'rules'=>[
]
],
And you can redirect www.example.com/ to some www.example.com/er45se5t on default controller
Related
I am upgrading a .net API to .net Core 3.1 and using Swashbuckle.AspNetcore 5.4.1. The API is running inside a ServiceFabric app. I found this https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/1173 and tried to follow that and swagger gets generated but if I try to use the Swagger UI to send requests the request URL is with the wrong IP so the request fail.
In the old Swashbuckle 4.0.1 setup we did not specify host, only the relative basePath. How can I achieve the same?
Startup.cs
var swaggerBasePath = "/MySfApp/SfApp.ClientApi/";
app.UseSwagger(c =>
{
c.SerializeAsV2 = serializeAsSwaggerV2;
c.RouteTemplate = "swagger/{documentName}/swagger.json";
c.PreSerializeFilters.Add((swaggerDoc, httpReq) =>
{
swaggerDoc.Servers = new List<OpenApiServer> { new OpenApiServer { Url = $"{httpReq.Scheme}://{httpReq.Host.Value}{swaggerBasePath}" } };
});
});
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint("api/swagger.json", "My API V1");
});
The result is that the Swagger UI loads correctly on URL:
http://145.12.23.1:54000/MySfApp/SfApp.ClientApi/swagger/index.html
and it says under name that BaseUrl is:
[ Base URL: 10.0.0.4:10680/MySfApp/SfApp.ClientApi/ ]
The 10.0.0.4:10680 is the node inside the ServiceFabric cluster. Correct IP to reach from outside is 145.12.23.1:54000. In the older version (4.0.1) of Swashbuckle it says baseUrl without IP first: "/MySfApp/SfApp.ClientApi"
Swagger.json is located at:
http://40.68.213.118:19081/MySfApp/SfApp.ClientApi/swagger/api/swagger.json
and it says:
"swagger": "2.0",
...
"host": "10.0.0.4:10680",
"basePath": "/MySfApp/SfApp.ClientApi/",
"schemes": [
"http"
],
"paths": {
"/activity/{activityId}": {
"get"
...etc
If i try to send a GET request from the Swagger UI the request is sent to wrong IP:
curl -X GET "http://10.0.0.4:10680/MySfApp/MySfApp/activity/3443"
EDIT 1:
After some digging I have now changed the setup to this in
startup.cs
var swaggerBasePath = "/MySfApp/SfApp.ClientApi/";
app.UsePathBase($"/{swaggerBasePath}");
app.UseMvc();
app.UseSwagger(c =>
{
c.SerializeAsV2 = serializeAsSwaggerV2;
c.PreSerializeFilters.Add((swaggerDoc, httpReq) =>
{
if (!httpReq.Headers.ContainsKey("X-Original-Host"))
return;
var serverUrl = $"{httpReq.Headers["X-Original-Proto"]}://" +
$"{httpReq.Headers["X-Original-Host"]}/" +
$"{httpReq.Headers["X-Original-Prefix"]}";
swaggerDoc.Servers = new List<OpenApiServer>()
{
new OpenApiServer { Url = serverUrl }
};
});
});
app.UseSwaggerUI(options => {
options.SwaggerEndpoint("api/swagger.json", "My API V1");
});
This now leads to the Swagger UI loading properly with the baseUrl
http://145.12.23.1:54000/MySfApp/SfApp.ClientApi/swagger/index.html
and also swagger.json is served correctly with the correct baseUrl.
http://145.12.23.1:54000/MySfApp/SfApp.ClientApi/swagger/api/swagger.json
So the wrong hostname is resolved. Thanks to idea from this thread.
However when I try to call an endpoint from the Swagger UI page, the curl URL does not include the baseUrl. So closer... but currently not possible to use Swagger UI.
curl -X GET "http://10.0.0.4:10680/activity/3443"
The swagger.json does not have 'host' nor 'basePath' defined.
We're using Swashbuckle version 6.1.4 - which is the latest as of this time of writing and we're still having the same issue when our API is deployed in Azure App Service that is mapped through Azure Front Door and APIM. The "Try out" functionality does not work as the base path / api route prefix is stripped from the Swagger UI. For example,
Instead of https://{DOMAIN}.com/{BASEPATH}/v1/Foo, the Swagger UI uses this: https://{DOMAIN}.com/v1/Foo. You can see that the /BASEPATH is missing.
I spent the whole day trying to fix this with trial and error, trying various approaches with no luck, I couldn't get an elegant way to get the base path from swagger configuration. For the time being, here's what I did to fix it:
app.UseSwagger(options =>
{
//Workaround to use the Swagger UI "Try Out" functionality when deployed behind a reverse proxy (APIM) with API prefix /sub context configured
options.PreSerializeFilters.Add((swagger, httpReq) =>
{
if (httpReq.Headers.ContainsKey("X-Forwarded-Host"))
{
//The httpReq.PathBase and httpReq.Headers["X-Forwarded-Prefix"] is what we need to get the base path.
//For some reason, they returning as null/blank. Perhaps this has something to do with how the proxy is configured which we don't have control.
//For the time being, the base path is manually set here that corresponds to the APIM API Url Prefix.
//In this case we set it to 'sample-app'.
var basePath = "sample-app"
var serverUrl = $"{httpReq.Scheme}://{httpReq.Headers["X-Forwarded-Host"]}/{basePath}";
swagger.Servers = new List<OpenApiServer> { new OpenApiServer { Url = serverUrl } };
}
});
})
.UseSwaggerUI(options =>
{
options.RoutePrefix = string.Empty;
options.SwaggerEndpoint("swagger/v1/swagger.json", "My Api (v1)");
});
Here's an open discussion related to this issue here.
I were having something similar in my solution and I have used a little bit this way and that works well for me, in case that helps someone.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
var pathBase = Configuration["PATH_BASE"];
if (!string.IsNullOrWhiteSpace(pathBase))
{
app.UsePathBase($"/{pathBase.TrimStart('/')}");
app.Use((context, next) =>
{
context.Request.PathBase = new PathString($"/{pathBase.TrimStart('/')}");
return next();
});
if (env.IsDevelopment())
{
app.UseSwagger(c =>
{
c.PreSerializeFilters.Add((swaggerDoc, httpReq) =>
{
if (!httpReq.Headers.ContainsKey("X-Original-Host"))
return;
var serverUrl = $"{httpReq.Headers["X-Original-Proto"]}://" + $"{httpReq.Headers["X-Original-Host"]}/" + $"{httpReq.Headers["X-Original-Prefix"]}";
swaggerDoc.Servers = new List<OpenApiServer>()
{
new OpenApiServer { Url = serverUrl }
}
});
});
app.UseSwaggerUI(c => c.SwaggerEndpoint($"/{pathBase.TrimStart('/')}/swagger/v1/swagger.json", "My.API v1"));
}
}
}
check the last line
app.UseSwaggerUI(c => c.SwaggerEndpoint($"/{pathBase.TrimStart('/')}/swagger/v1/swagger.json", "My.API v1"));
Try this:
serverUrl = $"{httpReq.Headers["X-Forwarded-Proto"]}://" +
$"{httpReq.Headers["X-Forwarded-Host"]}" + _basePath;
where _basePath can be set using the ServiceName property of StatelessServiceContext.
Please be noted that the original value of X-Forwarded-Proto may be overridden by SF.
It seems quite simple but there is something I am not able to figure out. I hope someone can help me fast.
I have an url, something like http://host/controller/action/argument/named:1/?query1=1. I want to add another query param to look it like http://host/controller/action/argument1/argument2/named:1/?query1=1&query2=2. I fact I want to add query2=2 to all URLs on a particular page, through some callback or something.
An URL may or may not have query params in the existing page URL.
How do I do it?
Example url : http://www.example.com/myController/myAction/param1:val1/param2:val2
You can use :
$this->redirect(array("controller" => "myController",
"action" => "myAction",
"param1" => "val1",
"param2" => "val2",
$data_can_be_passed_here),
$status,
$exit);
Hope it helps you.
May be I am thinking too much of it but here is how it came out. I put it in a UtilityHelper.
function urlmodify($params = array(), $baseurl = true) {
$top_level_1 = array('plugin', 'controller', 'action'); //top level vars
$top_level_2 = array('pass', 'named'); //top level vars
//for integrated use
$top_level = array_merge($top_level_1, $top_level_2);
$urlparams = array();
//get top level vars
foreach($top_level as $k) {
if(in_array($k, $top_level_1)) {
$urlparams[$k] = $this->request->params[$k];
}
if(in_array($k, $top_level_2)) {
$$k = $this->request->params[$k]; //create $pass & $named
}
}
//get query vars
if($this->request->query) {
$urlparams['?'] = $this->request->query;
}
//check for custom pass vars
if(isset($params['pass'])) {
$pass = array_merge($pass, $params['pass']);
}
//pass var has to be in numarical index
foreach($pass as $v) {
array_push($urlparams, $v);
}
//check for custom named vars
if(isset($params['named'])) {
$named = array_merge($named, $params['named']);
}
//pass var has to be in key=>value pair
foreach($named as $k=>$v) {
$urlparams[$k] = $v;
}
//check for custom query vars
if(isset($params['?'])) {
$urlparams['?'] = array_merge($urlparams['?'], $params['?']);
}
return Router::url($urlparams, $baseurl);
}
}
I have an URL: http://localhost/project/exlplugin/logs/manage_columns/1/a:1/n:1/?b=1. On some links I want to add some certain parameters. Here is the result when i call
echo $this->Utility->urlmodify(array('pass'=>array(2), 'named'=>array('m'=>2), '?'=>array('c'=>2)));*
It gives: http://localhost/thecontrolist/spreadsheet/logs/manage_columns/1/2/a:1/n:1/m:2?b=1&c=2
I just wanted to add just a query parameter to all my listing urls deleted=0 or deleted=1 for the SoftDelete thing :)
Thank you #u2460470 for the answer but it's just about modifying (not removing or creating anything but just adding some params to) current URL on a view page.
I am developing a CRUD system in Phalcon PHP (version 1.3.4).
My goal is to create a link (delete row), that asks for confirmation on click (JavaScript confirmation box) and then goes (request type POST) to the link.
So lets say a user clicks on the "delete row" button.
JavaScript confirmation "Are you sure you want to delete this row?"
User clicks "yes"
Webpage does a POST to "/users/delete/1"
I know CakePHP has a function (FormHelper::postLink()) that does exactly that.
I was wondering if Phalcon PHP also had a function like this.
I see three possibilities to achieve what you want. One is to create a macro in Volt template, second is to add a function to your View. Third and closest to - what I understand is your wish - is to extend Phalcons tag helper and this is part I will describe here.
Phalcon has its own Tag helper to allow you to easily create some elements. postLink is not a part that is implemented there, but you can easily achieve it. In my example I have namespace of Application with class of Tag that extends from \Phalcon\Tag. This is my base for this tutorial.
// Tag.php
namespace Application;
class Tag extends \Phalcon\Tag
{
static public function postLink() {
return '<strong>TEST TAG</strong>';
}
}
To force Phalcon DI to use this class, it is necessary to override it's standard declaration from engine by declaring it by hand as a new DI service:
// services.php
$di['tag'] = function() {
return new \Application\Tag();
};
You can test if it is working properly by typing {{ tag.postLink() }} in Volt template or with $this->tag->postLink() if using phtml template.
Now you can fill your Tag::postLink() method with HTML and parameters you wish it will produce:
namespace Application;
class Tag extends \Phalcon\Tag
{
static $forms = [];
static public function postLink($title, $url, $options = array()) {
// random & unique form ID
while ($randId = 'f_' . mt_rand(9000, 999999)) {
if (!isset(self::$forms[$randId])) {
self::$forms[$randId] = true;
break;
}
}
// dialog message
$dialogMessage = isset($options['message']) && $options['message'] ? $options['message'] : 'Are you sure you want to go on?';
$html = <<<HTML
<form action="{$url}" method="post" id="{$randId}">
<!-- maybe not necessary part -->
<input type="hidden" name="confirmed" value="1" />
</form>
{$title}
HTML;
return $html;
}
}
Now you can run it like this:
{{ tag.postLink('delete', '/users/delete/1') }}
{% set formOptions = ['message' : 'Are you sure you want to delete user Kialia Kuliambro?'] %}
{{ tag.postLink('delete', '/users/delete/1', formOptions) }}
{{ tag.postLink('delete', '/users/delete/1', ['message' : 'Are you sure you want to delete user Kialia Kuliambro?']) }}
Have fun extending :)
There's a few ways to implement such behavior in phalcon. Before anything, we need to understand how views and view helpers work in phalcon. And if you pay close attention, you'll notice, both .volt and .phtml have direct access to the DI.
In volt, for example, you can access the flash service, and output its messages by calling:
{{ flash.output() }}
which gets converted to the phtml: <?php echo $this->flash->output(); ?>
Thus my solution focuses on defining a new service in the DI which volt can access. In CakePHP, the syntax for postLink(), looks something like: echo $this->Form->postLink() while the function is actually defined in a class named FormHelper. So my solution will do the same thing, define a class FormHelper, then inject it into the view under the name Form.
Create an app/helpers/ directory.
Update your app/config/config.php file adding a reference to our new directory: 'helpersDir'=> APP_PATH . '/app/helpers/'
Update your app/config/loader.php file adding $config->application->helpersDir to the registered directories.
Create a new file app/helpers/FormHelper.php
Copy-paste the following code into the file:
<?php
use Phalcon\Tag;
class FormHelper extends Tag
{
protected $_lastAction = '';
public function dottedNameToBracketNotation($name)
{
$parts=explode('.',$name);
$first = array_shift($parts);
$name=$first . ($parts ? '[' . implode('][', $parts) . ']' : '');
return $name;
}
protected function flatten(array $data, $separator = '.')
{
$result = [];
$stack = [];
$path = null;
reset($data);
while (!empty($data)) {
$key = key($data);
$element = $data[$key];
unset($data[$key]);
if (is_array($element) && !empty($element)) {
if (!empty($data)) {
$stack[] = [$data, $path];
}
$data = $element;
reset($data);
$path .= $key . $separator;
} else {
$result[$path . $key] = $element;
}
if (empty($data) && !empty($stack)) {
list($data, $path) = array_pop($stack);
reset($data);
}
}
return $result;
}
protected function _confirm($message, $okCode, $cancelCode = '', $options = [])
{
$message = json_encode($message);
$confirm = "if (confirm({$message})) { {$okCode} } {$cancelCode}";
if (isset($options['escape']) && $options['escape'] === false) {
$confirm = $this->h($confirm);
}
return $confirm;
}
public function h($text, $double = true, $charset = 'UTF-8')
{
return htmlspecialchars($text, ENT_QUOTES | ENT_SUBSTITUTE, $charset, $double);
}
protected function _lastAction($url)
{
$action = $url;//Router::url($url, true);
$query = parse_url($action, PHP_URL_QUERY);
$query = $query ? '?' . $query : '';
$this->_lastAction = parse_url($action, PHP_URL_PATH) . $query;
}
public function postLink($title, $url = null, array $options = [])
{
$out='';
$options += ['block' => null, 'confirm' => null];
$requestMethod = 'POST';
if (!empty($options['method'])) {
$requestMethod = strtoupper($options['method']);
unset($options['method']);
}
$confirmMessage = $options['confirm'];
unset($options['confirm']);
$formName = str_replace('.', '', uniqid('post_', true));
$formOptions = [
'name' => $formName,
'style' => 'display:none;',
'method' => 'post',
];
if (isset($options['target'])) {
$formOptions['target'] = $options['target'];
unset($options['target']);
}
$formOptions[0]=$url;
$out.=$this->form($formOptions);
$out .= $this->hiddenField(['_method','value' => $requestMethod]);
$fields = [];
if (isset($options['data']) && is_array($options['data'])) {
foreach ($this->flatten($options['data']) as $key => $value) {
$out .= $this->hiddenField([$this->dottedNameToBracketNotation($key),'value' => $value]);
}
unset($options['data']);
}
$out .= $this->endForm();
//This is currently unsupported
if ($options['block']) {
if ($options['block'] === true) {
$options['block'] = __FUNCTION__;
}
//$this->_View->append($options['block'], $out);
$out = '';
}
unset($options['block']);
$url = '#';
$onClick = 'document.' . $formName . '.submit();';
if ($confirmMessage) {
$options['onclick'] = $this->_confirm($confirmMessage, $onClick, '', $options);
} else {
$options['onclick'] = $onClick . ' ';
}
$options['onclick'] .= 'event.returnValue = false; return false;';
$options[0]=$url;
$options[1]=$title;
$options[2]=false;
$out .= $this->linkTo($options);
return $out;
}
}
Edit your app/config/services.php file and add in:
$di->set('Form',function () {
return new FormHelper();
});
(you could make "Form" lowercase if you want, both work. I made it capital to closer resemble CakePHP's syntax. Do note that Volt is case sensitive when trying to access services but phtml will lowercase it.)
Edit the template you want to test the code on, such as app/views/index/test.volt
Copy-paste the following code into there:
{{ Form.postLink(' Delete','',['confirm':'Are you sure you want to delete #4?','data':['a':['b','c']]]) }}
Alternatively for phtml, use: <?php echo $this->form->postLink(' Delete', '', array('confirm' => 'Are you sure you want to delete #4?', 'data' => array('a' => array('b', 'c')))); ?>
Run it, and watch it work its magic, just render your index/test.volt template by visiting /index/test in your address bar. (Make sure you defined such an action in your index controller)
In terms, of other solutions, you could also use $compiler->addFunction() to make functions available to volt, one at time. The page in the manual gives the example of $compiler->addFunction('shuffle', 'str_shuffle');. You can attempt to override the factoryDefault for "tag" in the DI, and use the helper we already defined which extends tag. So you'd just change it from "form" to "tag" like so: $di->set('tag',function () {return new FormHelper();}); but, as you can see, it won't make the function postLink() available to volt as a function, you'll notice you still need to access it as tag.postLink(). Rather, all the \Phalcon\Tag functions are actually hard-coded into the volt engine. You can see this clearly by viewing the zephir source code of the \Phalcon\Mvc\View\Engine\Volt\Compiler class available over here. For your convenience, and in case the link ever gets broken, I have posted a snippet here which shows the "tag" functions in volt are actually hard-coded into it:
if method_exists(className, method) {
let arrayHelpers = this->_arrayHelpers;
if typeof arrayHelpers != "array" {
let arrayHelpers = [
"link_to": true,
"image": true,
"form": true,
"select": true,
"select_static": true,
"submit_button": true,
"radio_field": true,
"check_field": true,
"file_field": true,
"hidden_field": true,
"password_field": true,
"text_area": true,
"text_field": true,
"email_field": true,
"date_field": true,
"tel_field": true,
"numeric_field": true,
"image_input": true
];
let this->_arrayHelpers = arrayHelpers;
}
if isset arrayHelpers[name] {
return "$this->tag->" . method . "(array(" . arguments . "))";
}
return "$this->tag->" . method . "(" . arguments . ")";
}
So, if you'd like to "hack" in a few more methods by extending the \Phalcon\Tags class, you're out of luck. However, as demonstrated on the volt documentation page, there exists the concept of registering custom extensions to work with volt. The documentation gives the example of: $compiler->addExtension(new PhpFunctionExtension());
Where the source of the class is:
<?php
class PhpFunctionExtension
{
/**
* This method is called on any attempt to compile a function call
*/
public function compileFunction($name, $arguments)
{
if (function_exists($name)) {
return $name . '('. $arguments . ')';
}
}
}
This would allow volt access to any function you'd like, without having to manually register every possible function you could possibly ever need. You can test this by trying to access str_shuffle in volt, like we did before with $compiler->addFunction('shuffle', 'str_shuffle'); but this time without having to register it.
In terms of other solutions, you could also try to integrate CakePHP and PhalconPHP together, and attempt to call CakePHP's view helpers from PhalconPHP, but then you'd run into a problem of CakePHP not understanding your router setup you have configured in Phalcon. But, if you're determined, you could code all the routes and config for CakePHP and run it alongside PhalconPHP, but I'd highly discourage such a desperate workaround. And, finally, if you understand how the function works, and you barely use it, you could get away with just hard-coding the HTML in the first place. Honestly, CakePHP's logic doesn't look so sound to me in the first place because it has to corrupt your HTML document with a form inserted which can bother your layout. I think it would make more sense to generate a form dynamically with JavaScript, if we're using JavaScript already, and append it to the <body> when the button is clicked, then submit the form we just created dynamically. But, you wanted a CakePHP implementation, so I coded it as close to the logic they used as possible. It's not perfect, in terms of supporting all their features, such as block, but it should suit most of your needs.
I can always revise my implementation, but I think it demonstrates how to work with Phalcon pretty well for those migrating from CakePHP.
Currently my app posts to the users wall every time they access the app. I only want it to post to the wall one time when they first authorize the app. Then every time they access it afterward it only updates the news feed status.
here is my current code:
// Get User ID
$user = $facebook->getUser();
if ($user) {
try {
// Proceed knowing you have a logged in user who's authenticated.
$access_token = $facebook->getAccessToken();
$vars = array(
'message' => "Message goes here",
'picture' => "image",
'link' => "link here",
'name' => "Name here",
'caption' => "Caption here"
);
$result = $facebook->api('/me/feed', 'post', $vars);
} catch (FacebookApiException $e) {
error_log($e);
$user = null;
}
}
// Login or logout url will be needed depending on current user state.
if ($user) {
$logoutUrl = $facebook->getLogoutUrl();
} else {
$loginUrl = $facebook->getLoginUrl(array('redirect_uri'=> $app_url));
echo "<script type='text/javascript'>";
echo "top.location.href = '{$loginUrl}';";
echo "</script>";
}
What do I need to change in order to make that happen?
You have 2 choices of methods to achieve this behavior.
Utilize the Feed Dialog on the landing page for your users. This will popup a Facebook window prompting your users to share something on their wall. This method requires that you implement the JavaScript SDK as well.
Utilize the PHP SDK and programatically posting a feed story to the /me/feed endpoint. (As you have done in the try-catch block of your code sample).
With regard to only posting on the users first visit you should store in your database a boolean value. When you create a new record for the new user in your database you should include a field called something like first_visit and populate it with a "true" value.
Then when you detect a returning user (that means he is already in your database) you can check to see that the first_visit field is set to "false". Then your post via the PHP SDK can be the result of a conditional expression to test the first_visit value :
...
...
if ($first_visit == 'true'){
$result = $facebook->api('/me/feed', 'post', $vars);
}
An additional solution (not requiring a database) could be something similar to this :
When you so cunningly generate the login URL with the $facebook->getLoginUrl() method for your un-authorized users, you can add a temporary GET parameter to the redirect_uri parameter. Something like :
$redirect_uri = 'https://apps.facebook.com/waffle-ville?new_user=true';
Then your conditional expression for posting to the users wall would look something like this :
...
...
if ($_GET['new_user'] == 'true'){
$result = $facebook->api('/me/feed', 'post', $vars);
}
Don't forget to redirect the user back to the original URL after you have made the post :
var app_url = "https://apps.facebook.com/waffle-ville";
echo "<script type='text/javascript'>";
echo "top.location.href = app_url;";
echo "</script>";
The redirect is also possible with PHP :
$app_url = "https://apps.facebook.com/waffle-ville";
header("Location: {$app_url}");
IMO - Posting to a users wall automagically is a little bit annoying. There is a parameter in your application settings that is called Social Discovery. When this is set to "enabled" a story is automagically created as soon as a user installs your application. I recommend leaving posting to a users wall as an optional user initiated action.
I've figured it out. I created a database to store info and it checks to see if the User ID already exists or not. If it doesn't, then they are placed in the database and a post is made to their wall. If they are in the database, then nothing happens.
<?php
require 'facebook.php';
require 'dbconnect.php';
// Create our application instance
// (replace this with your appId and secret).
$app_id = "APP_ID";
$secret = "APP_SECRET";
$app_url = "APP_URL";
$facebook = new Facebook(array(
'appId' => $app_id,
'secret' => $secret,
'cookie' => true,
));
// Get User ID
$user = $facebook->getUser();
// We may or may not have this data based on whether the user is logged in.
//
// If we have a $user id here, it means we know the user is logged into
// Facebook, but we don't know if the access token is valid. An access
// token is invalid if the user logged out of Facebook.
if ($user) {
try {
// Proceed knowing you have a logged in user who's authenticated.
$user_profile = $facebook->api('/me');
$access_token = $facebook->getAccessToken();
$name = $user_profile['name'];
$birthday = $user_profile['birthday'];
} catch (FacebookApiException $e) {
error_log($e);
$user = null;
}
}
// Login or logout url will be needed depending on current user state.
if ($user) {
$logoutUrl = $facebook->getLogoutUrl();
} else {
$loginUrl = $facebook->getLoginUrl(array('redirect_uri'=> $app_url));
echo "<script type='text/javascript'>top.location.href = '$loginUrl';</script>";
}
//DO NOT EDIT BELOW
$db=mysql_connect($hostname, $dbuser, $pass);
mysql_select_db($database, $db);
//check if user has already signed up before
$insert = true;
$result = mysql_query("SELECT * FROM table_name") or die(mysql_error());
while($row = mysql_fetch_array($result)){
//if user id exists, do not insert
if(( $row['UID'] == $user)){
$insert = false;
}
}
// if new user, insert user details in your mysql table
if($insert){
mysql_query("INSERT INTO table_name (UID, username, userbirthday) VALUES ('$user','$name','$birthday') ") or die(mysql_error());
$access_token = $facebook->getAccessToken();
$vars = array(
'message' => "message goes here",
'picture' => "image",
'link' => "Link here",
'name' => "Name here",
'caption' => "Caption here",
);
$result = $facebook->api('/me/feed', 'post', $vars);
}
?>
I'm building FB app, need to check Does user like my page or not.
To arrange it, I need to get permissions from user.
I arranged Login (So that while entering in application it requires login),
but after login I need to redirect to the same page, App-s index..
After first login, it doesn't stop.
$facebook = new Facebook(array(
'appId' => '139844459464342',
'secret' => '*********************',
));
// Get User ID
$user = $facebook->getUser();
if ($user) {
try {
// Proceed knowing you have a logged in user who's authenticated.
$user_profile = $facebook->api('/me');
} catch (FacebookApiException $e) {
error_log($e);
$user = null;
}
}
if ($me) {
$logoutUrl = $facebook->getLogoutUrl();
} else {
$loginUrl = $facebook->getLoginUrl(array(
'canvas' => 1,
'fbconnect' => 1,
'display' => 'page',
'req_perms' => 'user_likes',
'next' => 'http://apps.facebook.com/my-aki-tim/',
'cancel_url'=> 'http://apps.facebook.com/my-aki-tim/'
));
echo "<script type='text/javascript'>top.location.href = '$loginUrl';</script>";
it works, but I can not stop Logged in user..
Please help me if you can, thanks in advance
You are using wrong variable $me which is not defined in your code and this causing redirection loop. Either change $me to $user_profile or rewrite an assignment:
$me = $facebook->api('/me');