├── .editorconfig ├── LICENSE ├── README.md ├── composer.json └── src ├── Application.php ├── BookFactory.php ├── Entities └── Book.php ├── Exceptions ├── Exception.php ├── HttpException.php ├── InvalidArgumentException.php └── InvalidResponseException.php ├── Interfaces ├── Entity.php └── Factory.php ├── ServiceProvider.php └── helper.php /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 4 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = false 10 | 11 | [*.{vue,js,scss}] 12 | charset = utf-8 13 | indent_style = space 14 | indent_size = 2 15 | end_of_line = lf 16 | insert_final_newline = true 17 | trim_trailing_whitespace = true 18 | 19 | [*.md] 20 | trim_trailing_whitespace = false -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) littlesqx 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

douban-book

2 | 3 |

:mag: :books: A book SDK, which can be used to get information of a book.
一个简单的图书 SDK,你可以使用它用于获取指定书籍的基本信息。

4 | 5 | [![Build Status](https://travis-ci.org/Littlesqx/douban-book.svg?branch=master)](https://travis-ci.org/Littlesqx/douban-book) 6 | [![StyleCI](https://github.styleci.io/repos/150088434/shield?branch=master)](https://github.styleci.io/repos/150088434) 7 | 8 | ## Requirement 9 | 10 | - PHP >= 7.1 11 | - Composer 12 | 13 | ## Installing 14 | 15 | ```shell 16 | composer require littlesqx/douban-book -vvv 17 | ``` 18 | 19 | ## Usage 20 | 21 | ```php 22 | getBook($isbn); 37 | // use as an array 38 | $book->toArray(); 39 | 40 | // or get json format 41 | $book->toJSON(); 42 | 43 | // also, get property directly is allowed 44 | $book->getTitle(); 45 | $book->getPrice(); 46 | } catch (\Exception $exception) { 47 | // handle exception 48 | } 49 | 50 | ``` 51 | 52 | ## Test 53 | 54 | ```shell 55 | composer test 56 | ``` 57 | 58 | ## Contributing 59 | 60 | You can contribute in one of three ways: 61 | 62 | 1. File bug reports using the [issue tracker](https://github.com/littlesqx/douban-book/issues). 63 | 2. Answer questions or fix bugs on the [issue tracker](https://github.com/littlesqx/douban-book/issues). 64 | 3. Contribute new features or update the wiki. 65 | 66 | _The code contribution process is not very formal. You just need to make sure that you follow the PSR-0, PSR-1, and PSR-2 coding guidelines. Any new code contributions must be accompanied by unit tests where applicable._ 67 | 68 | ## Thanks 69 | 70 | - [豆瓣 API](https://developers.douban.com) 71 | 72 | - [overtrue](https://github.com/overtrue) 73 | 74 | ## License 75 | 76 | MIT -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "littlesqx/douban-book", 3 | "description": "A book SDK, which can be used to get information of a book.", 4 | "license": "MIT", 5 | "authors": [ 6 | { 7 | "name": "littlesqx", 8 | "email": "littlesqx@gmail.com" 9 | } 10 | ], 11 | "require": { 12 | "php": ">=7.1.0", 13 | "ext-json": "*", 14 | "guzzlehttp/guzzle": "^6.3" 15 | }, 16 | "require-dev": { 17 | "mockery/mockery": "^1.1", 18 | "phpunit/phpunit": "~7" 19 | }, 20 | "autoload": { 21 | "psr-4": { 22 | "Littlesqx\\Book\\": "src" 23 | }, 24 | "files": [ 25 | "src/helper.php" 26 | ] 27 | }, 28 | "scripts": { 29 | "test": "./vendor/bin/phpunit" 30 | }, 31 | "extra": { 32 | "laravel": { 33 | "providers": [ 34 | "Littlesqx\\Book\\ServiceProvider" 35 | ] 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Application.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Littlesqx\Book; 13 | 14 | use GuzzleHttp\Client; 15 | use Littlesqx\Book\Entities\Book; 16 | use Littlesqx\Book\Exceptions\HttpException; 17 | use Littlesqx\Book\Exceptions\InvalidArgumentException; 18 | use Littlesqx\Book\Exceptions\InvalidResponseException; 19 | 20 | class Application 21 | { 22 | /** 23 | * @var array http client configuration 24 | */ 25 | protected $httpOptions = []; 26 | 27 | /** 28 | * @var string request api url, via douban/v2 29 | */ 30 | protected $requestUrl = 'https://api.douban.com/v2/book/'; 31 | 32 | /** 33 | * set http client options. 34 | * 35 | * @param array $httpOptions 36 | * 37 | * @return $this 38 | */ 39 | public function setHttpOptions(array $httpOptions) 40 | { 41 | $this->httpOptions = $httpOptions; 42 | 43 | return $this; 44 | } 45 | 46 | /** 47 | * get http client options. 48 | * 49 | * @return array 50 | */ 51 | public function getHttpOptions(): array 52 | { 53 | return $this->httpOptions; 54 | } 55 | 56 | /** 57 | * get a http client. 58 | * 59 | * @return Client 60 | */ 61 | public function getHttpClient(): Client 62 | { 63 | return new Client($this->httpOptions); 64 | } 65 | 66 | /** 67 | * get a book by isbn code. 68 | * 69 | * @param string $isbn 70 | * 71 | * @return Book 72 | * 73 | * @throws HttpException 74 | * @throws InvalidArgumentException 75 | * @throws InvalidResponseException 76 | */ 77 | public function getBook(string $isbn): Book 78 | { 79 | if (13 !== strlen($isbn) && 10 !== strlen($isbn)) { 80 | throw new InvalidArgumentException('Invalid isbn code(isbn10 or isbn13): '.$isbn); 81 | } 82 | $queryParams = ['isbn' => $isbn]; 83 | 84 | try { 85 | $response = $this->getHttpClient()->get($this->requestUrl.array_to_path($queryParams)); 86 | if (200 === $response->getStatusCode()) { 87 | return BookFactory::make($response->getBody()->getContents()); 88 | } 89 | } catch (\Exception $e) { 90 | if ($e instanceof InvalidResponseException) { 91 | throw $e; 92 | } 93 | 94 | throw new HttpException($e->getMessage(), $e->getCode(), $e); 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/BookFactory.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Littlesqx\Book; 13 | 14 | use Littlesqx\Book\Entities\Book; 15 | use Littlesqx\Book\Exceptions\InvalidResponseException; 16 | use Littlesqx\Book\Interfaces\Factory; 17 | 18 | class BookFactory implements Factory 19 | { 20 | /** 21 | * make a book entity. 22 | * 23 | * @param $body 24 | * 25 | * @return Book 26 | * 27 | * @throws InvalidResponseException 28 | */ 29 | public static function make($body): Book 30 | { 31 | $params = \json_decode($body, true); 32 | if (!isset($params['title'])) { 33 | throw new InvalidResponseException("Response body: {$body}"); 34 | } 35 | $book = new Book(); 36 | 37 | return $book->setIsbn($params['isbn13']) 38 | ->setTitle($params['title']) 39 | ->setSubtitle($params['subtitle']) 40 | ->setAuthor($params['author']) 41 | ->setAuthorIntro($params['author_intro']) 42 | ->setPrice($params['price']) 43 | ->setCatalog($params['catalog']) 44 | ->setPublicationDate($params['pubdate']) 45 | ->setPublisher($params['publisher']) 46 | ->setSummary($params['summary']) 47 | ->setCover($params['images']['large']) 48 | ->setTags(array_column($params['tags'], 'name')) 49 | ->setAltUrl($params['alt']); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Entities/Book.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Littlesqx\Book\Entities; 13 | 14 | use Littlesqx\Book\Interfaces\Entity; 15 | 16 | class Book implements Entity 17 | { 18 | /** 19 | * @var string book's isbn13 code 20 | */ 21 | private $isbn; 22 | 23 | /** 24 | * @var string book's title 25 | */ 26 | private $title; 27 | 28 | /** 29 | * @var string book's subtitle 30 | */ 31 | private $subtitle; 32 | 33 | /** 34 | * @var array book's authors 35 | */ 36 | private $author; 37 | 38 | /** 39 | * @var string authors' introduction 40 | */ 41 | private $authorIntro; 42 | 43 | /** 44 | * @var string book's publication date 45 | */ 46 | private $publicationDate; 47 | 48 | /** 49 | * @var string book's publisher 50 | */ 51 | private $publisher; 52 | 53 | /** 54 | * @var array book's tags 55 | */ 56 | private $tags; 57 | 58 | /** 59 | * @var string book's catalog 60 | */ 61 | private $catalog; 62 | 63 | /** 64 | * @var string book's summary 65 | */ 66 | private $summary; 67 | 68 | /** 69 | * @var string book's price 70 | */ 71 | private $price; 72 | 73 | /** 74 | * @var string book's cover (image url) 75 | */ 76 | private $cover; 77 | 78 | /** 79 | * @var string book page in douban 80 | */ 81 | private $altUrl; 82 | 83 | /** 84 | * @return string 85 | */ 86 | public function getCover(): string 87 | { 88 | return $this->cover; 89 | } 90 | 91 | /** 92 | * @param string $cover 93 | * 94 | * @return $this 95 | */ 96 | public function setCover(string $cover) 97 | { 98 | $this->cover = $cover; 99 | 100 | return $this; 101 | } 102 | 103 | /** 104 | * @return string 105 | */ 106 | public function getIsbn(): string 107 | { 108 | return $this->isbn; 109 | } 110 | 111 | /** 112 | * @param string $isbn 113 | * 114 | * @return $this 115 | */ 116 | public function setIsbn(string $isbn) 117 | { 118 | $this->isbn = $isbn; 119 | 120 | return $this; 121 | } 122 | 123 | /** 124 | * @return string 125 | */ 126 | public function getTitle(): string 127 | { 128 | return $this->title; 129 | } 130 | 131 | /** 132 | * @param string $title 133 | * 134 | * @return $this 135 | */ 136 | public function setTitle(string $title) 137 | { 138 | $this->title = $title; 139 | 140 | return $this; 141 | } 142 | 143 | /** 144 | * @return string 145 | */ 146 | public function getSubtitle(): string 147 | { 148 | return $this->subtitle; 149 | } 150 | 151 | /** 152 | * @param string $subtitle 153 | * 154 | * @return $this 155 | */ 156 | public function setSubtitle(string $subtitle) 157 | { 158 | $this->subtitle = $subtitle; 159 | 160 | return $this; 161 | } 162 | 163 | /** 164 | * @return array 165 | */ 166 | public function getAuthor(): array 167 | { 168 | return $this->author; 169 | } 170 | 171 | /** 172 | * @param array $author 173 | * 174 | * @return $this 175 | */ 176 | public function setAuthor(array $author) 177 | { 178 | $this->author = $author; 179 | 180 | return $this; 181 | } 182 | 183 | /** 184 | * @return string 185 | */ 186 | public function getAuthorIntro(): string 187 | { 188 | return $this->authorIntro; 189 | } 190 | 191 | /** 192 | * @param string $authorIntro 193 | * 194 | * @return $this 195 | */ 196 | public function setAuthorIntro(string $authorIntro) 197 | { 198 | $this->authorIntro = $authorIntro; 199 | 200 | return $this; 201 | } 202 | 203 | /** 204 | * @return string 205 | */ 206 | public function getPublicationDate(): string 207 | { 208 | return $this->publicationDate; 209 | } 210 | 211 | /** 212 | * @param string $publicationDate 213 | * 214 | * @return $this 215 | */ 216 | public function setPublicationDate(string $publicationDate) 217 | { 218 | $this->publicationDate = $publicationDate; 219 | 220 | return $this; 221 | } 222 | 223 | /** 224 | * @return string 225 | */ 226 | public function getPublisher(): string 227 | { 228 | return $this->publisher; 229 | } 230 | 231 | /** 232 | * @param string $publisher 233 | * 234 | * @return $this 235 | */ 236 | public function setPublisher(string $publisher) 237 | { 238 | $this->publisher = $publisher; 239 | 240 | return $this; 241 | } 242 | 243 | /** 244 | * @return array 245 | */ 246 | public function getTags(): array 247 | { 248 | return $this->tags; 249 | } 250 | 251 | /** 252 | * @param array $tags 253 | * 254 | * @return $this 255 | */ 256 | public function setTags(array $tags) 257 | { 258 | $this->tags = $tags; 259 | 260 | return $this; 261 | } 262 | 263 | /** 264 | * @return string 265 | */ 266 | public function getCatalog(): string 267 | { 268 | return $this->catalog; 269 | } 270 | 271 | /** 272 | * @param string $catalog 273 | * 274 | * @return $this 275 | */ 276 | public function setCatalog(string $catalog) 277 | { 278 | $this->catalog = $catalog; 279 | 280 | return $this; 281 | } 282 | 283 | /** 284 | * @return string 285 | */ 286 | public function getSummary(): string 287 | { 288 | return $this->summary; 289 | } 290 | 291 | /** 292 | * @param string $summary 293 | * 294 | * @return $this 295 | */ 296 | public function setSummary(string $summary) 297 | { 298 | $this->summary = $summary; 299 | 300 | return $this; 301 | } 302 | 303 | /** 304 | * @return string 305 | */ 306 | public function getPrice(): string 307 | { 308 | return $this->price; 309 | } 310 | 311 | /** 312 | * @param string $price 313 | * 314 | * @return $this 315 | */ 316 | public function setPrice(string $price) 317 | { 318 | $this->price = $price; 319 | 320 | return $this; 321 | } 322 | 323 | /** 324 | * @return string 325 | */ 326 | public function getAltUrl(): string 327 | { 328 | return $this->altUrl; 329 | } 330 | 331 | /** 332 | * @param string $altUrl 333 | * 334 | * @return $this 335 | */ 336 | public function setAltUrl(string $altUrl) 337 | { 338 | $this->altUrl = $altUrl; 339 | 340 | return $this; 341 | } 342 | 343 | /** 344 | * get attributes with array format. 345 | * 346 | * @return array 347 | */ 348 | public function toArray(): array 349 | { 350 | return [ 351 | 'isbn' => $this->isbn, 352 | 'title' => $this->title, 353 | 'subtitle' => $this->subtitle, 354 | 'price' => $this->price, 355 | 'author' => $this->author, 356 | 'author_intro' => $this->authorIntro, 357 | 'publication_date' => $this->publicationDate, 358 | 'publisher' => $this->publisher, 359 | 'tags' => $this->tags, 360 | 'catalog' => $this->catalog, 361 | 'cover' => $this->cover, 362 | 'summary' => $this->summary, 363 | ]; 364 | } 365 | 366 | /** 367 | * get attributes with json format. 368 | * 369 | * @return string 370 | */ 371 | public function toJSON(): string 372 | { 373 | return \json_encode($this->toArray(), JSON_UNESCAPED_UNICODE); 374 | } 375 | } 376 | -------------------------------------------------------------------------------- /src/Exceptions/Exception.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Littlesqx\Book\Exceptions; 13 | 14 | /** 15 | * Class Exceptions. 16 | */ 17 | class Exception extends \Exception 18 | { 19 | } 20 | -------------------------------------------------------------------------------- /src/Exceptions/HttpException.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Littlesqx\Book\Exceptions; 13 | 14 | /** 15 | * Class HttpException. 16 | */ 17 | class HttpException extends Exception 18 | { 19 | } 20 | -------------------------------------------------------------------------------- /src/Exceptions/InvalidArgumentException.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Littlesqx\Book\Exceptions; 13 | 14 | /** 15 | * Class InvalidArgumentException. 16 | */ 17 | class InvalidArgumentException extends Exception 18 | { 19 | } 20 | -------------------------------------------------------------------------------- /src/Exceptions/InvalidResponseException.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Littlesqx\Book\Exceptions; 13 | 14 | class InvalidResponseException extends Exception 15 | { 16 | } 17 | -------------------------------------------------------------------------------- /src/Interfaces/Entity.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Littlesqx\Book\Interfaces; 13 | 14 | interface Entity 15 | { 16 | public function toArray(); 17 | 18 | public function toJSON(); 19 | } 20 | -------------------------------------------------------------------------------- /src/Interfaces/Factory.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Littlesqx\Book\Interfaces; 13 | 14 | interface Factory 15 | { 16 | public static function make($params); 17 | } 18 | -------------------------------------------------------------------------------- /src/ServiceProvider.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | namespace Littlesqx\Book; 13 | 14 | class ServiceProvider extends \Illuminate\Support\ServiceProvider 15 | { 16 | protected $defer = true; 17 | 18 | public function register() 19 | { 20 | $this->app->singleton(Application::class, function () { 21 | return new Application(); 22 | }); 23 | $this->app->alias(Application::class, 'douban-book'); 24 | } 25 | 26 | public function provides() 27 | { 28 | return [Application::class, 'douban-book']; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/helper.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * This source file is subject to the MIT license that is bundled 9 | * with this source code in the file LICENSE. 10 | */ 11 | 12 | if (!function_exists('array_to_path')) { 13 | /** 14 | * input: ['foo' => 'bar'], output: foo/bar. 15 | * 16 | * @param $array 17 | * 18 | * @return string 19 | */ 20 | function array_to_path($array): string 21 | { 22 | $path = ''; 23 | foreach ($array as $key => $value) { 24 | if ('' === trim($key)) { 25 | continue; 26 | } 27 | $path .= "{$key}/{$value}"; 28 | } 29 | 30 | return $path; 31 | } 32 | } 33 | --------------------------------------------------------------------------------