承接 adammbalogh/box-sdk 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

adammbalogh/box-sdk

Composer 安装命令:

composer require adammbalogh/box-sdk

包简介

Unofficial Box.com Php Sdk

README 文档

README

Author Build Status Quality Score Software License Packagist Version Total Downloads

SensioLabsInsight

Description

This is an unofficial Box Php Sdk.

Toc

Support

Support with Gittip

Installation

Install it through composer.

{
    "require": {
        "adammbalogh/box-sdk": "@stable"
    }
}

tip: you should browse the adammbalogh/box-sdk page to choose a stable version to use, avoid the @stable meta constraint.

Authorization

Your goal is to obtain a valid access token.

Authorize

<?php
use AdammBalogh\Box\Client\OAuthClient;
use AdammBalogh\KeyValueStore\KeyValueStore;
use AdammBalogh\KeyValueStore\Adapter\NullAdapter;
use AdammBalogh\Box\Exception\ExitException;
use AdammBalogh\Box\Exception\OAuthException;
use GuzzleHttp\Exception\ClientException;


$clientId = 'clientid';
$clientSecret = 'clientsecret';
$redirectUri = 'http://example.com/my-box-app.php';

$keyValueStore = new KeyValueStore(new NullAdapter());

$oAuthClient = new OAuthClient($keyValueStore, $clientId, $clientSecret, $redirectUri);

try {
	$oAuthClient->authorize();
} catch (ExitException $e) {
	# Location header has set (box's authorize page)
	# Instead of an exit call it throws an ExitException
	exit;
} catch (OAuthException $e) {
	# e.g. Invalid user credentials
	# e.g. The user denied access to your application
} catch (ClientException $e) {
	# e.g. if $_GET['code'] is older than 30 sec
}

$accessToken = $oAuthClient->getAccessToken();

The $keyValueStore object is responsible for obtain/save the access token. The example above uses a NullAdapter for a KeyValueStore, this means it does not obtain or save anything, so authorizes on each call.

If you want to save the access (and the refresh) token persistently, you should check the other adapters of the KeyValueStore package, here.

Revoke tokens

$oAuthClient->revokeTokens();

Get access token Ttl

/* @var int $ttl Access token's time to live */
$ttl = $oAuthClient->getAccessTokenTtl();

Request

Extended Request

Here you can see an example request to the View Api. It calls the UrlDocumentUpload command.

Many of the commands are able to include an Extended Request object. With an Extended Request object you can inject your extra Headers, Url Parameters or Request Body Attributes.

<?php
use AdammBalogh\Box\ViewClient;
use AdammBalogh\Box\Client\View\ApiClient;
use AdammBalogh\Box\Client\View\UploadClient;
use AdammBalogh\Box\Command\View;
use AdammBalogh\Box\Request\ExtendedRequest;

$apiKey = 'apikey';
$viewClient = new ViewClient(new ApiClient($apiKey), new UploadClient($apiKey));

$er = new ExtendedRequest();
$er->setHeader('Content-Type', 'application/json');
$er->addQueryField('fields', 'status');
$er->setPostBodyField('name', 'file-name');

$command = new View\Document\UrlDocumentUpload('https://cloud.box.com/shared/static/zzxlzc38hq7u1u5jdteu.pdf', $er);

Response

Handle Response

You can get 5 important response values:

  • $response->getStatusCode(); # e.g. '201'
  • $response->getReasonPhrase(); # e.g. 'Created'
  • $response->getHeaders(); # array of response headers ['header name' => 'header value']
  • $response->json(); # parse json response as an array
  • (string)$response->getBody();
<?php
use AdammBalogh\Box\ViewClient;
use AdammBalogh\Box\Client\View\ApiClient;
use AdammBalogh\Box\Client\View\UploadClient;
use AdammBalogh\Box\Command\View;
use AdammBalogh\Box\Factory\ResponseFactory;
use AdammBalogh\Box\GuzzleHttp\Message\SuccessResponse;
use AdammBalogh\Box\GuzzleHttp\Message\ErrorResponse;

$apiKey = 'apikey';
$viewClient = new ViewClient(new ApiClient($apiKey), new UploadClient($apiKey));

$command = new View\Document\ListDocument();
$response = ResponseFactory::getResponse($viewClient, $command);

if ($response instanceof SuccessResponse) {
    $response->getStatusCode();
    $response->getReasonPhrase();
    $response->getHeaders();
    $response->json();
    (string)$response->getBody();
} elseif ($response instanceof ErrorResponse) {
    # same as above
}

Content Api

Create Client

<?php
use AdammBalogh\Box\ContentClient;
use AdammBalogh\Box\Client\Content\ApiClient;
use AdammBalogh\Box\Client\Content\UploadClient;

$accessToken = 'accesstoken';

$contentClient = new ContentClient(new ApiClient($accessToken), new UploadClient($accessToken));

Commands

User Commands

Get Current User Command

<?php
use AdammBalogh\Box\Command\Content;
use AdammBalogh\Box\Factory\ResponseFactory;
use AdammBalogh\Box\GuzzleHttp\Message\SuccessResponse;
use AdammBalogh\Box\GuzzleHttp\Message\ErrorResponse;

$command = new Content\User\GetCurrentUser();
$response = ResponseFactory::getResponse($contentClient, $command);

if ($response instanceof SuccessResponse) {
	# ...
} elseif ($response instanceof ErrorResponse) {
	# ...
}

Folder Commands

Copy Folder Command

<?php
use AdammBalogh\Box\Command\Content;
use AdammBalogh\Box\Factory\ResponseFactory;
use AdammBalogh\Box\GuzzleHttp\Message\SuccessResponse;
use AdammBalogh\Box\GuzzleHttp\Message\ErrorResponse;

$command = new Content\Folder\CopyFolder('sourceFolderId', 'destinationFolderId');
$response = ResponseFactory::getResponse($contentClient, $command);

if ($response instanceof SuccessResponse) {
	# ...
} elseif ($response instanceof ErrorResponse) {
	# ...
}

Create Folder Command

<?php
use AdammBalogh\Box\Command\Content;
use AdammBalogh\Box\Factory\ResponseFactory;
use AdammBalogh\Box\GuzzleHttp\Message\SuccessResponse;
use AdammBalogh\Box\GuzzleHttp\Message\ErrorResponse;

$command = new Content\Folder\CreateFolder('folderName', 'parentFolderId');
$response = ResponseFactory::getResponse($contentClient, $command);

if ($response instanceof SuccessResponse) {
	# ...
} elseif ($response instanceof ErrorResponse) {
	# ...
}

Create Shared Folder Link Command

<?php
use AdammBalogh\Box\Command\Content;
use AdammBalogh\Box\Factory\ResponseFactory;
use AdammBalogh\Box\GuzzleHttp\Message\SuccessResponse;
use AdammBalogh\Box\GuzzleHttp\Message\ErrorResponse;
use AdammBalogh\Box\Request\ExtendedRequest;

$er = new ExtendedRequest();
$er->setPostBodyField('shared_link', ['access'=>'open']);

$command = new Content\Folder\CreateSharedFolderLink('folderId', $er);
$response = ResponseFactory::getResponse($contentClient, $command);

if ($response instanceof SuccessResponse) {
	# ...
} elseif ($response instanceof ErrorResponse) {
	# ...
}

Delete Folder Command

✔ Extended Request

<?php
use AdammBalogh\Box\Command\Content;
use AdammBalogh\Box\Factory\ResponseFactory;
use AdammBalogh\Box\GuzzleHttp\Message\SuccessResponse;
use AdammBalogh\Box\GuzzleHttp\Message\ErrorResponse;

$command = new Content\Folder\DeleteFolder('folderId');
$response = ResponseFactory::getResponse($contentClient, $command);

if ($response instanceof SuccessResponse) {
	# ...
} elseif ($response instanceof ErrorResponse) {
	# ...
}

Get Folder Info Command

<?php
use AdammBalogh\Box\Command\Content;
use AdammBalogh\Box\Factory\ResponseFactory;
use AdammBalogh\Box\GuzzleHttp\Message\SuccessResponse;
use AdammBalogh\Box\GuzzleHttp\Message\ErrorResponse;

$command = new Content\Folder\GetFolderInfo('folderId');
$response = ResponseFactory::getResponse($contentClient, $command);

if ($response instanceof SuccessResponse) {
	# ...
} elseif ($response instanceof ErrorResponse) {
	# ...
}

List Folder Command

✔ Extended Request

<?php
use AdammBalogh\Box\Command\Content;
use AdammBalogh\Box\Factory\ResponseFactory;
use AdammBalogh\Box\GuzzleHttp\Message\SuccessResponse;
use AdammBalogh\Box\GuzzleHttp\Message\ErrorResponse;

$command = new Content\Folder\ListFolder('folderId');
$response = ResponseFactory::getResponse($contentClient, $command);

if ($response instanceof SuccessResponse) {
	# ...
} elseif ($response instanceof ErrorResponse) {
	# ...
}

List Folder Collaborations Command

<?php
use AdammBalogh\Box\Command\Content;
use AdammBalogh\Box\Factory\ResponseFactory;
use AdammBalogh\Box\GuzzleHttp\Message\SuccessResponse;
use AdammBalogh\Box\GuzzleHttp\Message\ErrorResponse;

$command = new Content\Folder\ListFolderCollaborations('folderId');
$response = ResponseFactory::getResponse($contentClient, $command);

if ($response instanceof SuccessResponse) {
	# ...
} elseif ($response instanceof ErrorResponse) {
	# ...
}

Update Folder Info Command

<?php
use AdammBalogh\Box\Command\Content;
use AdammBalogh\Box\Factory\ResponseFactory;
use AdammBalogh\Box\GuzzleHttp\Message\SuccessResponse;
use AdammBalogh\Box\GuzzleHttp\Message\ErrorResponse;
use AdammBalogh\Box\Request\ExtendedRequest;

$er = new ExtendedRequest();
$er->setPostBodyField('name', 'file-name');

$command = new Content\Folder\UpdateFolderInfo('folderId', $er);
$response = ResponseFactory::getResponse($contentClient, $command);

if ($response instanceof SuccessResponse) {
	# ...
} elseif ($response instanceof ErrorResponse) {
	# ...
}

File Commands

Copy File Command

<?php
use AdammBalogh\Box\Command\Content;
use AdammBalogh\Box\Factory\ResponseFactory;
use AdammBalogh\Box\GuzzleHttp\Message\SuccessResponse;
use AdammBalogh\Box\GuzzleHttp\Message\ErrorResponse;

$command = new Content\File\CopyFile('fileId', 'folderId');
$response = ResponseFactory::getResponse($contentClient, $command);

if ($response instanceof SuccessResponse) {
	# ...
} elseif ($response instanceof ErrorResponse) {
	# ...
}

Create Shared File Link Command

<?php
use AdammBalogh\Box\Command\Content;
use AdammBalogh\Box\Factory\ResponseFactory;
use AdammBalogh\Box\GuzzleHttp\Message\SuccessResponse;
use AdammBalogh\Box\GuzzleHttp\Message\ErrorResponse;
use AdammBalogh\Box\Request\ExtendedRequest;

$er = new ExtendedRequest();
$er->setPostBodyField('shared_link', ['access'=>'open']);

$command = new Content\File\CreateSharedFileLink('fileId', $er);
$response = ResponseFactory::getResponse($contentClient, $command);

if ($response instanceof SuccessResponse) {
	# ...
} elseif ($response instanceof ErrorResponse) {
	# ...
}

Delete File Command

✔ Extended Request

<?php
use AdammBalogh\Box\Command\Content;
use AdammBalogh\Box\Factory\ResponseFactory;
use AdammBalogh\Box\GuzzleHttp\Message\SuccessResponse;
use AdammBalogh\Box\GuzzleHttp\Message\ErrorResponse;

$command = new Content\File\DeleteFile('fileId');
$response = ResponseFactory::getResponse($contentClient, $command);

if ($response instanceof SuccessResponse) {
	# ...
} elseif ($response instanceof ErrorResponse) {
	# ...
}

Download File Command

✔ Extended Request

<?php
use AdammBalogh\Box\Command\Content;
use AdammBalogh\Box\Factory\ResponseFactory;
use AdammBalogh\Box\GuzzleHttp\Message\SuccessResponse;
use AdammBalogh\Box\GuzzleHttp\Message\ErrorResponse;

$command = new Content\File\DownloadFile('fileId');
$response = ResponseFactory::getResponse($contentClient, $command);

if ($response instanceof SuccessResponse) {
	# ...
} elseif ($response instanceof ErrorResponse) {
	# ...
}

Get File Info Command

<?php
use AdammBalogh\Box\Command\Content;
use AdammBalogh\Box\Factory\ResponseFactory;
use AdammBalogh\Box\GuzzleHttp\Message\SuccessResponse;
use AdammBalogh\Box\GuzzleHttp\Message\ErrorResponse;

$command = new Content\File\GetFileInfo('fileId');
$response = ResponseFactory::getResponse($contentClient, $command);

if ($response instanceof SuccessResponse) {
	# ...
} elseif ($response instanceof ErrorResponse) {
	# ...
}

Pre Flight Existing File Check Command

<?php
use AdammBalogh\Box\Command\Content;
use AdammBalogh\Box\Factory\ResponseFactory;
use AdammBalogh\Box\GuzzleHttp\Message\SuccessResponse;
use AdammBalogh\Box\GuzzleHttp\Message\ErrorResponse;

$command = new Content\File\PreFlightExistingFileCheck('fileId', fileSize);
$response = ResponseFactory::getResponse($contentClient, $command);

if ($response instanceof SuccessResponse) {
	# ...
} elseif ($response instanceof ErrorResponse) {
	# ...
}

Pre Flight New File Check Command

<?php
use AdammBalogh\Box\Command\Content;
use AdammBalogh\Box\Factory\ResponseFactory;
use AdammBalogh\Box\GuzzleHttp\Message\SuccessResponse;
use AdammBalogh\Box\GuzzleHttp\Message\ErrorResponse;

$command = new Content\File\PreFlightNewFileCheck('fileName', fileSize, 'parentFolderId');
$response = ResponseFactory::getResponse($contentClient, $command);

if ($response instanceof SuccessResponse) {
	# ...
} elseif ($response instanceof ErrorResponse) {
	# ...
}

Update File Info Command

<?php
use AdammBalogh\Box\Command\Content;
use AdammBalogh\Box\Factory\ResponseFactory;
use AdammBalogh\Box\GuzzleHttp\Message\SuccessResponse;
use AdammBalogh\Box\GuzzleHttp\Message\ErrorResponse;
use AdammBalogh\Box\Request\ExtendedRequest;

$er = new ExtendedRequest();
$er->setPostBodyField('name', 'file-name');
$er->setPostBodyField('description', 'file-description');

$command = new Content\File\UpdateFileInfo('fileId', $er);
$response = ResponseFactory::getResponse($contentClient, $command);

if ($response instanceof SuccessResponse) {
	# ...
} elseif ($response instanceof ErrorResponse) {
	# ...
}

Upload File Command

<?php
use AdammBalogh\Box\Command\Content;
use AdammBalogh\Box\Factory\ResponseFactory;
use AdammBalogh\Box\GuzzleHttp\Message\SuccessResponse;
use AdammBalogh\Box\GuzzleHttp\Message\ErrorResponse;

$command = new Content\File\UploadFile('fileName', 'parentFolderId', 'content');
$response = ResponseFactory::getResponse($contentClient, $command);

if ($response instanceof SuccessResponse) {
	# ...
} elseif ($response instanceof ErrorResponse) {
	# ...
}

Upload New File Version Command

✔ Extended Request

<?php
use AdammBalogh\Box\Command\Content;
use AdammBalogh\Box\Factory\ResponseFactory;
use AdammBalogh\Box\GuzzleHttp\Message\SuccessResponse;
use AdammBalogh\Box\GuzzleHttp\Message\ErrorResponse;

$command = new Content\File\UploadNewFileVersion('fileId', 'content');
$response = ResponseFactory::getResponse($contentClient, $command);

if ($response instanceof SuccessResponse) {
	# ...
} elseif ($response instanceof ErrorResponse) {
	# ...
}

Search Commands

Search Content Command

✔ Extended Request

<?php
use AdammBalogh\Box\Command\Content;
use AdammBalogh\Box\Factory\ResponseFactory;
use AdammBalogh\Box\GuzzleHttp\Message\SuccessResponse;
use AdammBalogh\Box\GuzzleHttp\Message\ErrorResponse;

$command = new Content\Search\SearchContent('query');
$response = ResponseFactory::getResponse($contentClient, $command);

if ($response instanceof SuccessResponse) {
	# ...
} elseif ($response instanceof ErrorResponse) {
	# ...
}

View Api

Create Client

<?php
use AdammBalogh\Box\ViewClient;
use AdammBalogh\Box\Client\View\ApiClient;
use AdammBalogh\Box\Client\View\UploadClient;

$apiKey = 'apikey';

$viewClient = new ViewClient(new ApiClient($apiKey), new UploadClient($apiKey));

Commands

Document Commands

Delete Document Command

<?php
use AdammBalogh\Box\Command\View;
use AdammBalogh\Box\Factory\ResponseFactory;
use AdammBalogh\Box\GuzzleHttp\Message\SuccessResponse;
use AdammBalogh\Box\GuzzleHttp\Message\ErrorResponse;

$command = new View\Document\DeleteDocument('documentId');
$response = ResponseFactory::getResponse($viewClient, $command);

if ($response instanceof SuccessResponse) {
	# ...
} elseif ($response instanceof ErrorResponse) {
	# ...
}

Get Document Content Command ☢

<?php
use AdammBalogh\Box\Command\View;
use AdammBalogh\Box\Factory\ResponseFactory;
use AdammBalogh\Box\GuzzleHttp\Message\SuccessResponse;
use AdammBalogh\Box\GuzzleHttp\Message\ErrorResponse;

$command = new View\Document\GetDocumentContent('documentId', 'zip'); # extension can be '', 'zip' or 'pdf'
$response = $viewClient->request($command);

echo (string)$response->getBody(); # the content of the document

Get Document Info Command

✔ Extended Request

<?php
use AdammBalogh\Box\Command\View;
use AdammBalogh\Box\Factory\ResponseFactory;
use AdammBalogh\Box\GuzzleHttp\Message\SuccessResponse;
use AdammBalogh\Box\GuzzleHttp\Message\ErrorResponse;

$command = new View\Document\GetDocumentInfo('documentId');
$response = ResponseFactory::getResponse($viewClient, $command);

if ($response instanceof SuccessResponse) {
	# ...
} elseif ($response instanceof ErrorResponse) {
	# ...
}

Get Document Thumbnail Command

✔ Extended Request

<?php
use AdammBalogh\Box\Command\View;
use AdammBalogh\Box\Factory\ResponseFactory;
use AdammBalogh\Box\GuzzleHttp\Message\SuccessResponse;
use AdammBalogh\Box\GuzzleHttp\Message\ErrorResponse;

$command = new View\Document\GetDocumentThumbnail('documentId');
$response = ResponseFactory::getResponse($viewClient, $command);

if ($response instanceof SuccessResponse) {
	# ...
} elseif ($response instanceof ErrorResponse) {
	# ...
}

List Document Command

✔ Extended Request

<?php
use AdammBalogh\Box\Command\View;
use AdammBalogh\Box\Factory\ResponseFactory;
use AdammBalogh\Box\GuzzleHttp\Message\SuccessResponse;
use AdammBalogh\Box\GuzzleHttp\Message\ErrorResponse;

$command = new View\Document\ListDocument();
$response = ResponseFactory::getResponse($viewClient, $command);

if ($response instanceof SuccessResponse) {
	# ...
} elseif ($response instanceof ErrorResponse) {
	# ...
}

Multipart Document Upload Command

✔ Extended Request

<?php
use AdammBalogh\Box\Command\View;
use AdammBalogh\Box\Factory\ResponseFactory;
use AdammBalogh\Box\GuzzleHttp\Message\SuccessResponse;
use AdammBalogh\Box\GuzzleHttp\Message\ErrorResponse;

$command = new View\Document\MultipartDocumentUpload('content', 'filename.pdf');
$response = ResponseFactory::getResponse($viewClient, $command);

if ($response instanceof SuccessResponse) {
	# ...
} elseif ($response instanceof ErrorResponse) {
	# ...
}

Update Document Info Command

<?php
use AdammBalogh\Box\Command\View;
use AdammBalogh\Box\Factory\ResponseFactory;
use AdammBalogh\Box\GuzzleHttp\Message\SuccessResponse;
use AdammBalogh\Box\GuzzleHttp\Message\ErrorResponse;

$command = new View\Document\UpdateDocumentInfo('documentId', 'newFileName');
$response = ResponseFactory::getResponse($viewClient, $command);

if ($response instanceof SuccessResponse) {
	# ...
} elseif ($response instanceof ErrorResponse) {
	# ...
}

Url Document Upload Command

✔ Extended Request

<?php
use AdammBalogh\Box\Command\View;
use AdammBalogh\Box\Factory\ResponseFactory;
use AdammBalogh\Box\GuzzleHttp\Message\SuccessResponse;
use AdammBalogh\Box\GuzzleHttp\Message\ErrorResponse;

$command = new View\Document\UrlDocumentUpload('urlOfTheDocument');
$response = ResponseFactory::getResponse($viewClient, $command);

if ($response instanceof SuccessResponse) {
	# ...
} elseif ($response instanceof ErrorResponse) {
	# ...
}

Session Commands

Create Document Session Command

✔ Extended Request

<?php
use AdammBalogh\Box\Command\View;
use AdammBalogh\Box\Factory\ResponseFactory;
use AdammBalogh\Box\GuzzleHttp\Message\SuccessResponse;
use AdammBalogh\Box\GuzzleHttp\Message\ErrorResponse;

$command = new View\Session\CreateDocumentSession('documentId');
$response = ResponseFactory::getResponse($viewClient, $command);

if ($response instanceof SuccessResponse) {
	# ...
} elseif ($response instanceof ErrorResponse) {
	# ...
}

Wrappers

Search Path Wrapper

It wraps the Search Content Command to able to get an Entry object from a path string (like /root/dir_1/dir_2, or /pictures/img.png)

<?php
use AdammBalogh\Box\Wrapper\SearchPath;
use AdammBalogh\Box\Wrapper\Response\FolderEntry;
use AdammBalogh\Box\Wrapper\Response\FileEntry;


$wrapper = new SearchPath($contentClient);

$entry = $wrapper->getEntry('/my-dir/example_dir');

if ($entry instanceof FolderEntry) {
    $entry->identity; # folderId
    # here you can create your own command, because now you have the folder id!
} elseif ($entry instanceof FileEntry) {
    $entry->identity;
}

Create Folders Wrapper

It wraps the Create Folder Command to able to create folders implicitly.

<?php
use AdammBalogh\Box\Wrapper\CreateFolders;


$wrapper = new CreateFolders($contentClient);

$lastFolderId = $wrapper->create('/dir_1/dir_2/dir_3/dir_4');

# $lastFolderId means dir_4's id

adammbalogh/box-sdk 适用场景与选型建议

adammbalogh/box-sdk 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 2.6k 次下载、GitHub Stars 达 12, 最近一次更新时间为 2014 年 10 月 01 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「sdk」 「box」 「box.com」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 adammbalogh/box-sdk 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 adammbalogh/box-sdk 我们能提供哪些服务?
定制开发 / 二次开发

基于 adammbalogh/box-sdk 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 2.6k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 12
  • 点击次数: 8
  • 依赖项目数: 1
  • 推荐数: 0

GitHub 信息

  • Stars: 12
  • Watchers: 1
  • Forks: 22
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2014-10-01