草庐IT

php - CakePHP - 保存一个 session 变量会删除另一个

coder 2024-04-16 原文

我在 CakePHP 中使用 session 变量来存储我的相关用户 Twitter 和 Facebook 数据,当用户登录时,如果他已经链接了他的 Twitter 和 FB 帐户,则此信息将保存在我自己的用户数据旁边的 session 变量中。

我有一个屏幕,用户可以在其中链接和取消链接所述社交网络数据,问题如下:

假设我连接了两个网络,我决定断开与 Facebook 的连接,Facebook 的 session 变量被删除。现在我想重新连接到 Facebook,我单击“连接”按钮,Facebook 数据已保存,但由于某种原因它删除了 Twitter 变量。

我的流程的工作方式如下:

1) 用户点击连接按钮。 2) 用户被定向到社交网络身份验证。 3) 用户被定向到一个获取所需数据的函数,将其保存在一个名为 NetworkData 的 session 变量中,然后被定向回他单击按钮的页面。 4) NetworkData被提取,设置为 session 中相应的社交网络(Facebook或Twitter),并从 session 中删除。

代码如下:

这是用户登录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'));
      }
    }

这是检索网络数据中的内容并将其设置为 session 的函数:

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>

抱歉发了这么长的帖子。

最佳答案

在您的 retrieve_network 操作中,我假设您在用户重新连接到特定服务时调用它,您正在覆盖 NetworkData session 变量 如果您发现 1 项特定服务已连接到:

if(isset($_GET['oauth_token'])) {...} 

if(isset($_GET['code'])) {...}

您将 $networkData 设置为返回的服务对象,然后通过以下方式覆盖整个 session :

$this->Session->write('NetworkData', $networkData);

按照您的代码,我会始终检查现有服务当前是否在 session 中,如果是,则不要覆盖整个 session ,只需将特定数据添加到现有 NetworkData session 数组中即可:

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 数组。此外,您可以通过 $this->params['url']['paramname'] 访问 $_GET 参数以维护 cakePHP 约定。

关于php - CakePHP - 保存一个 session 变量会删除另一个,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7208354/

有关php - CakePHP - 保存一个 session 变量会删除另一个的更多相关文章

  1. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  2. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  3. ruby-on-rails - 渲染另一个 Controller 的 View - 2

    我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>

  4. ruby-on-rails - 如何从 format.xml 中删除 <hash></hash> - 2

    我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为

  5. ruby - 我可以使用 Ruby 从 CSV 中删除列吗? - 2

    查看Ruby的CSV库的文档,我非常确定这是可能且简单的。我只需要使用Ruby删除CSV文件的前三列,但我没有成功运行它。 最佳答案 csv_table=CSV.read(file_path_in,:headers=>true)csv_table.delete("header_name")csv_table.to_csv#=>ThenewCSVinstringformat检查CSV::Table文档:http://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV/Table.html

  6. ruby-on-rails - 如何使用 instance_variable_set 正确设置实例变量? - 2

    我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击

  7. ruby - 通过 ruby​​ 进程共享变量 - 2

    我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是

  8. ruby - 我可以使用 aws-sdk-ruby 在 AWS S3 上使用事务性文件删除/上传吗? - 2

    我发现ActiveRecord::Base.transaction在复杂方法中非常有效。我想知道是否可以在如下事务中从AWSS3上传/删除文件:S3Object.transactiondo#writeintofiles#raiseanexceptionend引发异常后,每个操作都应在S3上回滚。S3Object这可能吗?? 最佳答案 虽然S3API具有批量删除功能,但它不支持事务,因为每个删除操作都可以独立于其他操作成功/失败。该API不提供任何批量上传功能(通过PUT或POST),因此每个上传操作都是通过一个独立的API调用完成的

  9. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  10. ruby - 为什么 SecureRandom.uuid 创建一个唯一的字符串? - 2

    关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?

随机推荐