CommentOut

【PHP】DropboxAPIをPHPで使ってみる 【PHP】DropboxAPIをPHPで使ってみる

【PHP】DropboxAPIをPHPで使ってみる

公開日:  最終更新日:

私はDropbox結構前から使っていたんですが、今までWEBサービスと連携させたことはなかったです。
なので、今回DropboxにAPIを使って、PHPからアクセスしてみます。

以下の記事を参考にさせていただきました。

Dropboxアカウントを取得しましょう

Dropboxのサイトからアカウントを作成してください。
https://www.dropbox.com/ja/

DropboxのDeveloperサイトでアプリを作成しましょう

Dropboxの通常ユーザーのページとは別に、開発者用ページDBX Platformというものがあり、こちらからアプリを作成します。
https://www.dropbox.com/developers

アプリを作成といっても、ここでプログラムを組むわけではなく、API接続するために必要な情報を登録するだけです。

この画面で『アプリを作成』をクリックしてください。

1.APIを選んでください。
  → Scoped access

そう、「選んでください」と言いつつ、初めから選択肢など無いのです。
謹んでScoped accessを選択してください。

2.このアプリは、アプリの指定フォルダ内のみアクセスできるか、Dropboxアカウントの全てのフォルダにアクセスできるか、どちらにしますか?

こちらについてはセキュリティ的な観点から、『App folder』を推奨します。

3.あなたのアプリ名を入力してください。

今回、私はブラウザからアップロードした画像をPHPでDropboxに転送するプログラムを作成したかったので、「ImageTransferApp」と名前を付けました。
そうすると「利用条件に同意しなさい」というチェックボックスが表示されます。

ここでつまづきポイントですが、Google Chromeでは同意ボタンが表示されましたが、Microsoft Edgeでは同意ボタンが表示されず、ここから先に進めませんでした。
同志たちは最初からGoogle Chromeを使うようにしよう!

I agreeすると先に進めるようになるのですが、ここでもつまづきポイントがありました。
このスクリーンショット撮影時点では問題なく進めましたが、最初検証した時はI agreeをチェックしてもCreate appボタンが有効化されませんでした。
その時、アクセスタイプをApp folderとFull Dropboxを付け替えなどすると有効化されました。(その現象もEdgeで起きてたんだったかな・・・

問題なく、アプリが作成できると、上記のような画面になります。

Dropbox Appのパーミッションを設定しましょう

アプリが作成できたら、パーミッションタブを開いて、権限の設定を行います。

Permissionsタブを開きます。

とりあえず、これくらいの権限を与えておけば良かろうと思います。

Dropboxのアクセストークンを取得する

このあたりから、ややこしくなってきます。

Dropboxが提供するAPIでは、誰でも彼でも勝手にAPIを利用できるわけではなく、APIを利用するために、アクセストークンを取得する必要があります
このアクセストークンがアプリの識別であり、どのDropboxアカウントに紐づいているかを表す記号でもあります。

以前は永続的アクセストークンが提供されていたようですが、現在は一時的なアクセストークンを毎回取得する必要があるようです。

一時的なアクセストークンの取得にはいくつかの手順があります。

上記手順は最初に1回実行したら、OKです。
そして、上記の手順で取得したApp Key、App Secret、リフレッシュトークンの3つを使って、一時アクセストークンを生成します。
一時アクセストークンは毎回取得する必要があります。

認証コードの取得

認証コードの取得には以下のURLにアクセスします。

https://www.dropbox.com/oauth2/authorize?token_access_type=offline&response_type=code&client_id=[AppKey]

[AppKey]の部分は、アプリ画面内に記載されています。

このApp Keyと記載されている部分の文字列を入れてください。

URLにブラウザからアクセスすると、以下のような表示が出ます。

続行しないと先には進めないので、続行してください。

アプリにアクセス権限を与えます。

そうすると、認証コードが生成されます。
認証コードはアプリの管理画面にも表示されませんので、どこかにメモっといてください。

リフレッシュトークンを取得

このリフレッシュトークンは、一時的なアクセストークンを使い続けていると有効期限が切れてしまうので、新しい一時的トークンを再取得するために必要になるトークンだと思います。

リフレッシュトークンの取得はコンソール(コマンドプロンプトやPowerShell、ターミナル等)から操作してください。

curl https://api.dropbox.com/oauth2/token \
    -d code=[Access Code] \
    -d grant_type=authorization_code \
    -u [AppKey]:[AppSecret] \

WindowsのコマンドプロンプトやPowerShellなどで上記コマンドを実行すると、SSL認証に関する警告が出て、うまくいかないので、以下のコマンドを試してください。

curl https://api.dropbox.com/oauth2/token \
    -d code=[Access Code] \
    -d grant_type=authorization_code \
    -u [AppKey]:[AppSecret] \
    --ssl-no-revoke

コマンドプロンプトで実際にコマンドを実行してみました。

上記コマンドで取得したコードがリフレシュトークンです。
以下の画像の赤い線の部分です。

このrefresh_tokenの部分は後でプログラム内部で利用します。

ここまでで取得したApp KeyとApp Secretとリフレッシュトークンは定数などで呼び出せるようにしておいてください。

<?php
// 定数として記述しておく
const APP_KEY = '[App Key]';
const APP_SECRET = '[App Secret]';
const REFRESH_TOKEN = '[リフレッシュトークン]';

ここまでの処理は最初に1回やっておけば大丈夫です。

一時的アクセストークンを取得する

さて、DropboxAPIに接続するには、一時的なアクセストークンを発行する必要があるのですが、『一時的』なので当然すぐ有効期限が切れてしまいます。
なので、ここからの処理は定型処理として、プログラムに記述しておきます。

<?php
// 定数として記述しておく
const APP_KEY = '[App Key]';
const APP_SECRET = '[App Secret]';
const REFRESH_TOKEN = '[リフレッシュトークン]';

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// 一時的なアクセストークンを取得
private function getAccessToken() {
    $url = 'https://api.dropboxapi.com/oauth2/token';
    $data = [
        'grant_type'    => 'refresh_token',
        'refresh_token' => REFRESH_TOKEN,
        'client_id'     => APP_KEY,
        'client_secret' => APP_SECRET
    ];

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));

    $res = curl_exec($ch);
    $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

    $access_token = '';
    if (!curl_errno($ch) && $http_code == "200") {
        $res = json_decode($res, true);
        $this->access_token = $res['access_token'];
    } else {
        echo "ERROR: Failed to access Dropbox API : " . curl_error($ch) . "<br>";
    }

    curl_close($ch);

    return $access_token;
}

// 一時的なアクセストークンを取得
$access_token = getAccessToken();

cURLを使って、アクセスします。
getAccessToken()を実行すると、戻り値として一時的なアクセストークンが返ってきます。

Dropbox内のファイル一覧を取得する

さて、一時的なアクセストークンが取得できたら、いよいよDropboxへのアクセスです。

<?php
// 定数として記述しておく
const APP_KEY = '[App Key]';
const APP_SECRET = '[App Secret]';
const REFRESH_TOKEN = '[リフレッシュトークン]';

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// 一時アクセストークンを取得
private function getAccessToken() {
    // さっきの処理
}

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// ファイル一覧を取得
function getFileList($access_token, $dirname) {
    $url = "https://api.dropboxapi.com/2/files/list_folder";
    $headers = array(
        "Authorization: Bearer " . $access_token,
        "Content-Type: application/json",
    );
    $post = array(
        "path"      => $dirname,    // 対象のディレクトリ
        "recursive" => true,        // サブフォルダ下も見る
    );

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    $options = array(
        CURLOPT_POSTFIELDS => json_encode($post),
    );

    curl_setopt_array($ch, $options);

    $res = curl_exec($ch);
    $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

    $files = array();
    if (!curl_errno($ch) && $http_code == "200") {
        $res = json_decode($res, true);
        if ($res["entries"]) {
            foreach ($res["entries"] as $index => $content) {
                if ($content[".tag"] == "file") {
                    $files[] = $content;
                }
            }
        }
        if ($res["has_more"]) {
            //続き読み込み
            $morefiles = $this->getFileListRecursive($res["cursor"]);
            $files = array_merge($files, $morefiles);
        }
    } else {
        echo "ERROR: Failed to access Dropbox API : " . curl_error($ch) . "<br>";
    }

    curl_close($ch);
    return $files;
}

// 一時的なアクセストークンを取得
$access_token = getAccessToken();
// ファイルの一覧を取得
$files = getFileList($access_token, "");

// 結果を出力
echo "<pre>";
var_dump($files);
echo "</pre>";

今回の注意すべき点としては、アクセス先ディレクトリがルートディレクトリの場合、”/”ではなく、””を指定する点ですね。

そして、””を指定した時のルートディレクトリがどこかというと、”Dropbox/アプリ/ImageTransferApp”となります。
Dropboxルートではなく、アプリディレクトリが作成され、さらにその下にアプリ名のディレクトリが作成され、アプリ名のディレクトリがルートとなります。

だって、Dropboxアプリ作成時に「App folder」を選んだもんね?

Dropbox内のファイルにアクセスするURLを取得する

Dropbox内のファイルURLを直接取得するのではなく、ファイルにアクセスするための一時URLを生成して、そのURLを返すという方式をとっています。

<?php
// 定数として記述しておく
const APP_KEY = '[App Key]';
const APP_SECRET = '[App Secret]';
const REFRESH_TOKEN = '[リフレッシュトークン]';

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// 一時アクセストークンを取得
private function getAccessToken() {
    // さっきの処理
}

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// ファイルの一時アクセス用リンクURLを取得
function getFileURL($access_token, $local_filepath) {
    $url = "https://api.dropboxapi.com/2/files/get_temporary_link";
    $headers = array(
        "Authorization: Bearer " . $access_token,
        "Content-Type: application/json",
    );
    $post = array(
        "path"      => $local_filepath, // 対象ファイルのパス
    );

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    $options = array(
        CURLOPT_POSTFIELDS => json_encode($post),
    );

    curl_setopt_array($ch, $options);

    $res = curl_exec($ch);
    $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

    $file_uri = '';
    if (!curl_errno($ch) && $http_code == "200") {
        $res = json_decode($res, true);
        $file_uri = $res['link'];
    } else {
        echo "ERROR: Failed to access Dropbox API : " . curl_error($ch) . "<br>";
    }

    curl_close($ch);
    return $file_uri;
}

// 一時的なアクセストークンを取得
$access_token = getAccessToken();
// Dropbox内のファイルにアクセスするURLを取得する
$url = getFileURL($access_token, "/test/img.png");

// 結果を出力
echo "<pre>";
var_dump($res);
echo "</pre>";

Dropbox内にファイルをアップロードする

<?php
// 定数として記述しておく
const APP_KEY = '[App Key]';
const APP_SECRET = '[App Secret]';
const REFRESH_TOKEN = '[リフレッシュトークン]';

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// 一時アクセストークンを取得
private function getAccessToken() {
    // さっきの処理
}

//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// ファイルをアップロード(軽いファイル用)
function uploadFile($access_token, $local_filepath, $upload_filepath) {
    $url = "https://content.dropboxapi.com/2/files/upload";
    $headers = array(
        "Authorization: Bearer " . $access_token,
        "Content-Type: application/octet-stream",
        "Dropbox-API-Arg: " . json_encode(array(
            "path" => $upload_filepath,
            "mode" => "add",
            "autorename" => true
        )),
    );
    $file = fopen($local_filepath, 'rb');
    $size = filesize($local_filepath);

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_PUT, true);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
		curl_setopt($ch, CURLOPT_INFILE, $file);
		curl_setopt($ch, CURLOPT_INFILESIZE, $size);

    $res = curl_exec($ch);
    $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

    if (!curl_errno($ch) && $http_code == "200") {
        $res = json_decode($res, true); //連想配列で返す
    } else {
        echo "ERROR: Failed to access DropBox via API : " . curl_error($ch) . "<br>";
    }

    fclose($file);
    curl_close($ch);
    return $res['path_lower'];
}

// 一時的なアクセストークンを取得
$access_token = getAccessToken();
// ファイルをアップロード
$remote_path = uploadFile($access_token, "C:\\Sample\\Sample.png", "/test/img02.png");

// 結果を出力
echo "<pre>";
var_dump($res);
echo "</pre>";

これ、コメントに(軽いファイル用)って書いてるんですけど、Dropbox HTTP APIの公式リファレンスを見ると、「Do not use this to upload a file larger than 150 MB.(150MB以上のサイズのファイルアップロードには使っちゃダメだよ)」って書いてるんですね。

150MB以上のファイルをアップロードする時にはupload_sessionっていうのを使うようです。
upload_sessionの使い方については、またの機会に掲載しようと思います。

ここまでの処理をクラス化してみたよ

class Dropbox {
    const APP_KEY = '[App Key]';
    const APP_SECRET = '[App Secret]';
    const REFRESH_TOKEN = '[リフレッシュトークン]';

    // 一時的なアクセストークン
    private $access_token;

    // コンストラクタ
    public function __construct() {
        // 一時的なアクセストークンを取得
        $this->access_token = $this->getAccessToken();
    }

    //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    // 一時的なアクセストークンを取得
    private function getAccessToken() {
        $url = 'https://api.dropboxapi.com/oauth2/token';
        $data = [
            'grant_type'    => 'refresh_token',
            'refresh_token' => self::REFRESH_TOKEN,
            'client_id'     => self::APP_KEY,
            'client_secret' => self::APP_SECRET
        ];

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));

        $res = curl_exec($ch);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

        $access_token = '';
        if (!curl_errno($ch) && $http_code == "200") {
            $res = json_decode($res, true);
            $access_token = $res['access_token'];
        } else {
            echo "ERROR: Failed to access Dropbox API : " . curl_error($ch) . "<br>";
        }

        curl_close($ch);

        return $access_token;
    }

    //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    // ファイル一覧を取得
    public function getFileList($dirname) {
		    $url = "https://api.dropboxapi.com/2/files/list_folder";
		    $headers = array(
		        "Authorization: Bearer " . $this->access_token, //取得したアクセストークン
		    	  "Content-Type: application/json",
		    );
        $post = array(
			      "path"      => $dirname,    // 対象のディレクトリ
			      "recursive" => true,        // サブフォルダ下も見る
		    );

		    $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
		    $options = array(
			      CURLOPT_POSTFIELDS => json_encode($post),
		    );

		    curl_setopt_array($ch, $options);

		    $res = curl_exec($ch);
		    $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

		    $files = array();
		    if (!curl_errno($ch) && $http_code == "200") {
			      $res = json_decode($res, true); //連想配列で返す
			      if ($res["entries"]) {
				        foreach ($res["entries"] as $index => $content) {
					          if ($content[".tag"] == "file") {
						            $files[] = $content;
					          }
				        }
			      }
			      if ($res["has_more"]) {
				        $morefiles = $this->getFileListRecursive($res["cursor"]);
				        $files = array_merge($files, $morefiles);
			      }
		    } else {
            echo "ERROR: Failed to access Dropbox API : " . curl_error($ch) . "<br>";
		    }

		    curl_close($ch);

        return $files;
	  }

    //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    // ファイル一覧を取得
    public function getFileListRecursive($cursor) {
		    $url = "https://api.dropboxapi.com/2/files/list_folder/continue";

		    $headers = array(
			      "Authorization: Bearer " . $this->access_token,
			      "Content-Type: application/json",
		    );

		    $post = array(
			      "cursor" => "{$cursor}", //ファイル取得レスポンスに含まれるカーソルがパラメータ
		    );

		    $ch = curl_init();
		    $options = array(
			      CURLOPT_URL => $url,
			      CURLOPT_HTTPHEADER => $headers,
			      CURLOPT_POST => true,
			      CURLOPT_POSTFIELDS => json_encode($post),
			      CURLOPT_RETURNTRANSFER => true,
		    );
		    curl_setopt_array($ch, $options);

		    $res = curl_exec($ch);
		    $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

		    $files = array();
		    if (!curl_errno($ch) && $http_code == "200") {
			      $res = json_decode($res, true);
			      if ($res["entries"]) {
				        foreach ($res["entries"] as $content) {
					          if ($content[".tag"] == "file") {
						            $files[] = $content;
					          }
				        }
			      }
			      if ($res["has_more"]) {
				        $morefiles = $this->getFileListRecursive($res["cursor"]);
				        $files = array_merge($files, $morefiles);
			      }
		    } else {
            echo "ERROR: Failed to access Dropbox API : " . curl_error($ch) . "<br>";
		    }

		    curl_close($ch);

		    return $files;
	  }

    //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    // ファイルの一時アクセス用リンクURLを取得
    public function getFileURL($local_filepath) {
		    $url = "https://api.dropboxapi.com/2/files/get_temporary_link";
		    $headers = array(
			      "Authorization: Bearer " . $this->access_token, //取得したアクセストークン
			      "Content-Type: application/json",
		    );
        $post = array(
			      "path"      => $local_filepath, // 対象ファイルのパス
		    );

		    $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
		    $options = array(
			      CURLOPT_POSTFIELDS => json_encode($post),
		    );
		    curl_setopt_array($ch, $options);

		    $res = curl_exec($ch);
		    $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

		    $file_uri = '';
		    if (!curl_errno($ch) && $http_code == "200") {
			      $res = json_decode($res, true);
            $file_uri = $res['link'];
		    } else {
            echo "ERROR: Failed to access Dropbox API : " . curl_error($ch) . "<br>";
		    }

		    curl_close($ch);

        return $file_uri;
	  }

    //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    // ファイルをアップロード(軽いファイル用)
    public function uploadFile($local_filepath, $upload_filepath) {
		    $url = "https://content.dropboxapi.com/2/files/upload";
		    $headers = array(
			      "Authorization: Bearer " . $this->access_token, // 取得したアクセストークン
			      "Content-Type: application/octet-stream",
			      "Dropbox-API-Arg: " . json_encode(array(
                "path" => $upload_filepath,
                "mode" => "add",
                "autorename" => true
            )),
		    );
        $file = fopen($local_filepath, 'rb');
        $size = filesize($local_filepath);

		    $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_PUT, true);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
		    curl_setopt($ch, CURLOPT_INFILE, $file);
		    curl_setopt($ch, CURLOPT_INFILESIZE, $size);
       
		    $res = curl_exec($ch);
		    $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

		    if (!curl_errno($ch) && $http_code == "200") {
			      $res = json_decode($res, true);
		    } else {
            echo "ERROR: Failed to access Dropbox API : " . curl_error($ch) . "<br>";
		    }

        fclose($file);
		    curl_close($ch);

        return $res['path_lower'];
	  }
}

// クラスのインスタンスを生成
$dropbox = new Dropbox();

// ファイル一覧を取得
// DropboxRoot => アプリ => アプリ名(アプリルート) => 指定ディレクトリパス
$files = $dropbox->getFileList('');

// ファイルアップロード
$remote_path = $dropbox->uploadFile('.\img\sea.jpg', '/sea.jpg');
echo "<div>UPLOAD PATH : {$remote_path}</div>";

// ファイルのアクセスURLを取得
// DropboxRoot => アプリ => アプリ名(アプリルート) => 指定ディレクトリパス
$url = $dropbox->getFileURL("/sea.jpg");
// 取得したURLの画像を表示してみる
echo "<div><img style='max-width:320px; max-height:320px;' src='{$url}'/></div>";

みんなはうまく動いたかな?

宣伝
WordPressサイトのテンプレート編集やトラブル対応、バグ修正、簡単なJavascriptの作成(カルーセルやバリデーション等)など、小規模なスポット対応を受け付けております。
もしお困りごとがありましたら、お問い合わせフォームよりご相談ください。

この記事を書いた人

uilou

uilou

プログラマー

基本的に、自分自身の備忘録のつもりでブログを書いています。 自分と同じ所で詰まった人の助けになれば良いかなと思います。 システムのリファクタリングを得意としており、バックエンド、フロントエンド、アプリケーション、SQLなど幅広い知識と経験があります。 広いだけでなく、知識をもっと深堀りしていきたいですね。