Jak na FB login na vlastní stránky
- David Matějka
- Moderator | 6445
@xciza: ten example u kdyby/facebook ani nijak nepouziva vlastni authenticator, rovnou nastavuje identitu, tudiz tvuj authenticator s emailem by mel i nadale fungovat bez problemu
- xciza
- Člen | 194
Tak se zkousim vydat vlastni cestou ale narazil jsem na mensi problem. Stahl jsem is SDK od facebooku a ulozil ji do libs. v configu jsem si nadefinal appid a secret a v services dal facebook:
Facebook( {appId: %facebook.appId%, secret: %facebook.secret%} )
ale laděnka mě vypiše že třídu nenašla. Musim ji ještě nekde specialně registrovat tu třídu? je v:
libs
-Facebook
-src
-facebook.php
díky
- David Matějka
- Moderator | 6445
pokud neco instalujes jinak pres composer, tak na to musi videt robot loader. to, kam vidi, si nastavis v bootstrap.php
- Filip Procházka
- Moderator | 4668
@xciza měl bys použít Kdyby/Facebook, ušetříš si spoustu práce, ten SDK přímo od facebooku se nemá s Nette moc rád kvůli sessions a taky nemá sexy debug bar panel ;)
- Pavel Macháň
- Člen | 282
xciza napsal(a):
Tak jsem se na to trosku hloubeji podival a nevim jestli to chapu dobre ale v podstate stahnu z github Kdyby/Facebook, hodim to slozky libs a pak v souboru composer.json hodim require: Kdyby/Facebook?
do composer.json pridej to require a dej update… kdyby/facebook ti to stahne samo
- Filip Procházka
- Moderator | 4668
@xciza Naopak, nainstaluješ si composer, do
composer.json
přidáš do sekce
require
kdyby/facebook
"require": {
"nette/nette": "~2.1",
"kdyby/facebook": "~1.0"
}
Potom pustíš příkaz composer update
, který stáhne
Kdyby/Facebook do složky vendor/
, vygeneruje autoloader a
potom pomocí
require_once __DIR__ . '/../vendor/autoload.php';
tento vygenerovaný autoloader vložíš do app/bootstrap.php
a
díky tomu se bude Nette a Kdyby/Facebook načítat pomocí composeru
(respektive autoloaderu který vygeneroval).
Používat composer se opravdu musíš naučit, doplňků a knihoven které bez něj nefungují bude ubývat.
- xciza
- Člen | 194
Díky. Úspěšně nainstalováno přes composer. v configu zapsano appId a secret. Teď bych to rád zakomponoval do svého SignPresenteru, ale tady se opět ztrácim. Nevím čím přesně začít. V SignPresenteru mám standartní komponetu pro vytvoření přihlašovacího formuláře a jeho zpracování. Pomohl by někdo opět prosím? V dokumentaci sice je nástřel authenticatoru, ale nevím jak to přehodit do toho svého…
Díky
Edit: po zapsání do configu:
facebook:
appId: '727802710587354'
secret: string secret
mě laděnka hodi chybu „The Application ID expects to be string, NULL given“ v souboru vendor\kdyby\facebook\src\Kdyby\Facebook\DI\FacebookExtension.php
Nmělo by si to to appId vzit z toho configu?
Editoval xciza (10. 3. 2014 16:14)
- xciza
- Člen | 194
Tak jsem si na to vytvoril od zakladu novou aplikaci pouze na to abych rozchodil prihlaseni. Prihlaseni pomoci usernam a hesla jde v pohode. Nainstaloval jsem si pomoci composeru kdyby/facebook a do sveho sign presenteru pridal komponetu FbLogin. Teď mám v souboru:
namespace App\Presenters;
use Nette,
Kdyby\Facebook\Facebook,
Kdyby\Facebook\Dialog\LoginDialog,
Kdyby\Facebook\FacebookApiException,
Nette\Diagnostics\Debugger;
/**
* Sign in/out presenters.
*/
class SignPresenter extends BasePresenter {
/** @var Facebook */
private $facebook;
public function __construct(Facebook $facebook) {
parent::__construct();
$this->facebook = $facebook;
}
protected function createComponentFbLogin() {
$dialog = $this->facebook->createDialog('login');
...
}
ale laděnka mě vyhodí chybu:
No service of type Kdyby\Facebook\Facebook found. Make sure the type hint in App\Presenters\SignPresenter::__construct() is written correctly and service of this type is registered.
Tak nějak nevím co si s touto chybou počít?
- Filip Procházka
- Moderator | 4668
@xciza když to dáš do bootstrapu tak musíš cache mazat ručně, kdybys to dal do configu tak by se to překompilovalo samo… Smazal jsi cache?
- jiri.pudil
- Nette Blogger | 1032
Registrace rozšíření patří do sekce extensions
,
konfigurace jednotlivých rozšíření do sekcí, které se jmenují stejně
jako klíč, pod kterým rozšíření registruješ. Všechny jsou na stejné
úrovni jako services
, nette
, … Tedy
nějak takto:
nette:
# ...
services:
# ...
extensions:
facebook: Kdyby\Facebook\DI\FacebookExtension
facebook:
appId: "..."
appSecret: ...
- Filip Procházka
- Moderator | 4668
Takhle to mám já a funguje
extensions:
facebook: Kdyby\Facebook\DI\FacebookExtension
facebook:
appId: "12345"
appSecret: "*****"
permissions: [email, ...]
Pokud ti to hlásí tu chybu, znamená to že hodnota se do extension
nedostala. To může být způsobeno blbou cachí, tím že to píšeš do
špatného configu který se třeba ani nenačítá, nebo to píšeš do blbé
sekce v tom configu. Nebo neumíš kopírovat z dokumentace a místo
appId
jsi napsal appid
.
Jdi na web http://ne-on.org, zkopíruj do levého textarea svůj config, smázni z toho hesla a hoď sem datovou strukturu jaká z toho vylezla.
Další věc co můžeš udělat je otevřít metodu
Kdyby\Facebook\DI\FacebookExtension::loadConfiguration()
a dumpnout
si co vrací tohle
$config = $this->getConfig($this->defaults); // najdi tenhle řádek
dump($config, $this->getConfig()); exit; // tenhle řádek přidej
Mělo by se ti ukázat jaký config se dostane do extension a to by ti mohlo napovědět co děláš blbě.
- xciza
- Člen | 194
Tady je datová struktura configu:
array(5) {
parameters => array(1) {
facebook => array(2) {
appId => "12345" (5)
appSecret => "******" (6)
}
}
php => array(1) {
"date.timezone" => "Europe/Prague" (13)
}
nette => array(2) {
application => array(2) {
errorPresenter => "Error" (5)
mapping => array(1) {
"*" => "App\*Module\Presenters\*Presenter" (33)
}
}
session => array(1) {
expiration => "14 days" (7)
}
}
extensions => array(1) {
facebook => "Kdyby\Facebook\DI\FacebookExtension" (35)
}
services => array(3) {
0 => "App\UserManager" (15)
1 => "App\RouterFactory" (17)
router => "@App\RouterFactory::createRouter" (32)
}
}
tady celý config:
parameters:
facebook:
appId: "12345"
appSecret: "******"
php:
date.timezone: Europe/Prague
# zlib.output_compression: yes
nette:
application:
errorPresenter: Error
mapping:
*: App\*Module\Presenters\*Presenter
session:
expiration: 14 days
extensions:
facebook: Kdyby\Facebook\DI\FacebookExtension
services:
- App\UserManager
- App\RouterFactory
router: @App\RouterFactory::createRouter
a zde dump ze souboru FacebookExtension:
array (9)
appId => NULL
appSecret => NULL
fileUploadSupport => FALSE
trustForwarded => FALSE
clearAllWithLogout => TRUE
domains => array ()
permissions => array ()
canvasBaseUrl => NULL
curlOptions => array (6)
78 => 10
19913 => TRUE
13 => 20
10018 => "facebook-php-3.2" (16)
10023 => array ()
2 => TRUE
array ()
Jestli to z toho dumpu chápu dobře tak se tam config ani nenatáhne. Jak je to možné?
Configy mám dva: config.neon (struktura výše) a config.local.neon kde je pouze pripojení na db
Editoval xciza (11. 3. 2014 7:08)
- jiri.pudil
- Nette Blogger | 1032
Jak jsem napsal: „všechny [konfigurační sekce] jsou na stejné úrovni
jako services
, nette
, …“ Tedy i
facebook
má být samostatná sekce (stejně jako
extensions
), v parameters
nemá co dělat.
- xciza
- Člen | 194
Jo aha, blbe sem to pochopil. Teď za se mám chybu „No service of type Facebook found. Make sure the type hint in App\Presenters\SignPresenter::__construct() is written correctly and service of this type is registered.“
Přeoložit si to umim, ale zaregistrovana je v tom configu ne?
EDIT: Moje chyba-vloudil se me tam spatny znak. po smazani je to ok
Editoval xciza (11. 3. 2014 9:16)
- xciza
- Člen | 194
Ještě se k tomu zeptám: Co vše je nejlepší ukládat do db a podle čeho nejlépe kontrolovat jestli uživatel již není na stránkách registrován? Později chci implementovat i sdílení příspěvků, které uživatel napíše na webovkách. Proto se ptám co je nejlepší ukládat do db, podle čeho pak příspěvky můžu postnout na zeď uživatele na fb?
- jiri.pudil
- Nette Blogger | 1032
Určitě si ulož id uživatele, abys ho měl příště jak poznat. A hodit se ti může také access token. Kdyby si ho sice drží v session, ale není od věci mít ho i v databázi pro případ, kdy bys chtěl s Facebookem něco provádět třeba v CLI skriptu.
A co se týče kontroly, jestli uživatel už není registrovaný,
nejjednoduššeji a nejpřímočařeji to jde asi podle emailu (musíš si
o něj říct v configu v permissions
).
- Filip Procházka
- Moderator | 4668
@xciza facebook ve svých best practise říká, že o právo o sdílení si máš říct až jej potřebuješ.
Není od věci si udělat nějakou tabulku
user_facebook_permissions
, do které si uložíš jednotlivá
práva která ti uživatel povolil, bude to taková databázová cache těch
oprávnění.
dump($facebook->getProfile()->getPermissions());
- koukneš jestli máš podle databáze povoleno sdílení
- A) pokud máš tak pošleš požadavek na sdílení
- pokud sdílení selže (vyhodí to
FacebookApiException
) tak B)
- pokud sdílení selže (vyhodí to
- B) oprávnění nemáš, takže uživatele přesměruješ
na facebook s žádostí o povolení oprávnění
- až se vrátíš, tak si uložíš nový stav oprávnění do databáze, potom A)
- A) pokud máš tak pošleš požadavek na sdílení
- piskotek
- Člen | 35
ahoj,
zkousim pouzit FB login, ale vyhodilo mi to tuto chybu:
Nette\MemberAccessException
Call to undefined method Nette\DI\ServiceDefinition::setInject()
kdyby/facebook/src/Kdyby/Facebook/DI/FacebookExtension.php:72
64: // dump($config, $this->getConfig()); exit;
65:
66: $configurator = $builder->addDefinition($this->prefix('config'))
67: ->setClass('Kdyby\Facebook\Configuration')
68: ->setArguments(array($config['appId'], $config['appSecret']))
69: ->addSetup('$fileUploadSupport', array($config['fileUploadSupport']))
70: ->addSetup('$trustForwarded', array($config['trustForwarded']))
71: ->addSetup('$permissions', array($config['permissions']))
72: ->setInject(FALSE);
poradite mi nekdo co s tim ?
diky
- Tomáš Votruba
- Moderator | 1114
Ahoj, tvá verze Nette zřejmě tuto metodu nemá. Jakou verzi Nette
používáš?
Doporučuji instalovat přes composer, který se
o závislosti postará.
- xciza
- Člen | 194
Tak tohle jsem vyresil prozatim presunutim vytvoreni componenty FbLogin do BasePresenteru (možnost přihlásit se bude na každé stránce). Ale teď mě to vyhodilo hlášku:
Call to a member function createDialog() on a non-object
na řádek
$dialog = $this->facebook->createDialog('login');
Chápu že se to snaží vytvořit na ne-objektu, ale co upravit?
Děkuju moc
- Filip Procházka
- Moderator | 4668
Problém je v tom, že se snažíš sahat na property $facebook
ve které nic není. Nejspíš do té property budeš muset dostat nějak tu
službu.
Takže buďto v čistém Nette takto (pozor, to @var
a
@inject
jsou důležité!).
abstract class BasePresenter extends Nette\Application\UI\Presenter
{
/** @var \Kdyby\Facebook\Facebook @inject */
public $facebook;
// potom v createControlFbLogin() už bude naplněná
// protože nette tam tu třídu dá po vytvoření instance presenteru samo
}
Nebo pomocí Kdyby\Autowired, pokud máš PHP >= 5.4
abstract class BasePresenter extends Nette\Application\UI\Presenter
{
use \Kdyby\Autowired\AutowireProperties;
/** @var \Kdyby\Facebook\Facebook @autowire */
protected $facebook;
// v createControlFbLogin() bude objekt přístupný
// ovšem jeho instance se díky magii bude vytvářet lazy
}
- David Matějka
- Moderator | 6445
a kde to pouzivas? nemas to v anonymni fci v php 5.3?
kdyztak pouzij
$self = $this;
function() use($self) {
if(!$existing = $self->usersModel ...)
...
(usersModel pak musi byt public, pripadne si do use rovnou predej ten usersModel)
- piskotek
- Člen | 35
používám to v SignPresenteru, mám vytvořený úplně nový projekt a
mám to udělané dle návodu
nicméně, při přidání $self mi vyskočí chyba:
PDOException #2013
SQLSTATE[HY000] [2013] Lost connection to MySQL server at 'reading initial communication packet', system error: 111
File: …/vendor/nette/database/src/Database/Connection.php:66
66: $this->pdo = new PDO($this->params[0], $this->params[1], $this->params[2], $this->options);
- David Matějka
- Moderator | 6445
tohle opravdu nesouvisi s kdyby/facebook, ale s chybou s pripojenim k mysql serveru. Bud mas spatne nastaveny pristupovy udaje nebo si to proste vygoogli.
- Tomáš Votruba
- Moderator | 1114
@vosy Tu si musíš vytvořit sám. Pracuje s databází, příkladem ti může být UserManager ze sandboxu.
- David Matějka
- Moderator | 6445
@vosy a co se stane? nejaka chyba? neprihlasi te to?
nebo jen ze te to prihlasi bez zobrazeni toho okna? jestli tohle tak je to
spravne, aplikace je jiz u fb toho uzivatele autorizovana.
Nevim, jestli to jde nejak elegantnejc pro testovani, ale muzes ji odebrat
na facebooku a pak se prihlasis znova
- luke82
- Člen | 12
@vosy, řeším teď stejný problém jak jsi zde nastínil. Když se přihlásím do nette aplikace přes kdyby/facebook, a pak se odhlásím pomocí:
$this->getUser()->logout();
a následně se chci do aplikace přihlásit zase přes facebook, ale již jako jiný uživatel, už mi to nenabídne přihlašovací okno pro facebook. Prostě se přihlásí jako předchozí. Vyřešil jsi to nějak? Díky.
- luke82
- Člen | 12
Jde mi o to, že když se uživatel přihlásí do nette aplikace přes Facebook login, nemusí mu dojít, že je přihlášen i na Facebooku. Odhlásí se z nette aplikace, ale na Facebooku přihlášen zůstane. Když je uživatel zrovna třeba v internetové kavárně, je to bezpečnostní problém… A když zůstane přihlášen na Facebooku, nette aplikace se už neptá a přihlásí se zase jako předchozí uživatel.
- Filip Procházka
- Moderator | 4668
@luke82 to na straně tvojí aplikace jen těžko vyřešíš. Maximálně můžeš udělat nějaké okno „nezapomeňte se odhlásit i z facebooku“ potom co se odhlásí od tebe.
- David Matějka
- Moderator | 6445
Jestli jsem dobre pochopil dokumentaci, tak by odhlaseni v aplikaci by melo odhlasit i uzivatele na fb: https://developers.facebook.com/…ok-login/web#…
Note: This function call will also log the person out of Facebook. The reason for this is that someone may have logged into your app and into Facebook during the login flow. If this is the case, they might not expect to still be logged into Facebook when they log out of your app. To avoid confusing people and to protect personal security, we enforce this logout behavior.