Я использую переменные сеанса в CakePHP для хранения данных моего соответствующего пользователя Twitter и Facebook, когда пользователь входит в систему, если он связал свои учетные записи Twitter и FB, эта информация сохраняется в переменной сеанса рядом с моими собственными пользовательскими данными.
У меня есть экран, на котором пользователь может связывать и отключать указанные данные социальной сети, проблема в следующем:
Допустим, у меня подключены обе сети, я решаю отключиться от Facebook, переменная сеанса для Facebook удалена. Теперь я хочу повторно подключиться к Facebook, я нажимаю кнопку «Подключиться», данные Facebook сохраняются, но по какой-то причине переменная Twitter удаляется.
Мой процесс работает следующим образом:
1) Пользователь нажимает кнопку подключения. 2) Пользователь перенаправляется на авторизацию в социальной сети. 3) Пользователь направляется к функции, которая принимает необходимые данные, сохраняет их в переменной сеанса под названием NetworkData и направляется обратно на страницу, где он нажал кнопку. 4) NetworkData извлекается, устанавливается как соответствующая социальная сеть (Facebook или Twitter) в сеансе и удаляется из сеанса.
Код выглядит следующим образом:
Это функция, которую пользователь направляет после входа в Twitter или FB:
function retrieve_network($page) {
$networkData = null;
$this->autoRender = false;
$this->layout = 'ajax';
if(isset($_GET['oauth_token'])) {
$token = $this->TwitterHelper->setOAuthToken($_GET['oauth_token']);
$userinfo = $this->TwitterHelper->getTwitterUserInfo();
$networkData = array(
'TwitterData' => array(
'username' => $userinfo['username'],
'name' => $userinfo['name'],
'token' => $token->oauth_token,
'token_secret' => $token->oauth_token_secret
)
);
} else if (isset($_GET['code'])) {
$token = $this->FacebookHelper->facebook->getAccessToken();
$userinfo = $this->FacebookHelper->getUserInfo();
$networkData = array(
'FacebookData' => array(
'username' => $userinfo['username'],
'name' => $userinfo['name'],
'email' => $userinfo['email'],
'token' => $token,
'link' => $userinfo['link'],
)
);
}
$this->Session->write('NetworkData', $networkData);
if($page == 'settings') {
$this->redirect(array('controller' => 'fonykers', 'action' => 'settings/networks'));
}
}
Это функция, которая извлекает то, что находится в сетевых данных, и устанавливает их для сеанса:
function settings($tab) {
$this->layout = 'frontend';
$this->Fonyker->recursive = -1;
$this->TwitterData->recursive = -1;
$this->FacebookData->recursive = -1;
if(!$this->checkSessionCookie()) {
$this->redirect(array('controller' => 'pages', 'action' => 'home'));
}
$fields = array(
'Fonyker.id',
'Fonyker.username',
'Fonyker.name',
'Fonyker.email',
'Fonyker.gender',
'Fonyker.birthdate',
'Fonyker.image_url'
);
$fonyker = $this->Fonyker->find('first', array(
'conditions' => array(
'Fonyker.fonykid' => $this->Session->read('Fonyker.Fonyker.fonykid')
),
'fields' => $fields
));
$this->Fonyker->set($fonyker);
$this->data = $fonyker;
if($this->Session->read('NetworkData')) {
$networkData = $this->Session->read('NetworkData');
$this->Session->delete('NetworkData');
if($networkData['TwitterData']) {
$networkData['TwitterData']['fonyker_id'] = $fonyker['Fonyker']['id'];
if($this->TwitterData->save($networkData)) {
$this->Session->write('TwitterData', $networkData['TwitterData']);
}
} else if($networkData['FacebookData']) {
$networkData['FacebookData']['fonyker_id'] = $fonyker['Fonyker']['id'];
if($this->FacebookData->save($networkData)) {
$this->Session->write('FacebookData', $networkData['FacebookData']);
}
}
}
pr($this->Session->read());
if(!$this->Session->read('TwitterData')) {
$this->TwitterHelper->setTwitterObj();
$this->set('twitterUrl', $this->TwitterHelper->twitterObj->getAuthorizeUrl(null, array('oauth_callback' => 'http://127.0.0.1/fonykweb/pages/retrieve_network/settings')));
} else {
$this->set('twitterUrl', '#');
}
if(!$this->Session->read('FacebookData')) {
$this->set('facebookUrl', $this->FacebookHelper->facebook->getLoginUrl(array('redirect_uri' => 'http://localhost/fonykweb/pages/retrieve_network/settings','scope' => 'email,user_birthday,publish_stream,offline_access')));
} else {
$this->set('facebookUrl', '#');
}
$this->set('tab', $tab);
}
Это функция, которая удаляет сеть, если пользователь желает:
function remove_network($network) {
$this->autoRender = false;
$this->Fonyker->recursive = -1;
$this->TwitterData->recursive = -1;
$this->FacebookData->recursive = -1;
$response = null;
if($network == 'twitter') {
$twitterData = $this->TwitterData->find('first', array(
'conditions' => array(
'TwitterData.fonyker_id' => $this->Session->read('TwitterData.fonyker_id')
)
));
if($this->TwitterData->delete($twitterData['TwitterData']['id'], false)) {
$this->TwitterHelper->setTwitterObj();
$twitterUrl = $this->TwitterHelper->twitterObj->getAuthorizeUrl(null, array('oauth_callback' => 'http://127.0.0.1/fonykweb/pages/retrieve_network/settings'));
$this->Session->delete('TwitterData');
$response = json_encode(array('ok' => true, 'url' => $twitterUrl));
} else {
$response = json_encode(array('ok' => false));
}
}
if($network == 'facebook') {
$facebookData = $this->FacebookData->find('first', array(
'conditions' => array(
'FacebookData.fonyker_id' => $this->Session->read('FacebookData.fonyker_id')
)
));
if($this->FacebookData->delete($facebookData['FacebookData']['id'], false)) {
$facebookUrl = $this->FacebookHelper->facebook->getLoginUrl(array('redirect_uri' => 'http://localhost/fonykweb/pages/retrieve_network/settings','scope' => 'email,user_birthday,publish_stream,offline_access'));
$this->Session->delete('FacebookData');
$response = json_encode(array('ok' => true, 'url' => $facebookUrl));
} else {
$response = json_encode(array('ok' => false));
}
}
echo $response;
}
Посмотреть код:
<script type="text/javascript">
$(document).ready(function() {
var splitUrl = window.location.href.split('/');
$('#' + splitUrl[splitUrl.length - 1] + '-tab').addClass('active-tab');
$('#' + splitUrl[splitUrl.length - 1] + '-tab').children().addClass('active-tab');
});
</script>
<div class="prepend-1 prepend-top span-23">
<div class="tabs span-22">
<ul>
<li id="account-tab">
<a href="<?php echo $html->url(array('controller' => 'fonykers', 'action' => 'settings'), true); ?>/account">
Account
</a>
</li>
<li id="password-tab">
<a href="<?php echo $html->url(array('controller' => 'fonykers', 'action' => 'settings'), true); ?>/password">
Password
</a>
</li>
<li id="notifications-tab">
<a href="<?php echo $html->url(array('controller' => 'fonykers', 'action' => 'settings'), true); ?>/notifications">
Notifications
</a>
</li>
<li id="networks-tab">
<a href="<?php echo $html->url(array('controller' => 'fonykers', 'action' => 'settings'), true); ?>/networks">
Social Networks
</a>
</li>
</ul>
</div>
<div class="tab-content prepend-top prepend-1">
<?php
if($tab == 'account') {
echo $this->element('settings/account');
} else if ($tab == 'password') {
echo $this->element('settings/password');
} else if ($tab == 'notifications') {
echo $this->element('settings/notifications');
} else {
echo $this->element('settings/networks');
}
?>
</div>
</div>
Код элемента:
<script type="text/javascript">
$(document).ready(function(){
var deleteNetwork = function(network, button) {
$.ajax({
url: '<?php echo $html->url('/fonykers/remove_network/', true); ?>' + network,
dataType: 'json',
type: 'POST',
success: function(response) {
if(response.ok) {
button.replaceWith('<a id="'+network+'-connect" class="connect-button connect" href="'+response.url+'" class="span-3">Connect</a>');
}
}
});
}
if($('#twitter-connect').attr('href') == '#'){
$('#twitter-connect').addClass('connected');
$('#twitter-connect').html('Connected');
} else {
$('#twitter-connect').addClass('connect');
$('#twitter-connect').html('Connect');
}
if($('#facebook-connect').attr('href') == '#'){
$('#facebook-connect').addClass('connected');
$('#facebook-connect').html('Connected');
} else {
$('#facebook-connect').addClass('connect');
$('#facebook-connect').html('Connect');
}
$('.connected').hover(
function() {
$(this).removeClass('connected');
$(this).addClass('disconnect');
$(this).html('Disconnect')
},
function() {
$(this).removeClass('disconnect');
$(this).addClass('connected');
$(this).html('Connected')
}
);
$('#twitter-connect').click(function(event) {
if($(this).attr('href') == '#') {
event.preventDefault();
deleteNetwork('twitter', $(this));
}
});
$('#facebook-connect').click(function(event) {
if($(this).attr('href') == '#') {
event.preventDefault();
deleteNetwork('facebook', $(this));
}
});
});
</script>
<div class="span-4 prepend-top">
<div class="span-4">
<div class="span-1">
<?php echo $html->image('twitter-connect.png', array('alt' => 'Twitter', 'class' => 'span-1', 'style' => 'height:40px;width:40px')); ?>
</div>
<div class="span-3 last">
<a id="twitter-connect" class="connect-button" href="<?php echo $twitterUrl; ?>" class="span-3"></a>
</div>
</div>
<div class="span-4 prepend-top">
<div class="span-1">
<?php echo $html->image('facebook-connect.png', array('alt' => 'Twitter', 'class' => 'span-1', 'style' => 'height:40px;width:40px')); ?>
</div>
<div class="span-3 last">
<a id="facebook-connect" class="connect-button" href="<?php echo $facebookUrl; ?>"></a>
</div>
</div>
</div>
Извините, за длинную статью.
2 ответа
В вашем действии retrieve_network, которое, как я предполагаю, вы вызываете, когда пользователь повторно подключается к определенной службе, вы перезаписываете переменную сеанса NetworkData, если обнаруживаете, что 1 конкретная служба была подключена к:
if(isset($_GET['oauth_token'])) {...}
ИЛИ
if(isset($_GET['code'])) {...}
Вы устанавливаете $ networkData в возвращаемый объект служб, а затем перезаписываете весь сеанс с помощью:
$this->Session->write('NetworkData', $networkData);
Следуя вашему коду, я всегда буду проверять, находится ли существующая служба в данный момент в сеансе, и если это так, не перезаписывайте весь сеанс, просто добавьте определенные данные в существующий массив сеансов NetworkData:
if($this->Session->read('NetworkData.TwitterData')){
$facebookData = array(
'username' => $userinfo['username'],
'name' => $userinfo['name'],
'email' => $userinfo['email'],
'token' => $token,
'link' => $userinfo['link'],
);
$this->Session->write('NetworkData.FacebookData', $facebookData);
}
Примечание. Это просто пример, показывающий, как этого добиться. Я бы реорганизовал этот метод с лучшей логикой для этой конкретной ситуации, возможно, сохраняя TwitterData и FacebookData в их собственных отдельных массивах, а не в более крупном и более сложном массиве NetworkData. Кроме того, вы можете получить доступ к параметрам $ _GET через $ this-> params ['url'] ['paramname'], чтобы поддерживать соглашение cakePHP.
Я думаю, проблема в том, что вы заменяете сетевые данные, а не объединяете их.
Это означает, что, например, когда вы входите в систему с помощью FB, вы заменяете любые данные Twitter на FB, а не сохраняете их оба.
Я надеюсь, что, может быть, вместо
$this->Session->write('NetworkData', $networkData);
Что
$this->Session->write('NetworkData', array_merge($networkData, $this->Session->read('NetworkData'));
Может работать.
В противном случае мне кажется, что код удаления сеанса не должен взаимодействовать, чтобы один удалял другой. Хотя я мог что-то пропустить, просматривая его. Я бы сделал несколько операций / отладки echo (), чтобы проследить пути выполнения кода.
Похожие вопросы
Новые вопросы
php
PHP - это широко используемый высокоуровневый, динамический, объектно-ориентированный и интерпретируемый язык сценариев, в первую очередь предназначенный для серверной веб-разработки. Используется для вопросов о языке PHP.