在非对象上调用成员函数isValid()

时间:2011-07-12 18:56:18

标签: php zend-framework

我有错误

[12-Jul-2011 11:05:43] PHP Fatal error:  Call to a member function isValid() on a non-object in /usr/share/pear/ZendFramework/1.11.7/library/Zend/Auth.php on line 127

出现在我的代码中。我一直试图找出问题所在,并一直在研究它,但没有成功。

<?php

class UserController extends Zend_Controller_Action
{

    /**
     * Application keys from appkeys.ini
     *
     * @var ZendX_Config
     */
    protected $_keys;

    public function init()
    {
         $appkeys = new ZendX_Config_Ini(APPLICATION_PATH . '/configs/appkeys.ini', APPLICATION_ENV);
         Zend_Registry::set('keys',$appkeys);
         $this->_keys = Zend_Registry::get('keys');
    }

    public function indexAction()
    {
        // action body
    }

    public function loginAction()
    {
        // get an instace of Zend_Auth
        $auth = Zend_Auth::getInstance();

        // check if a user is already logged
        if ($auth->hasIdentity())
        {
            $this->_helper->FlashMessenger('It seems you are already logged into the system ');
            return $this->_redirect('/index/index');
        }

        // if the user is not logged, then do the logging
        // $openid_identifier will be set when users 'clicks' on the account provider
        $openid_identifier = $this->getRequest()->getParam('openid_identifier', null);

        // $openid_mode will be set after first query to the openid provider
        $openid_mode = $this->getRequest()->getParam('openid_mode', null);

        // this one will be set by facebook connect
        $code = $this->getRequest()->getParam('code', null);

        // while this one will be set by twitter
        $oauth_token = $this->getRequest()->getParam('oauth_token', null);


        // do the first query to an authentication provider
        if ($openid_identifier)
        {

            if ('https://www.twitter.com' == $openid_identifier)
            {
                $adapter = $this->_getTwitterAdapter();
            }
            else if ('https://www.facebook.com' == $openid_identifier)
            {
                $adapter = $this->_getFacebookAdapter();
            }
            else
            {
                // for openid
                $adapter = $this->_getOpenIdAdapter($openid_identifier);

                // specify what to grab from the provider and what extension to use
                // for this purpose
                $toFetch = $this->_keys->openid->tofetch->toArray();

                // for google use AtributeExchange Extension
                if ('https://www.google.com/accounts/o8/id' == $openid_identifier)
                {
                    $ext = $this->_getOpenIdExt('ax', $toFetch);
                }
                else
                {
                    $ext = $this->_getOpenIdExt('sreg', $toFetch);
                }

                $adapter->setExtensions($ext);
            }

            // here a user is redirect to the provider for logging
            $result = $auth->authenticate($adapter);

            // the following two lines should never be executed unless the redirection fails.
            //$this->_helper->FlashMessenger('Redirection failed');
           // return $this->_redirect('/index/');
        }
        else if ($openid_mode || $code || $oauth_token)
        {
            // this will be exectued after provider redirected the user back to us

            if ($code)
            {
                // for facebook
                $adapter = $this->_getFacebookAdapter();
            }
            else if ($oauth_token)
            {
                // for twitter
                $adapter = $this->_getTwitterAdapter()->setQueryData($_GET);
            }
            else
            {
                // for openid
                $adapter = $this->_getOpenIdAdapter(null);

                // specify what to grab from the provider and what extension to use
                // for this purpose
                $ext = null;

                $toFetch = $this->_keys->openid->tofetch->toArray();

                // for google use AtributeExchange Extension
                if (isset($_GET['openid_ns_ext1']) || isset($_GET['openid_ns_ax']))
                {
                    $ext = $this->_getOpenIdExt('ax', $toFetch);
                }
                else if (isset($_GET['openid_ns_sreg']))
                {
                    $ext = $this->_getOpenIdExt('sreg', $toFetch);
                }

                if ($ext)
                {
                    $ext->parseResponse($_GET);
                    $adapter->setExtensions($ext);
                }
            }

            $result = $auth->authenticate($adapter);

            if ($result->isValid())
            {

                $toStore = array('identity' => $auth->getIdentity());


                if ($ext)
                {
                    // for openId
                    $toStore['properties'] = $ext->getProperties();
                }
                else if ($code)
                {
                    // for facebook
                    $msgs = $result->getMessages();
                    $user = ($msgs['user']);
                    $hometown = ($user['hometown']['name']);
                    $location = ($user['location']['name']);
                    $sports = ($user['sports']['0']['name']);
                    $favAth = ($user['favorite_athletes']['0']['name']);

                    $user['hometown'] = $hometown;
                    $user['location'] = $location;
                    $user['sports'] = $sports;
                    $user['favorite_athletes'] = $favAth;

                    $toStore['properties'] = $user;

                    $userID = $user['id'];

                    $ogurl = "******";
                    define(FACEBOOK_APP_ID, "*****");
                    define(FACEBOOK_SECRET, "******");

                    $message = "Hello World!";
                    $link = '****';
                    $name = '****';
                    $picture = '****';

                    $access_token_url = "https://graph.facebook.com/oauth/access_token";
                    $parameters = "grant_type=client_credentials&client_id=" . FACEBOOK_APP_ID .
                        "&client_secret=" . FACEBOOK_SECRET;
                    $access_token = file_get_contents($access_token_url . "?" . $parameters);

                    $apprequest_url = "https://graph.facebook.com/{$userID}/feed";
                    $parameters = "?" . $access_token . /*"&message=" .
                        urlencode($message) . */"&picture=" .
                        urlencode($picture) . "&link=" . urlencode($link) ."&name=" .
                        urlencode($name) ."&id=" . $ogurl . "&method=post";

                    $myurl = $apprequest_url . $parameters;

                    $post = file_get_contents($myurl);

                    // output the post id
               //     echo "post_id" . $result;


                }
                else if ($oauth_token)
                {
                    // for twitter
                    $identity = $result->getIdentity();

                    // get user info
                    $twitterUserData = (array) $adapter->verifyCredentials();

                    $toStore = array('identity' => $identity['user_id']);

                    if (isset($twitterUserData['status']))
                    {
                        $twitterUserData['status'] = (array) $twitterUserData['status'];
                    }
                    $toStore['properties'] = $twitterUserData;

                    //Tweet
                    $oAuthToken     = '****';
                    $oAuthSecret    = '****';


                    // create a new instance
                    $tweet = new TwitterOAuth($consumerKey, $consumerSecret, $oAuthToken, $oAuthSecret);

                    //send a tweet
                    $tweet->post('statuses/update', array('status' => 'Hello World'));
                }

                $auth->getStorage()->write($toStore);
                $this->_helper->FlashMessenger('Successful authentication');
                return $this->_redirect('/index/index');

            }
            else
            {
                $this->_helper->FlashMessenger('Failed authentication');
                $this->_helper->FlashMessenger($result->getMessages());
                return $this->_redirect('/index/index');
            }
        }
    }


    public function logoutAction()
    {
        $auth = Zend_Auth::getInstance();
        $auth->clearIdentity();
        $this->_helper->FlashMessenger('You were logged out');
        return $this->_redirect('/index/index');
    }

    /**
     * Get My_Auth_Adapter_Facebook adapter
     *
     * @return My_Auth_Adapter_Facebook
     */
    protected function _getFacebookAdapter()
    {
        extract($this->_keys->facebook->toArray());
        return new My_Auth_Adapter_Facebook($appId, $secret, $redirecturi, $scope);


    }

    /**
     * Get My_Auth_Adapter_Oauth_Twitter adapter
     *
     * @return My_Auth_Adapter_Oauth_Twitter
     */
    protected function _getTwitterAdapter()
    {
        extract($this->_keys->twitter->toArray());
        return new My_Auth_Adapter_Oauth_Twitter(array(), $appid, $secret, $redirecturi, $token, $authSecret);


    }

    /**
     * Get ZendX_Auth_Adapter_OpenId adapter
     *
     * @param string $openid_identifier
     * @return ZendX_Auth_Adapter_OpenId
     */
    protected function _getOpenIdAdapter($openid_identifier = null)
    {
        $adapter = new ZendX_Auth_Adapter_OpenId($openid_identifier);
        $dir = APPLICATION_PATH . '/tmp';

        if (!file_exists($dir))
        {
            if (!mkdir($dir))
            {
                throw new Zend_Exception("Cannot create $dir to store tmp auth data.");
            }
        }
        $adapter->setStorage(new Zend_OpenId_Consumer_Storage_File($dir));

        return $adapter;
     }

    /**
     * Get Zend_OpenId_Extension. Sreg or Ax.
     *
     * @param string $extType Possible values: 'sreg' or 'ax'
     * @param array $propertiesToRequest
     * @return Zend_OpenId_Extension|null
     */
    protected function _getOpenIdExt($extType, array $propertiesToRequest)
    {
        $ext = null;

        if ('ax' == $extType)
        {
            $ext = new My_OpenId_Extension_AttributeExchange($propertiesToRequest);
        }
        elseif ('sreg' == $extType)
        {
            $ext = new Zend_OpenId_Extension_Sreg($propertiesToRequest);
        }
        return $ext;
    }
}

Facebook适配器看起来像......

<?php


/**
 * Description of Facebook
 *
 * @link http://www.krotscheck.net/2010/08/21/zend_auth_adapter_facebook.html
 * @author Michael Krotscheck
 */
class My_Auth_Adapter_Facebook implements Zend_Auth_Adapter_Interface
{
    /**
     * The Authentication URI, used to bounce the user to the facebook redirect uri.
     *
     * @var string
     */
    const AUTH_URI = 'https://graph.facebook.com/oauth/authorize?client_id=%s&redirect_uri=%s';

    /**
     * The token URI, used to retrieve the OAuth Token.
     *
     * @var string
     */
    const TOKEN_URI = 'https://graph.facebook.com/oauth/access_token';


    /**
     * The user URI, used to retrieve information about the user.
     *
     * @var string
     */
    const USER_URI = 'https://graph.facebook.com/me';
    /**
     * The application ID
     *
     * @var string
     */
    private $_appId = null;

    /**
     * The application secret
     *
     * @var string
     */
    private $_secret = null;

    /**
     * The authentication scope (advanced options) requested
     *
     *
     */
    private $_scope;

    /**
     * The redirect uri
     *
     * @var string
     */
    private $_redirectUri = null;

     /**
     * Constructor
     *
     * @param string $appId the application ID
     * @param string $secret the application secret
     * @param array $scope the application scope
     * @param string $redirectUri the URI to redirect the user to after successful authentication
     */
    public function __construct($appId, $secret, $redirectUri, $scope)
    {
        $this->_appId = $appId;
        $this->_secret = $secret;
        $this->_scope = $scope;
        $this->_redirectUri   = $redirectUri;
    }

    /**
     * Sets the value to be used as the application ID
     *
     * @param  string $appId The application ID
     * @return My_Auth_Adapter_Facebook Provides a fluent interface
     */
    public function setAppId($appId)
    {
        $this->_appId = $appId;
        return $this;
    }

    /**
     * Sets the value to be used as the application secret
     *
     * @param  string $secret The application secret
     * @return My_Auth_Adapter_Facebook Provides a fluent interface
     */
    public function setSecret($secret)
    {
        $this->_secret = $secret;
        return $this;
    }

    /**
     * Sets the value to be used as the application scope (array())
     *
     * @param  string $scope The application scope
     * @return My_Auth_Adapter_Facebook Provides a fluent interface
     */
    public function setApplicationScope($scope)
    {
        $this->_scope = $scope;
        return $this;
    }

    /**
     * Sets the redirect uri after successful authentication
     *
     * @param  string $redirectUri The redirect URI
     * @return My_Auth_Adapter_Facebook Provides a fluent interface
     */
    public function setRedirectUri($redirectUri)
    {
        $this->_redirectUri = $redirectUri;
        return $this;
    }


    /**
     * Authenticates the user against facebook
     * Defined by Zend_Auth_Adapter_Interface.
     *
     * @throws Zend_Auth_Adapter_Exception If answering the authentication query is impossible
     * @return Zend_Auth_Result
     */
    public function authenticate()
    {
        // Get the request object.
        $frontController = Zend_Controller_Front::getInstance();
        $request = $frontController->getRequest();

        // First check to see whether we're processing a redirect response.
        $code = $request->getParam('code');

        if ( empty ($code ) )
        {
            // Create the initial redirect
            $loginUri = sprintf(My_Auth_Adapter_Facebook::AUTH_URI , $this->_appId, $this->_redirectUri);

            if ( !empty($this->_scope) )
            {
                $loginUri .= "&scope=" . $this->_scope;
            }

            header('Location: ' . $loginUri );

        }

        else
        {
            // Looks like we have a code. Let's get an access token
            $client = new Zend_Http_Client( My_Auth_Adapter_Facebook::TOKEN_URI );
            $client->setParameterGet('client_id', $this->_appId);
            $client->setParameterGet('client_secret', $this->_secret);
            $client->setParameterGet('code', $code);
            $client->setParameterGet('redirect_uri', $this->_redirectUri);
            $result = $client->request('GET');
            $params = array();
            parse_str($result->getBody(), $params);


            // Retrieve the user info
            $client = new Zend_Http_Client(My_Auth_Adapter_Facebook::USER_URI );
            $client->setParameterGet('client_id', $this->_appId);
            $client->setParameterGet('access_token', $params['access_token']);
            $result = $client->request('GET');
            $user = json_decode($result->getBody(), true);

            return new Zend_Auth_Result( Zend_Auth_Result::SUCCESS, $user['id'], array('user'=>$user, 'token'=>$params['access_token']) );

        }
    }
}

对此问题的任何帮助将不胜感激。提前谢谢。

2 个答案:

答案 0 :(得分:3)

Zend_Auth_Result失败时,您忘记返回My_Auth_Adapter_Facebook::authenticate() - 对象。

答案 1 :(得分:1)

在调用$result之前,您应该检查isValid()是否为实际对象。