Créer une application Twitter OAuth

王林
Libérer: 2023-08-27 20:34:02
original
827 Les gens l'ont consulté

OAuth est peut-être un concept difficile à comprendre au début, mais avec l'API Twitter nécessitant désormais son utilisation, vous devez le comprendre avant de créer une application Twitter. Ce didacticiel vous présente OAuth et vous guide tout au long du processus de création d'une application de base.


Présentation

Dans ce tutoriel, nous allons créer une application simple qui permet aux utilisateurs d'appliquer différents effets à leur avatar Twitter. Afin d'utiliser l'API Twitter, nous devons utiliser OAuth pour autoriser notre application à faire des requêtes au nom de l'utilisateur.

Notre flux de candidature sera le suivant :

  1. Le système demandera à l'utilisateur de se connecter à Twitter.
  2. Le système affichera un aperçu de la liste d'avatars à l'utilisateur pour sa sélection.
  3. Après la sélection, l'utilisateur verra un écran de confirmation montrant l'avatar d'origine et le nouvel avatar à des fins de comparaison. Les utilisateurs peuvent également choisir d'envoyer des tweets.
  4. Après confirmation de l'utilisateur, l'application crée l'avatar modifié et le télécharge sur Twitter, affichant une page de réussite.

Paramètres

Tout d’abord, nous devons définir le répertoire source. Nous avons besoin d'un répertoire lib 目录来存放我们的 PHP 库(类)文件,一个 tmp 目录来保存临时文件(这需要服务器可写),一个 css 目录来存放我们的样式表,以及一个 img pour toutes les images.

Votre arborescence de répertoires devrait ressembler à ceci :

  • Tutoriel
    • CSS
    • Photos
    • lib
    • tmp (inscriptible)

Enregistrez votre candidature

Pour utiliser OAuth, vous avez besoin de ce qu'on appelle une clé client et un secret pour identifier votre application. Pour obtenir ces informations, vous devez suivre les étapes ci-dessous pour enregistrer votre application sur Twitter.

Rendez-vous sur la page d'inscription et connectez-vous si nécessaire. Vous verrez un formulaire comme celui-ci :

构建 Twitter OAuth 应用程序Créer une application Twitter OAuth构建 Twitter OAuth 应用程序

Remplissez le formulaire avec les détails liés à votre candidature. Dans notre cas, le type d'application est navigateur et nous devons définir l'URL de rappel par défaut. L'URL peut être n'importe quoi, à condition qu'elle soit dans un format valide. Nous allons réécrire le rappel dans le code afin que peu importe s'il s'agit d'une véritable URL. Pour plus de commodité, le type d'accès par défaut doit être lecture et écriture.

Après vous être inscrit et accepté les conditions, vous verrez des informations sur votre nouvelle candidature. Les détails importants dont nous avons besoin sont la Consumer Key et le Consumer Secret, qui devraient ressembler à ceci :

构建 Twitter OAuth 应用程序Créer une application Twitter OAuth构建 Twitter OAuth 应用程序

Téléchargez la bibliothèque tmhOAuth

Nous exploiterons une bibliothèque pour gérer tous les détails des requêtes OAuth. Dans ce didacticiel, nous utiliserons la bibliothèque tmhOAuth de @themattharris, qui prend en charge le téléchargement de fichiers.

  1. Téléchargez tmhOAuth depuis GitHub
  2. Extraire tmhOAuth.php vers le répertoire lib
  3. que nous avons créé précédemment

Authentification

L'authentification avec OAuth est essentiellement un processus en trois étapes. Pour une explication plus approfondie, consultez la page Twitter sur l'authentification, mais voici un résumé :

  1. L'application obtient un jeton de demande : la première étape consiste pour notre application à s'identifier sur Twitter (à l'aide de sa clé de consommateur) et à obtenir un jeton de demande. Nous devons enregistrer ce jeton de demande pour une utilisation ultérieure.
  2. L'utilisateur autorise l'application sur Twitter : l'utilisateur doit maintenant être envoyé sur Twitter pour accorder à notre application l'accès à son compte. L'utilisateur sera alors renvoyé vers l'URL de rappel spécifiée par l'application.
  3. L'application échange le jeton de demande contre un jeton d'accès : maintenant que notre application est approuvée, elle peut échanger le jeton de demande de l'étape 1 contre un jeton d'accès. Après avoir obtenu le jeton d'accès, notre application peut interagir librement avec l'API Twitter au nom de l'utilisateur.

Alors commençons à écrire du code. Nous allons démarrer le code suivant dans un nouveau fichier nommé TwitterApp 的类中处理所有身份验证任务。在名为 lib/TwitterApp.php :

<?php
class TwitterApp {
    /**
     * This variable holds the tmhOAuth object used throughout the class
     *
     * @var tmhOAuth An object of the tmhOAuth class
     */
    public $tmhOAuth;

    /**
     * User's Twitter account data
     *
     * @var array Information on the current authenticated user
     */
    public $userdata;

    /**
     * Authentication state
     *
     * Values:
     *  - 0: not authed
     *  - 1: Request token obtained
     *  - 2: Access token obtained (authed)
     *
     * @var int The current state of authentication
     */
    protected $state;

    /**
     * Initialize a new TwitterApp object
     *
     * @param tmhOAuth $tmhOAuth A tmhOAuth object with consumer key and secret
     */
    public function  __construct(tmhOAuth $tmhOAuth) {
        
        // save the tmhOAuth object
        $this->tmhOAuth = $tmhOAuth;
    }
}
Copier après la connexion

Ici, nous créons trois propriétés et un constructeur simple. $tmhOAuth 属性将是一个 tmhOAuth 对象,它将在整个类中使用。 $userdata 属性将保存一个包含用户信息的对象,例如他们的 Twitter 用户名和状态。 $state Propriété suivant le statut d'authentification actuel.

Le constructeur

accepte simplement un objet tmhOAuth et l'assigne à la propriété $tmhOAuth.


Étape 1 : Obtenez un jeton de demande

Voici comment obtenir un jeton de demande :

/**
 * Obtain a request token from Twitter
 *
 * @return bool False if request failed
 */
private function getRequestToken() {
    
    // send request for a request token
    $this->tmhOAuth->request("POST", $this->tmhOAuth->url("oauth/request_token", ""), array(
        // pass a variable to set the callback
        'oauth_callback'    => $this->tmhOAuth->php_self()
    ));

    if($this->tmhOAuth->response["code"] == 200) {
        
        // get and store the request token
        $response = $this->tmhOAuth->extract_params($this->tmhOAuth->response["response"]);
        $_SESSION["authtoken"] = $response["oauth_token"];
        $_SESSION["authsecret"] = $response["oauth_token_secret"];

        // state is now 1
        $_SESSION["authstate"] = 1;

        // redirect the user to Twitter to authorize
        $url = $this->tmhOAuth->url("oauth/authorize", "") . '?oauth_token=' . $response["oauth_token"];
        header("Location: ' . $url);
        exit;
    }
    return false;
}
Copier après la connexion

Pour comprendre la première partie, vous devez comprendre la méthode tmhOAuth::request(). Cette méthode nous permet de faire une requête HTTP compatible OAuth et peut être utilisée comme suit :

tmhOAuth::request($method, $url[, $params[, $useauth[, $multipart]]])

  • string $method - La méthode de requête à utiliser (GET, POST, etc.)
  • string $url - URL à visiter
  • array $params (facultatif) - Tableau associatif de paramètres à inclure dans la requête
  • bool $useauth (facultatif, vrai par défaut) - L'authentification est-elle requise ?
  • bool $multipart (facultatif, false par défaut) - le téléchargement de fichier est défini sur true

Pour la méthode $url 参数,我们使用 tmhOAuth::url(), crée une URL basée sur la méthode API que nous avons appelée :

tmhOAuth::url($request[, $format])

  • string $request - méthodes API (sans extension)
  • string $format (facultatif, 'json' par défaut") - le format de réponse souhaité (JSON, XML, etc.)

Maintenant que vous connaissez les méthodes, nous devons faire une requête POST à ​​la méthode API oauth/request_token. Cela renverra les données OAuth dans un format spécial, donc lorsque nous utiliserons la méthode tmhOAuth::url() 方法时,需要将格式设置为空白。我们还需要传递一个名为 oauth_callback 的变量,这是用户在 Twitter 授权后将返回的位置。我们将使用 tmhOAuth::php_self() pour référencer la page actuelle. Voici le code :

// send request for a request token
$this->tmhOAuth->request("POST", $this->tmhOAuth->url("oauth/request_token", ""), array(
    // pass a variable to set the callback
    'oauth_callback'    => $this->tmhOAuth->php_self()
));
Copier après la connexion

Une fois la demande effectuée, la réponse est stockée dans l'attribut tmhOAuth::response sous forme de tableau contenant les données clés suivantes :

  • code - Code de réponse HTTP
  • response - données réelles renvoyées
  • headers - En-têtes de réponse

Donc, la partie suivante de notre code vérifie le code de réponse (200 pour succès) puis transmet la variable de session oauth_tokenoauth_token_secret 放入会话变量中,因为稍后我们将需要它们。这些是使用 tmhOAuth::extract_params() 方法从响应数据中提取的,该方法返回响应中包含的数据数组。我们还设置了 authstate que nous avons reçue pour indiquer que nous sommes dans la prochaine étape d'authentification. Voici le code :

if($this->tmhOAuth->response["code"] == 200) {

    // get and store the request token
    $response = $this->tmhOAuth->extract_params($this->tmhOAuth->response["response"]);
    $_SESSION["authtoken"] = $response["oauth_token"];
    $_SESSION["authsecret"] = $response["oauth_token_secret"];

    // state is now 1
    $_SESSION["authstate"] = 1;
}
Copier après la connexion

Ceci fait, nous devons maintenant rediriger l'utilisateur vers l'URL oauth/authorize, en incluant le oauth_token dans les paramètres GET. Voici le code :

// redirect the user to Twitter to authorize
$url = $this->tmhOAuth->url("oauth/authorize", "") . '?oauth_token=' . $response["oauth_token"];
header("Location: ' . $url);
exit;
Copier après la connexion

Étape 2 : Obtenir le jeton d'accès

Voici comment échanger un jeton de demande contre un jeton d'accès :

/**
 * Obtain an access token from Twitter
 *
 * @return bool False if request failed
 */
private function getAccessToken() {

    // set the request token and secret we have stored
    $this->tmhOAuth->config["user_token"] = $_SESSION["authtoken"];
    $this->tmhOAuth->config["user_secret"] = $_SESSION["authsecret"];

    // send request for an access token
    $this->tmhOAuth->request("POST", $this->tmhOAuth->url("oauth/access_token", ""), array(
        // pass the oauth_verifier received from Twitter
        'oauth_verifier'    => $_GET["oauth_verifier"]
    ));

    if($this->tmhOAuth->response["code"] == 200) {

        // get the access token and store it in a cookie
        $response = $this->tmhOAuth->extract_params($this->tmhOAuth->response["response"]);
        setcookie("access_token", $response["oauth_token"], time()+3600*24*30);
        setcookie("access_token_secret", $response["oauth_token_secret"], time()+3600*24*30);

        // state is now 2
        $_SESSION["authstate"] = 2;

        // redirect user to clear leftover GET variables
        header("Location: ' . $this->tmhOAuth->php_self());
        exit;
    }
    return false;
}
Copier après la connexion

La première chose que nous devons faire est de définir tmhOAuth::config 数组中的 user_tokenuser_secret le jeton de requête que nous avons obtenu plus tôt.

// set the request token and secret we have stored
$this->tmhOAuth->config["user_token"] = $_SESSION["authtoken"];
$this->tmhOAuth->config["user_secret"] = $_SESSION["authsecret"];
Copier après la connexion

La partie suivante est celle où nous faisons la requête POST à ​​oauth/access_token. Nous passons le oauth_verifier que nous avons reçu dans la variable GET en paramètre dans cette requête.

// send request for an access token
$this->tmhOAuth->request("POST", $this->tmhOAuth->url("oauth/access_token", ""), array(
    // pass the oauth_verifier received from Twitter
    'oauth_verifier'    => $_GET["oauth_verifier"]
));
Copier après la connexion

Twitter répondra avec le jeton d'accès et le secret, nous devons conserver ces jetons pour les demandes futures. Ainsi, le morceau de code suivant les prend et enregistre chaque contenu dans un cookie, puis définit l'état sur 2.

if($this->tmhOAuth->response["code"] == 200) {

    // get the access token and store it in a cookie
    $response = $this->tmhOAuth->extract_params($this->tmhOAuth->response["response"]);
    setcookie("access_token", $response["oauth_token"], time()+3600*24*30);
    setcookie("access_token_secret", $response["oauth_token_secret"], time()+3600*24*30);

    // state is now 2
    $_SESSION["authstate"] = 2;

    // redirect user to clear leftover GET variables
    header("Location: ' . $this->tmhOAuth->php_self());
    exit;
}
Copier après la connexion

La redirection finale consiste à effacer les paramètres d'URL laissés par Twitter et à permettre au cookie de prendre effet.


Étape 3 : Vérifier le jeton d'accès

Après avoir obtenu le jeton d'accès, nous devons vérifier qu'il est valide. Voici comment procéder :

/**
 * Verify the validity of our access token
 *
 * @return bool Access token verified
 */
private function verifyAccessToken() {
    $this->tmhOAuth->config["user_token"] = $_COOKIE["access_token"];
    $this->tmhOAuth->config["user_secret"] = $_COOKIE["access_token_secret"];

    // send verification request to test access key
    $this->tmhOAuth->request("GET", $this->tmhOAuth->url("1/account/verify_credentials"));

    // store the user data returned from the API
    $this->userdata = json_decode($this->tmhOAuth->response["response"]);

    // HTTP 200 means we were successful
    return ($this->tmhOAuth->response["code"] == 200);
}
Copier après la connexion

Ce code devrait vous sembler familier maintenant. Tout ce que nous faisons ici est de configurer user_tokenuser_secret et de faire une demande GET à 1/account/verify_credentials. Si Twitter répond avec un code 200, le jeton d'accès est valide.

Un autre détail à noter est que nous le remplissons ici avec les données renvoyées par cette requête Twitter $userdata 属性。数据是JSON格式的,所以我们使用json_decode()en la convertissant en objet PHP. Voici à nouveau cette ligne :

// store the user data returned from the API
$this->userdata = json_decode($this->tmhOAuth->response["response"]);
Copier après la connexion

Étape 4 : Regroupez le tout

Une fois nos composants OAuth en place, il est temps de tout rassembler. Nous avons besoin d'une méthode publique pour permettre à notre code client de lancer le processus d'authentification, comme ceci :

/**
 * Authenticate user with Twitter
 *
 * @return bool Authentication successful
 */
public function auth() {

    // state 1 requires a GET variable to exist
    if($this->state == 1 && !isset($_GET["oauth_verifier"])) {
        $this->state = 0;
    }

    // Step 1: Get a request token
    if($this->state == 0) {
        return $this->getRequestToken();
    }
    // Step 2: Get an access token
    elseif($this->state == 1) {
        return $this->getAccessToken();
    }

    // Step 3: Verify the access token
    return $this->verifyAccessToken();
}
Copier après la connexion

大多数 auth() 方法应该是不言自明的。根据状态,它执行该阶段的身份验证的适当方法。如果状态为 1,则 oauth_verifier GET 变量应该存在,因此该方法也会检查该变量。

我们现在应该创建一个公共方法来确定我们是否通过了身份验证。如果状态为 2,则 isAuthed() 方法返回 true:

/**
 * Check the current state of authentication
 *
 * @return bool True if state is 2 (authenticated)
 */
public function isAuthed() {
    return $this->state == 2;
}
Copier après la connexion

我们还可以使用一种方法来删除用户的身份验证。此 endSession() 方法将状态设置为 0 并删除包含访问令牌的 cookie:

/**
 * Remove user's access token cookies
 */
public function endSession() {
    $this->state = 0;
    $_SESSION["authstate"] = 0;
    setcookie("access_token", "", 0);
    setcookie("access_token_secret", "", 0);
}
Copier après la connexion

初始化

现在我们需要向 __construct() 方法添加一些内容,以确定应用程序在初始化时处于哪种身份验证状态。另外,由于我们的代码使用会话变量,因此我们应该确保会话是使用以下代码启动的:

// start a session if one does not exist
if(!session_id()) {
    session_start();
}
Copier après la connexion

下一部分是我们确定状态的地方。状态从0开始;如果设置了包含访问令牌的 cookie,则状态假定为 2;如果失败,状态将设置为 authstate 会话变量(如果存在)。这是代码:

// determine the authentication status
// default to 0
$this->state = 0;
// 2 (authenticated) if the cookies are set
if(isset($_COOKIE["access_token"], $_COOKIE["access_token_secret"])) {
    $this->state = 2;
}
// otherwise use value stored in session
elseif(isset($_SESSION["authstate"])) {
    $this->state = (int)$_SESSION["authstate"];
}
Copier après la connexion

如果状态为 1,则表示我们正在进行身份验证。所以我们现在可以继续这个过程:

// if we are in the process of authentication we continue
if($this->state == 1) {
    $this->auth();
}
Copier après la connexion

如果状态为2,我们应该验证访问令牌。如果身份验证失败,此代码将清除 cookie 并重置状态:

// verify authentication, clearing cookies if it fails
elseif($this->state == 2 && !$this->auth()) {
    $this->endSession();
}
Copier après la connexion

这是进行了这些更改的新构造函数:

/**
 * Initialize a new TwitterApp object
 *
 * @param tmhOAuth $tmhOAuth A tmhOAuth object with consumer key and secret
 */
public function  __construct(tmhOAuth $tmhOAuth) {

    // save the tmhOAuth object
    $this->tmhOAuth = $tmhOAuth;

    // start a session if one does not exist
    if(!session_id()) {
        session_start();
    }

    // determine the authentication status
    // default to 0
    $this->state = 0;
    // 2 (authenticated) if the cookies are set
    if(isset($_COOKIE["access_token"], $_COOKIE["access_token_secret"])) {
        $this->state = 2;
    }
    // otherwise use value stored in session
    elseif(isset($_SESSION["authstate"])) {
    $this->state = (int)$_SESSION["authstate"];
    }

    // if we are in the process of authentication we continue
    if($this->state == 1) {
        $this->auth();
    }
    // verify authentication, clearing cookies if it fails
    elseif($this->state == 2 && !$this->auth()) {
        $this->endSession();
    }
}
Copier après la connexion

发送推文

现在所有授权代码都已完成,我们可以向我们的类添加一些常用功能。以下是通过 Twitter API 发送推文的方法:

/**
 * Send a tweet on the user's behalf
 *
 * @param string $text Text to tweet
 * @return bool Tweet successfully sent
 */
public function sendTweet($text) {

    // limit the string to 140 characters
    $text = substr($text, 0, 140);

    // POST the text to the statuses/update method
    $this->tmhOAuth->request("POST", $this->tmhOAuth->url("1/statuses/update"), array(
        'status' => $text
    ));

    return ($this->tmhOAuth->response["code"] == 200);
}
Copier après la connexion

sendTweet() 方法接受一个字符串,将其限制为 140 个字符,然后在 POST 请求中将其发送到 1/statuses/update。这种模式现在应该非常熟悉了。


完整的 TwitterApp 类

<?php
class TwitterApp {
    
    /**
     * This variable holds the tmhOAuth object used throughout the class
     *
     * @var tmhOAuth An object of the tmhOAuth class
     */
    public $tmhOAuth;

    /**
     * User's Twitter account data
     *
     * @var array Information on the current authenticated user
     */
    public $userdata;

    /**
     * Authentication state
     *
     * Values:
     *  - 0: not authed
     *  - 1: Request token obtained
     *  - 2: Access token obtained (authed)
     *
     * @var int The current state of authentication
     */
    protected $state;

    /**
     * Initialize a new TwitterApp object
     *
     * @param tmhOAuth $tmhOAuth A tmhOAuth object with consumer key and secret
     */
    public function  __construct(tmhOAuth $tmhOAuth) {
        
        // save the tmhOAuth object
        $this->tmhOAuth = $tmhOAuth;

        // start a session if one does not exist
        if(!session_id()) {
            session_start();
        }
        
        // determine the authentication status
        // default to 0
        $this->state = 0;
        // 2 (authenticated) if the cookies are set
        if(isset($_COOKIE["access_token"], $_COOKIE["access_token_secret"])) {
            $this->state = 2;
        }
        // otherwise use value stored in session
        elseif(isset($_SESSION["authstate"])) {
            $this->state = (int)$_SESSION["authstate"];
        }
        
        // if we are in the process of authentication we continue
        if($this->state == 1) {
            $this->auth();
        }
        // verify authentication, clearing cookies if it fails
        elseif($this->state == 2 && !$this->auth()) {
            $this->endSession();
        }
    }

    /**
     * Authenticate user with Twitter
     *
     * @return bool Authentication successful
     */
    public function auth() {
        
        // state 1 requires a GET variable to exist
        if($this->state == 1 && !isset($_GET["oauth_verifier"])) {
            $this->state = 0;
        }

        // Step 1: Get a request token
        if($this->state == 0) {
            return $this->getRequestToken();
        }
        // Step 2: Get an access token

        elseif($this->state == 1) {
            return $this->getAccessToken();
        }

        // Step 3: Verify the access token
        return $this->verifyAccessToken();
    }

    /**
     * Obtain a request token from Twitter
     *
     * @return bool False if request failed
     */
    private function getRequestToken() {
        
        // send request for a request token
        $this->tmhOAuth->request("POST", $this->tmhOAuth->url("oauth/request_token", ""), array(
            // pass a variable to set the callback
            'oauth_callback'    => $this->tmhOAuth->php_self()
        ));

        if($this->tmhOAuth->response["code"] == 200) {
            
            // get and store the request token
            $response = $this->tmhOAuth->extract_params($this->tmhOAuth->response["response"]);
            $_SESSION["authtoken"] = $response["oauth_token"];
            $_SESSION["authsecret"] = $response["oauth_token_secret"];

            // state is now 1
            $_SESSION["authstate"] = 1;

            // redirect the user to Twitter to authorize
            $url = $this->tmhOAuth->url("oauth/authorize", "") . '?oauth_token=' . $response["oauth_token"];
            header("Location: ' . $url);
            exit;
        }
        return false;
    }

    /**
     * Obtain an access token from Twitter
     *
     * @return bool False if request failed
     */
    private function getAccessToken() {
        
        // set the request token and secret we have stored
        $this->tmhOAuth->config["user_token"] = $_SESSION["authtoken"];
        $this->tmhOAuth->config["user_secret"] = $_SESSION["authsecret"];

        // send request for an access token
        $this->tmhOAuth->request("POST", $this->tmhOAuth->url("oauth/access_token", ""), array(
            // pass the oauth_verifier received from Twitter
            'oauth_verifier'    => $_GET["oauth_verifier"]
        ));

        if($this->tmhOAuth->response["code"] == 200) {

            // get the access token and store it in a cookie
            $response = $this->tmhOAuth->extract_params($this->tmhOAuth->response["response"]);
            setcookie("access_token", $response["oauth_token"], time()+3600*24*30);
            setcookie("access_token_secret", $response["oauth_token_secret"], time()+3600*24*30);

            // state is now 2
            $_SESSION["authstate"] = 2;

            // redirect user to clear leftover GET variables
            header("Location: ' . $this->tmhOAuth->php_self());
            exit;
        }
        return false;
    }

    /**
     * Verify the validity of our access token
     *
     * @return bool Access token verified
     */
    private function verifyAccessToken() {
        $this->tmhOAuth->config["user_token"] = $_COOKIE["access_token"];
        $this->tmhOAuth->config["user_secret"] = $_COOKIE["access_token_secret"];

        // send verification request to test access key
        $this->tmhOAuth->request("GET", $this->tmhOAuth->url("1/account/verify_credentials"));

        // store the user data returned from the API
        $this->userdata = json_decode($this->tmhOAuth->response["response"]);

        // HTTP 200 means we were successful
        return ($this->tmhOAuth->response["code"] == 200);
    }

    /**
     * Check the current state of authentication
     *
     * @return bool True if state is 2 (authenticated)
     */
    public function isAuthed() {
        return $this->state == 2;
    }

    /**
     * Remove user's access token cookies
     */
    public function endSession() {
        $this->state = 0;
        $_SESSION["authstate"] = 0;
        setcookie("access_token", "", 0);
        setcookie("access_token_secret", "", 0);
    }
    
    /**
     * Send a tweet on the user's behalf
     *
     * @param string $text Text to tweet
     * @return bool Tweet successfully sent
     */
    public function sendTweet($text) {

        // limit the string to 140 characters
        $text = substr($text, 0, 140);

        // POST the text to the statuses/update method
        $this->tmhOAuth->request("POST", $this->tmhOAuth->url("1/statuses/update"), array(
            'status' => $text
        ));
        
        return ($this->tmhOAuth->response["code"] == 200);
    }
}
Copier après la connexion

我们的应用

现在我们有了一个处理所有 OAuth 任务的类,我们现在可以使用特定于我们的应用程序的功能来扩展它。这包括获取、更改和设置用户头像的能力。

我们将使用 TwitterAvatars 类扩展 TwitterApp 类。在名为 lib/TwitterAvatars.php 的新文件中开始以下代码:

<?php
class TwitterAvatars extends TwitterApp {
    
    /**
     * The path to our temporary files directory
     *
     * @var string Path to store image files
     */
    public $path;
    
    /**
     * These are all the GD image filters available in this class
     *
     * @var array Associative array of image filters
     */
    protected $filters = array(
        'grayscale'     => IMG_FILTER_GRAYSCALE,
        'negative'      => IMG_FILTER_NEGATE,
        'edgedetect'    => IMG_FILTER_EDGEDETECT,
        'embossed'      => IMG_FILTER_EMBOSS,
        'blurry'        => IMG_FILTER_GAUSSIAN_BLUR,
        'sketchy'       => IMG_FILTER_MEAN_REMOVAL
    );
    
    /**
     * Initialize a new TwitterAvatars object
     *
     * @param tmhOAuth $tmhOAuth A tmhOAuth object with consumer key and secret
     * @param string $path Path to store image files (default 'tmp")
     */
    public function  __construct(tmhOAuth $tmhOAuth, $path = 'tmp") {
        
        // call the parent class' constructor
        parent::__construct($tmhOAuth);

        // save the path variable
        $this->path = $path;
    }
}
Copier après la connexion

正如你所看到的,扩展类包括一个 $path 属性,用于指向临时图像文件的位置,一个 $filters 属性,保存图像过滤器数组,以及一个带有要设置的参数的扩展构造函数路径。由于我们要重写原始构造函数,因此必须使用 parent::__construct() 显式调用父级构造函数。

现在我们可以开始添加我们的方法了。


下载

显然,我们需要能够下载图像才能操作它们。这是一个通用的 download() 方法,它接受 URL 并返回该位置的数据。该方法发出基本的 cURL 请求。

/**
 * Download data from specified URL
 *
 * @param string $url URL to download
 * @return string Downloaded data
 */
protected function download($url) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    $ret = curl_exec($ch);
    curl_close($ch);

    return $ret;
}
Copier après la connexion

查找 URL

现在我们可以下载文件了,我们需要找到所需文件的位置。我们感兴趣的是两种不同的图像,标准尺寸的缩略图和原始的全尺寸图像。因此,我们将创建一个方法来获取每个 URL。

为了获取标准尺寸的缩略图,我们将调用 users/profile_image/:screen_name API 方法,该方法通过 302 重定向响应指定用户的头像图像。这意味着 URL 将在 Location 标头中找到。这是该方法:

/**
 * Get the URL to the standard sized avatar
 *
 * @return string The URL to the image file
 */
protected function getImageURL() {

    // request user's 'bigger' profile image
    $this->tmhOAuth->request("GET", $this->tmhOAuth->url("1/users/profile_image/" . $this->userdata->screen_name), array(
        'screen_name'   => $this->userdata->screen_name,
        'size'          => 'bigger'
    ));

    if($this->tmhOAuth->response["code"] == 302) {

        // the direct URL is in the Location header
        return $this->tmhOAuth->response["headers"]["location"];
    }
    throw new Exception("Error locating image");
}
Copier après la connexion

请注意,我们正在使用 tmhOAuth 发出 GET 请求,传递 screen_namesize 参数,然后返回 Location 标头的内容。

没有 API 方法可以获取完整尺寸的图像,因此对于下一个方法,我们将稍微作弊并编辑 URL。用户数据包含一个 profile_image_url 字段,该字段指向 avatar_normal.jpg 之类的内容,并且可以在 avatar.jpg 中找到不带后缀的原始图像。所以这个方法获取URL,去掉尺寸后缀并返回修改后的URL:

/**
 * Get the URL to the full sized avatar
 *
 * @return string The URL to the image file
 */
protected function getCréer une application Twitter OAuthImageURL() {

    // get the regular sized avatar
    $url = $this->userdata->profile_image_url;

    // save the extension for later
    $ext = strrchr($url, '.");

    // strip the "_normal' suffix and add back the extension
    return substr($url, 0, strrpos($url, "_")) . $ext;
}
Copier après la connexion

读取图像

现在我们可以找到并下载图像,我们需要一种方法来读取它们。我们将使用 GD 库来操作图像,因此此方法会将原始图像数据转换为 GD 图像资源。

/**
 * Convert raw image data to a GD resource
 *
 * @param string $data Binary image data to parse
 * @return resource A GD image resource identifier
 */
protected function readImage($data) {

    // read in the original image
    $src = imagecreatefromstring($data);

    if(!$src) {
        throw new Exception("Error reading image");
    }

    // get the dimensions
    $width = imagesx($src);
    $height = imagesy($src);

    // create a blank true color image of the same size
    $img = imagecreatetruecolor($width, $height);

    // copy the original image to this new canvas
    imagecopy($img, $src, 0, 0, 0, 0, $width, $height);

    // discard the source image
    imagedestroy($src);

    return $img;
}
Copier après la connexion

描述上面发生的事情:

  1. 使用 imagecreatefromstring() 函数将图像数据转换为 GD 资源。
  2. 使用 imagesx()imagesy() 记录图像尺寸。
  3. 使用 imagecreatetruecolor() 创建具有相同尺寸的新空白真彩色图像。
  4. 使用 imagecopy() 函数将原始图像复制到新图像中。无论原始颜色模式如何,这都会产生原始图像的真彩色版本。
  5. 使用 imagedestroy() 销毁原始图像资源,并返回新图像的句柄。

保存图像

现在我们可以下载图像并创建 GD 资源,我们需要一种将图像保存到文件系统的方法。以下是使用 imagepng() 将提供的图像保存为具有指定名称的 PNG 文件的方法:

/**
 * Save a GD image resource to a PNG file
 *
 * @param resource $img GD image resource identifier
 * @param string $name Name of the image
 * @return string Path to the saved image
 */
protected function saveImage($img, $name) {
    $path = $this->path . "/' . $name . '.png';
    imagepng($img, $path);
    imagedestroy($img);
    return $path;
}
Copier après la connexion

生成预览

现在我们已经拥有了为我们的应用程序提供支持的所有部分,我们可以开始将它们组合在一起。在我们的应用程序流程中,我们将为用户提供可供选择的预览选项。以下是生成这些预览的方法:

/**
 * Generate previews for each image filter
 *
 * @return array Associative array of image previews
 */
public function generatePreviews() {

    // we need valid user info to know whose avatar to handle
    if(!$this->isAuthed()) {
        throw new Exception("Requires oauth authorization");
    }
    $username = $this->userdata->screen_name;

    // cache the raw data to use
    $data = $this->download($this->getImageURL());

    // copy the original image
    $img = $this->readImage($data);
    $this->saveImage($img, $username . "_orig");

    // array to hold the list of previews
    $images = array();

    // loop through each filter to generate previews
    foreach($this->filters as $filter_name => $filter) {
        $img = $this->readImage($data);
        imagefilter($img, $filter);
        $images[$filter_name] = $this->saveImage($img, $username . "_' . $filter_name);
    }

    return $images;
}
Copier après la connexion

我们要做的第一件事是检查用户是否已通过身份验证,然后获取用户名以便稍后在文件名中使用。

// we need valid user info to know whose avatar to handle
if(!$this->isAuthed()) {
    throw new Exception("Requires oauth authorization");
}
$username = $this->userdata->screen_name;
Copier après la connexion

然后我们使用我们创建的 getImageURL()download() 方法下载用户的图像。该数据将在每次预览中重复使用,因此我们将其保存在 $data 变量中。

// cache the raw data to use
$data = $this->download($this->getImageURL());
Copier après la connexion

接下来,我们使用 _orig 后缀保存未修改的副本。这是为了稍后进行视觉比较。

// copy the original image
$img = $this->readImage($data);
$this->saveImage($img, $username . "_orig");
Copier après la connexion

该方法的最后一部分是我们循环遍历 $filters 属性中列出的图像过滤器,为每个过滤器生成一个图像。在每次迭代中,我们创建一个图像并应用 imagefilter() 函数,该函数接受我们在 $filters 数组中列出的常量之一。然后,对于我们保存的每个图像,我们将其路径添加到该方法最后返回的关联数组(使用过滤器名称作为键)。

// array to hold the list of previews
$images = array();

// loop through each filter to generate previews
foreach($this->filters as $filter_name => $filter) {
    $img = $this->readImage($data);
    imagefilter($img, $filter);
    $images[$filter_name] = $this->saveImage($img, $username . "_' . $filter_name);
}

return $images;
Copier après la connexion

我们的应用程序流程的下一部分要求用户确认他们的选择,因此我们需要一种方法来查找特定的预览。下面是根据作为参数传递的选项获取图像路径的简单方法,默认为原始图像:

/**
 * Get the path to a previously generated preview
 *
 * @param string $filter The image filter to get the preview for
 * @return string The path to the preview file or null if not found
 */
public function getPreview($filter = 'orig") {
    if(!$this->isAuthed()) {
        throw new Exception("Requires oauth authorization");
    }
    $path = $this->path . "/' . $this->userdata->screen_name . "_' . $filter . '.png';
    if(file_exists($path)) {
        return $path;
    }
    return null;
}
Copier après la connexion

更改头像

我们的应用程序流程的最后阶段是实际更改用户的头像。首先,我们需要一种方法来获取全尺寸图像并对其应用特定的滤镜。这是:

/**
 * Process the user's full avatar using one of the filters
 *
 * @param string $filter The filter to apply to the image
 * @return string Path to the output file
 */
protected function processImage($filter = "grayscale") {

    // make sure the filter exists
    $filter = strtolower($filter);
    if(!array_key_exists($filter, $this->filters)) {
        throw new Exception("Unsupported image filter");
    }

    $username = $this->userdata->screen_name;

    // get the full sized avatar
    $data = $this->download($this->getCréer une application Twitter OAuthImageURL());
    $img = $this->readImage($data);

    // apply the filter to the image
    imagefilter($img, $this->filters[$filter]);

    // save the image and return the path
    return $this->saveImage($img, $username . "_' . $filter . "_full");
}
Copier après la connexion

这应该很容易理解,因为它与 generatePreviews() 方法非常相似。它接受一个参数来指定图像过滤器并检查它是否存在。然后它下载原始图像并对其应用过滤器,将生成图像的路径作为返回值传回。

现在我们需要将生成的图像实际发送到 Twitter 的方法,以更新用户的头像。该方法调用 processImage() 方法创建图像并通过 1/account/update_profile_image API 方法上传到 Twitter:

/**
 * Update user's avatar with a filtered version
 *
 * @param string $filter The filter to use
 * @return bool Operation successful
 */
public function commitAvatar($filter) {
    if(!$this->isAuthed()) {
        throw new Exception("Requires oauth authorization");
    }

    // generate the image and get the path
    $path = $this->processImage($filter);
    if(file_exists($path)) {

        // send a multipart POST request with the image file data
        $this->tmhOAuth->request("POST", $this->tmhOAuth->url("1/account/update_profile_image"), array(
            // format: @local/path.png;type=mime/type;filename=file_name.png
            'image' => '@' . $path . ';type=image/png;filename=' . basename($path)
        ), true, true);

        return ($this->tmhOAuth->response["code"] == 200);
    }

    return false;
}
Copier après la connexion

这里棘手的部分是实际的 tmhOAuth POST 请求,它是一个包含原始图像数据的多部分请求。为此,我们必须将 tmhOAuth::request() 方法的最后一个参数设置为 true,并以特殊格式传递 image 变量:

@[图像路径];type=[mime_type];filename=[file_name]

例如,如果我们要上传 tmp/username_grayscale_full.png,则值为 @tmp/username_grayscale_full.png;type=image/png;filename=username_grayscale_full.png

这又是那部分代码:

// send a multipart POST request with the image file data
$this->tmhOAuth->request("POST", $this->tmhOAuth->url("1/account/update_profile_image"), array(
    // format: @local/path.png;type=mime/type;filename=file_name.png
    'image' => '@' . $path . ';type=image/png;filename=' . basename($path)
), true, true);
Copier après la connexion

清理

所有这些文件操作的副作用是留下大量临时文件。下面是清理临时目录的方法:

/**
 * Delete leftover image files
 */
public function cleanupFiles() {

    // file to track when we last checked
    $flag = $this->path . "/.last_check';

    $time = time();

    // have we checked within the last hour?
    if(!file_exists($flag) || $time - filemtime($flag) > 3600) {

        // get an array of PNG files in the directory
        $files = glob($this->path . "/*.png");

        // loop through files, deleting old files (12+ hours)
        foreach($files as $file) {
            if($time - filemtime($file) > 60*60*12) {
                unlink($file);
            }
        }

        // update the timestamp of our flag file
        touch($flag);
    }
}
Copier après la connexion

这只是循环遍历 PNG 文件,删除那些超过 12 小时的文件。它还检查自我们使用 .last_check 文件上的时间戳进行检查以来已经过去了多长时间,从而允许我们将检查限制为每小时一次。这样我们就可以在每个请求上调用这个方法,而不会浪费资源。

注意:我们在 PHP 中使用 glob() 函数,这是获取与模式匹配的文件数组的简单方法。


完整的 TwitterAvatars 类

&?php
class TwitterAvatars extends TwitterApp {
    
    /**
     * The path to our temporary files directory
     *
     * @var string Path to store image files
     */
    public $path;
    
    /**
     * These are all the GD image filters available in this class
     *
     * @var array Associative array of image filters
     */
    protected $filters = array(
        'grayscale'     => IMG_FILTER_GRAYSCALE,
        'negative'      => IMG_FILTER_NEGATE,
        'edgedetect'    => IMG_FILTER_EDGEDETECT,
        'embossed'      => IMG_FILTER_EMBOSS,
        'blurry'        => IMG_FILTER_GAUSSIAN_BLUR,
        'sketchy'       => IMG_FILTER_MEAN_REMOVAL
    );
    
    /**
     * Initialize a new TwitterAvatars object
     *
     * @param tmhOAuth $tmhOAuth A tmhOAuth object with consumer key and secret
     * @param string $path Path to store image files (default 'tmp")
     */
    public function  __construct(tmhOAuth $tmhOAuth, $path = 'tmp") {
        
        // call the parent class' constructor
        parent::__construct($tmhOAuth);

        // save the path variable
        $this->path = $path;
    }

    /**
     * Download data from specified URL
     *
     * @param string $url URL to download
     * @return string Downloaded data
     */
    protected function download($url) {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

        $ret = curl_exec($ch);
        curl_close($ch);

        return $ret;
    }

    /**
     * Get the URL to the standard sized avatar
     *
     * @return string The URL to the image file
     */
    protected function getImageURL() {

        // request user's 'bigger' profile image
        $this->tmhOAuth->request("GET", $this->tmhOAuth->url("1/users/profile_image/' . $this->userdata->screen_name), array(
            'screen_name'   => $this->userdata->screen_name,
            'size'          => 'bigger'
        ));

        if($this->tmhOAuth->response["code"] == 302) {
            
            // the direct URL is in the Location header
            return $this->tmhOAuth->response["headers"]["location"];
        }
        throw new Exception("Error locating image");
    }

    /**
     * Get the URL to the full sized avatar
     *
     * @return string The URL to the image file

     */
    protected function getCréer une application Twitter OAuthImageURL() {

        // get the regular sized avatar
        $url = $this->userdata->profile_image_url;

        // save the extension for later
        $ext = strrchr($url, '.");

        // strip the "_normal' suffix and add back the extension
        return substr($url, 0, strrpos($url, "_")) . $ext;
    }

    /**
     * Convert raw image data to a GD resource
     *
     * @param string $data Binary image data to parse
     * @return resource A GD image resource identifier
     */
    protected function readImage($data) {

        // read in the original image
        $src = imagecreatefromstring($data);

        if(!$src) {
            throw new Exception("Error reading image");
        }

        // get the dimensions
        $width = imagesx($src);
        $height = imagesy($src);

        // create a blank true color image of the same size
        $img = imagecreatetruecolor($width, $height);

        // copy the original image to this new canvas
        imagecopy($img, $src, 0, 0, 0, 0, $width, $height);

        // discard the source image
        imagedestroy($src);

        return $img;
    }

    /**
     * Save a GD image resource to a PNG file
     *
     * @param resource $img GD image resource identifier
     * @param string $name Name of the image
     * @return string Path to the saved image
     */
    protected function saveImage($img, $name) {
        $path = $this->path . "/' . $name . '.png';
        imagepng($img, $path);
        imagedestroy($img);
        return $path;
    }

    /**
     * Generate previews for each image filter
     *
     * @return array Associative array of image previews
     */
    public function generatePreviews() {
        
        // we need valid user info to know whose avatar to handle
        if(!$this->isAuthed()) {
            throw new Exception("Requires oauth authorization");
        }
        $username = $this->userdata->screen_name;

        // cache the raw data to use
        $data = $this->download($this->getImageURL());

        // copy the original image
        $img = $this->readImage($data);
        $this->saveImage($img, $username . "_orig");
        
        // array to hold the list of previews
        $images = array();

        // loop through each filter to generate previews
        foreach($this->filters as $filter_name => $filter) {
            $img = $this->readImage($data);
            imagefilter($img, $filter);
            $images[$filter_name] = $this->saveImage($img, $username . "_' . $filter_name);
        }

        return $images;
    }

    /**
     * Get the path to a previously generated preview
     *
     * @param string $filter The image filter to get the preview for
     * @return string The path to the preview file or null if not found
     */
    public function getPreview($filter = 'orig") {
        if(!$this->isAuthed()) {
            throw new Exception("Requires oauth authorization");
        }
        $path = $this->path . "/' . $this->userdata->screen_name . "_' . $filter . '.png';
        if(file_exists($path)) {
            return $path;
        }
        return null;
    }

    /**
     * Process the user's full avatar using one of the filters
     *
     * @param string $filter The filter to apply to the image
     * @return string Path to the output file
     */
    protected function processImage($filter = 'grayscale") {
        
        // make sure the filter exists
        $filter = strtolower($filter);
        if(!array_key_exists($filter, $this->filters)) {
            throw new Exception("Unsupported image filter");
        }

        $username = $this->userdata->screen_name;

        // get the full sized avatar
        $data = $this->download($this->getCréer une application Twitter OAuthImageURL());
        $img = $this->readImage($data);

        // apply the filter to the image
        imagefilter($img, $this->filters[$filter]);
        
        // save the image and return the path
        return $this->saveImage($img, $username . "_' . $filter . "_full");
    }

    /**
     * Update user's avatar with a filtered version
     *
     * @param string $filter The filter to use
     * @return bool Operation successful
     */
    public function commitAvatar($filter) {
        if(!$this->isAuthed()) {
            throw new Exception("Requires oauth authorization");
        }

        // generate the image and get the path
        $path = $this->processImage($filter);
        if(file_exists($path)) {

            // send a multipart POST request with the image file data
            $this->tmhOAuth->request("POST", $this->tmhOAuth->url("1/account/update_profile_image"), array(
                // format: @local/path.png;type=mime/type;filename=file_name.png
                'image' => '@' . $path . ';type=image/png;filename=' . basename($path)
            ), true, true);

            return ($this->tmhOAuth->response["code"] == 200);
        }

        return false;
    }

    /**
     * Delete leftover image files
     */
    public function cleanupFiles() {
        
        // file to track when we last checked
        $flag = $this->path . "/.last_check';

        $time = time();

        // have we checked within the last hour?
        if(!file_exists($flag) || $time - filemtime($flag) > 3600) {
            
            // get an array of PNG files in the directory
            $files = glob($this->path . "/*.png");

            // loop through files, deleting old files (12+ hours)
            foreach($files as $file) {
                if($time - filemtime($file) > 60*60*12) {
                    unlink($file);
                }
            }

            // update the timestamp of our flag file
            touch($flag);
        }
    }
}
Copier après la connexion

前端

我们将应用程序的所有组件放在一起,所以现在我们需要的只是用户界面。这里的所有代码都将进入根目录中的index.php文件。我们将首先包含库并设置配置:

<?php

// include our libraries
include 'lib/tmhOAuth.php';
include 'lib/TwitterApp.php';
include 'lib/TwitterAvatars.php';

// set the consumer key and secret
define("CONSUMER_KEY",      'qSkJum23MqlG6greF8Z76A");
define("CONSUMER_SECRET",   'Bs738r5UY2R7e5mwp1ilU0voe8OtXAtifgtZe9EhXw");
?>
Copier après la connexion

注意:请务必将 CONSUMER_KEYCONSUMER_SECRET 替换为您自己的。

我们将把代码放在 try-catch 块中,这样我们就可以优雅地处理任何错误,将它们的消息分配给 $error 变量。

try {
    
} catch(Exception $e) {

    // catch any errors that may occur
    $error = $e;
}
Copier après la connexion

在 try 块中,我们可以开始编写代码,首先使用配置的 tmhOAuth 对象初始化名为 $ta 的 TwitterAvatars 对象:

    // our tmhOAuth settings
    $config = array(
        'consumer_key'      => CONSUMER_KEY,
        'consumer_secret'   => CONSUMER_SECRET
    );

    // create a new TwitterAvatars object
    $ta = new TwitterAvatars(new tmhOAuth($config));
Copier après la connexion

此时我们可以清除所有旧的临时文件:

    // check for stale files
    $ta->cleanupFiles();
Copier après la connexion

接下来,我们检查用户是否已通过身份验证,或者如果用户未通过身份验证,则检查用户是否已请求身份验证,在这种情况下,我们通过调用 auth() 方法来启动该过程:

    // check our authentication status
    if($ta->isAuthed()) {
        
    }
    // did the user request authorization?
    elseif(isset($_POST["auth"])) {

        // start authentication process
        $ta->auth();
    }
Copier après la connexion

如果用户已通过身份验证,我们需要检查是否已选择某个选项,否则我们将生成预览:

    // check our authentication status
    if($ta->isAuthed()) {

        // has the user selected an option?
        if(isset($_POST["filter"])) {
            
        }
        // generate previews if the user has not chosen
        else {

            // $previews will be a list of images
            $previews = $ta->generatePreviews();
        }
    }
Copier après la connexion

如果选择了某个选项,我们需要获取要显示的旧图像和新图像的路径:

        // has the user selected an option?
        if(isset($_POST["filter"])) {

            // get the image paths for display
            $original = $ta->getPreview();
            $newimage = $ta->getPreview($_POST["filter"]);
        }
Copier après la connexion

最后,我们检查用户是否确认了他们的选择并应用更改。如果需要,我们还会发送一条推文,并将 $success 变量设置为 true:

        // has the user selected an option?
        if(isset($_POST["filter"])) {

            // is the user sure?
            if(isset($_POST["confirm"])) {

                // change the user's avatar
                $ta->commitAvatar($_POST["filter"]);

                // tweet if the user chose to
                if(isset($_POST["tweet"])) {
                    $ta->sendTweet("I just updated my avatar using Avatar Effects...");
                }

                $success = true;
            }

            // get the image paths for display
            $original = $ta->getPreview();
            $newimage = $ta->getPreview($_POST["filter"]);
        }
Copier après la connexion

这是我们迄今为止所拥有的:

isAuthed()) {

        // has the user selected an option?
        if(isset($_POST["filter"])) {

            // is the user sure?
            if(isset($_POST["confirm"])) {

                // change the user's avatar
                $ta->commitAvatar($_POST["filter"]);

                // tweet if the user chose to
                if(isset($_POST["tweet"])) {
                    $ta->sendTweet("I just updated my avatar using Avatar Effects...");
                }

                $success = true;
            }

            // get the image paths for display
            $original = $ta->getPreview();
            $newimage = $ta->getPreview($_POST["filter"]);
        }
        // generate previews if the user has not chosen
        else {

            // $previews will be a list of images
            $previews = $ta->generatePreviews();
        }
    }
    // did the user request authorization?
    elseif(isset($_POST["auth"])) {

        // start authentication process
        $ta->auth();
    }
} catch(Exception $e) {

    // catch any errors that may occur
    $error = $e;
}
?>
Copier après la connexion

HTML

在 PHP 代码之后,我们将输出适当的 HTML,从这个模板开始,它设置标题和主标题:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Twitter Avatar Effects</title>
    <link rel="stylesheet" href="css/style.css">
  </head>
  <body>
      <h1>Twitter Avatar Effects</h1>
  </body>
</html>
Copier après la connexion

这里是我们显示带有每个预览的图像输入的表单的地方:

  <?php if(isset($previews)): ?>
      <h2>Choose your weapon...</h2>
      <form action="index.php" method="post">
      <?php foreach($previews as $filter => $path): ?>
          <input type="image" src="<?php echo $path; ?>"
                 alt="<?php echo ucfirst($filter); ?>"
                  width="73" height="73"
                 name="filter" value="<?php echo $filter; ?>">
      <?php endforeach; ?>
      </form>
      <p>Select one of the images above to change your Twitter avatar.</p>
Copier après la connexion

这是成功页面:

  <?php elseif(isset($success)): ?>
      <h2>Success! Your Twitter avatar is now:</h2>
      <img  src="<?php echo $newimage; ? alt="Créer une application Twitter OAuth" >" alt="Your Avatar" width="73"    style="max-width:90%">
      <p><a href="http://twitter.com/<?php echo $ta->userdata->screen_name; ?>">Go see it</a></p>
Copier après la connexion

这是确认页面,我们在其中显示比较并提供取消的机会:

  <?php elseif(isset($newimage)): ?>
      <h2>Are you sure?</h2>
      <img  src="<?php echo $original; ? alt="Créer une application Twitter OAuth" >" alt="Créer une application Twitter OAuth" width="73"    style="max-width:90%">
      <span class="arrow">&rArr;</span>
      <img  src="<?php echo $newimage; ? alt="Créer une application Twitter OAuth" >" alt="<?php echo ucfirst($_POST["filter"]); ?>">
      <form action="index.php" method="post">
          <input type="hidden" name="filter" value="<?php echo $_POST["filter"]; ?>">
          <input type="submit" name="confirm" value="Confirm">
          <a href="index.php">Cancel</a>
          <p><label>Tweet about your new avatar?
                  <input type="checkbox" name="tweet" value="true"></label></p>
      </form>
Copier après la connexion

请注意,确认表单在隐藏字段中包含所选的过滤器。

如果出现错误,我们会显示:

  <?php elseif(isset($error)): ?>
      <p>Error. <a href="index.php">Try again?</a></p>
Copier après la connexion

默认显示的是“连接到 Twitter”按钮作为图像输入(从本页底部下载一张图像到 img 目录):

  <?php else: ?>
      <form action="index.php" method="post">
          <input type="image" src="img/sign-in-with-twitter-l.png"
                 alt="Connect to Twitter" name="auth" value="1">
      </form>
      <p>Connect to Twitter to use this app.</p>
  <?php endif; ?>
Copier après la connexion

这是完整的 HTML 部分:



  
    
    Twitter Avatar Effects
    
  
  
      

Twitter Avatar Effects

<?php if(isset($previews)): ?> <h2>Choose your weapon...</h2> <form action="index.php" method="post"> <?php foreach($previews as $filter => $path): ?> <input type="image" src="<?php echo $path; ?>" alt="<?php echo ucfirst($filter); ?>" width="73" height="73" name="filter" value="<?php echo $filter; ?>"> <?php endforeach; ?> </form> <p>Select one of the images above to change your Twitter avatar.</p> <?php elseif(isset($success)): ?> <h2>Success! Your Twitter avatar is now:</h2> <img src="<?php echo $newimage; ? alt="Créer une application Twitter OAuth" >" alt="Your Avatar" width="73" style="max-width:90%"> <p><a href="http://twitter.com/<?php echo $ta->userdata->screen_name; ?>">Go see it</a></p> <?php elseif(isset($newimage)): ?> <h2>Are you sure?</h2> <img src="<?php echo $original; ? alt="Créer une application Twitter OAuth" >" alt="Créer une application Twitter OAuth" width="73" style="max-width:90%"> <span class="arrow">&rArr;</span> <img src="<?php echo $newimage; ? alt="Créer une application Twitter OAuth" >" alt="<?php echo ucfirst($_POST["filter"]); ?>"> <form action="index.php" method="post"> <input type="hidden" name="filter" value="<?php echo $_POST["filter"]; ?>"> <input type="submit" name="confirm" value="Confirm"> <a href="index.php">Cancel</a> <p><label>Tweet about your new avatar? <input type="checkbox" name="tweet" value="true"></label></p> </form> <?php elseif(isset($error)): ?> <p>Error. <a href="index.php">Try again?</a></p> <?php else: ?> <form action="index.php" method="post"> <input type="image" src="img/sign-in-with-twitter-l.png" alt="Connect to Twitter" name="auth" value="1"> </form> <p>Connect to Twitter to use this app.</p> <?php endif; ?>
Copier après la connexion

CSS

这里是一些使界面看起来更漂亮的基本 CSS,保存在 css/style.css 中:

html {
    background-color: #eee;
    text-align: center;
    font-family: "Lucida Grande",Verdana, sans-serif;
    font-size: 16px;
    color: #224;
}
body {
    width: 700px;
    margin: 30px auto;
    background-color: #acf;
    padding: 10px;
    border-radius: 10px;
    -moz-border-radius: 10px;
    -webkit-border-radius: 10px;
}
p {
    font-size: 1em;
}
h1 {
    font-size: 2em;
}
h2 {
    font-size: 1.6em;
}
.arrow {
    font-size: 4em;
    font-weight: bold;
}
Copier après la connexion

结果

这是一个视频,详细介绍了我们完成的应用程序的外观:


结论

如果您完全按照本教程进行操作,您应该对 OAuth 以及创建简单 Twitter Web 应用程序所需的内容有很好的了解。一旦您了解了基本概念,使用 Twitter API 就会很容易 - 特别是如果您使用像 tmhOAuth 这样的库来处理次要细节。

我们在本教程中创建的简单示例可以轻松修改或扩展以执行任何操作。因此,如果您对一款很酷的新 Twitter 应用程序有好主意,请随意使用它作为基础。

感谢您的阅读。如果您对本教程有任何疑问或意见,请留言!

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!