<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[
<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[
Zend Framework: ZendX_Service_Rakuten Component Proposal
| Proposed Component Name |
ZendX_Service_Rakuten |
| Developer Notes |
http://framework.zend.com/wiki/display/ZFDEV/ZendX_Service_Rakuten |
| Proposers |
Satoru Yoshida
Ralph Schindler, Zend liaison |
| Revision |
------31 Dec:Name change from Zend_ to ZendX_
------11 Dec:add explanation of method parameters.
0.8 - 28 Nov 2008:I made APIs correspond from version 1.10 to 1.12 and I implemented the checking of the required parameters.
0.7 - 26 Dec: update References, Use Cases and Class Skeletons.
0.6 - 19 Dec: update References, Class Index, Use Cases and Class Skeletons.
0.5 - 11 Dec: update References, Use Cases and Class Skeletons.
0.4 - 22 Nov: update all except Dependencies and Milestones.
0.3 - 21 May: update class skeletons.
0.2 - 15 March 2007: add class skeletons. (wiki revision: 35) |
Table of Contents
1. Overview
ZendX_Service_Rakuten is a interface to use the "Rakuten Web service" that is provided by the Rakuten, Inc. .
2. References
The following links are API references written in Japanese. I write method names and brief description for each API.
- Rakuten Web Service
- for the Rakuten Market
- searchItem() - Search items. Uses ItemSearch API
| parameter |
type |
min |
max |
required |
default |
explanation |
|
|
|
|
|
|
|
following in params array |
| affiliateId |
string |
|
|
|
null |
affiliate id |
| callBack |
string |
|
|
|
null |
function name of Json call back |
| keyword |
string |
|
|
may required |
null |
key word. One of keyword, genreId or catalogCode is required |
| shopCode |
string |
|
|
|
null |
shop code |
| genreId |
int |
0 |
|
may required |
0 |
genre id. One of keyword, genreId or catalogCode is required. |
| catalogCode |
string |
|
|
may required |
null |
catalog code. One of keyword, genreId or catalogCode is required |
| hits |
int |
1 |
30 |
|
30 |
items per page. |
| page |
int |
1 |
100 |
|
1 |
page limits. |
| sort |
string |
|
|
|
standard |
sort type. (mark)affiliateRate, (mark)reviewCount, (mark)itemPrice, (mark)updateTimestamp or standard. (mark) means plus or minus mark, each mark means Ascend and Descend. For example, +itemPrice |
| minPrice |
int |
0 |
|
|
null |
minimum price |
| maxPrice |
int |
0 |
|
|
null |
maximum price. It must be grater than minPrice |
| availability |
int |
0 |
1 |
|
1 |
0:all items, 1:only items that can be bought |
| field |
int |
0 |
1 |
|
1 |
0:search widely, 1:search narrowly |
| carrier |
int |
0 |
1 |
|
0 |
0:PC, 1:mobile |
| imageFlag |
int |
0 |
1 |
|
0 |
0:all item, 1:only items that has image |
| orFlag |
int |
0 |
1 |
|
0 |
0:AND keywords, 1:OR keywords |
| NGKeyword |
string |
|
|
|
null |
keyword that you want to omit |
| genreInformationFlag |
int |
0 |
1 |
|
0 |
No Use. 0:not get count of items that are in the same genre, 1:get count. This method supports only 0. |
- searchGenre() - Retrieve genre's information. Uses GenreSearch API
| parameter |
type |
min |
max |
required |
default |
explanation |
| type |
string |
|
|
required |
child |
information type. child, parent or current |
| genreId |
int |
0 |
|
required |
0 |
genre id. If parent is specified, genre id must be grater than 0. |
|
|
|
|
|
|
|
following in optparams array |
| affiliateId |
string |
|
|
|
null |
affiliate id |
| callBack |
string |
|
|
|
null |
function name of Json call back |
| genrePath |
int |
0 |
1 |
|
|
No Use. genrePath is auto controlled in this method. |
- searchItemCode() - Retrieve item's information by item code. Uses ItemCodeSearch API
| parameter |
type |
min |
max |
required |
default |
explanation |
| code |
string |
|
|
required |
|
item code |
|
|
|
|
|
|
|
following in optparams array |
| affiliateId |
string |
|
|
|
null |
affiliate id |
| callBack |
string |
|
|
|
null |
function name of Json call back |
| carrier |
int |
0 |
1 |
|
0 |
0:PC, 1:mobile |
- searchCatalog() - Search items by catalog. Uses CatalogSearch API
| parameter |
type |
min |
max |
required |
default |
explanation |
|
|
|
|
|
|
|
following in params array |
| affiliateId |
string |
|
|
|
null |
affiliate id |
| callBack |
string |
|
|
|
null |
function name of Json call back |
| keyword |
string |
|
|
may required |
null |
key word. One of keyword or genreId is required |
| genreId |
int |
0 |
|
may required |
0 |
genre id. One of keyword or genreId is required. |
| hits |
int |
1 |
30 |
|
30 |
items per page. |
| page |
int |
1 |
100 |
|
1 |
page limits. |
| sort |
string |
|
|
|
-registerDate |
sort type. (mark)registerDate,(mark)releaseDate, (mark)reviewNum or random. (mark) means plus or minus mark, each mark means Ascend and Descend. For example, +reviewNum |
| field |
int |
0 |
1 |
|
1 |
0:search widely, 1:search narrowly |
| imageFlag |
int |
0 |
1 |
|
0 |
0:all item, 1:only items that has image |
| releaseRange |
int |
0 |
12 |
|
0 |
0:no limit, 1-12:search only sold in specified months |
| orFlag |
int |
0 |
1 |
|
0 |
0:AND keywords, 1:OR keywords |
| NGKeyword |
string |
|
|
|
null |
keyword that you want to omit |
| genreInformationFlag |
int |
0 |
1 |
|
0 |
No use. cf. searchItem() |
- itemRanking() - Retrieve item ranking. Uses ItemRanking API
| parameter |
type |
min |
max |
required |
default |
explanation |
|
|
|
|
|
|
|
following in optparams array |
| affiliateId |
string |
|
|
|
null |
affiliate id |
| callBack |
string |
|
|
|
null |
function name of Json call back |
| genreId |
int |
0 |
|
|
null |
genre id. |
| age |
int |
10 |
50 |
|
null |
age zone. 10:teen agers, 20:20 agers, 30:30 agers, 40:40 agers, 50:50 over |
| sex |
int |
0 |
1 |
|
null |
sex. 0:men, 1:women |
- for the Rakuten Books
- searchBook() - search books. Uses BookSearch API
| parameter |
type |
min |
max |
required |
default |
explanation |
|
|
|
|
|
|
|
following in params array |
| affiliateId |
string |
|
|
|
null |
affiliate id |
| callBack |
string |
|
|
|
null |
function name of Json call back |
| keyword |
string |
|
|
may required |
null |
key word. One of keyword or genreId is required |
| genreId |
int |
0 |
|
may required |
0 |
genre id. One of keyword or genreId is required. The root id of the genreId must be 200162(books, magazine and comic). |
| hits |
int |
1 |
30 |
|
30 |
items per page. |
| page |
int |
1 |
100 |
|
1 |
page limits. |
| sort |
string |
|
|
|
standard |
sort type. (mark)affiliateRate, (mark)reviewCount, (mark)itemPrice, (mark)updateTimestamp or random. (mark) means plus or minus mark, each mark means Ascend and Descend. For example, +itemPrice |
| minPrice |
int |
0 |
|
|
null |
minimum price |
| maxPrice |
int |
0 |
|
|
null |
maximum price. It must be grater than minPrice. |
| availability |
int |
0 |
1 |
|
1 |
0:all items, 1:only items that you can buy. |
| field |
int |
0 |
1 |
|
1 |
0:search widely, 1:search narrowly |
| carrier |
int |
0 |
1 |
|
0 |
0:PC, 1:mobile |
| imageFlag |
int |
0 |
1 |
|
0 |
0:all item, 1:only items that has image |
| orFlag |
int |
0 |
1 |
|
0 |
0:AND keywords, 1:OR keywords |
| NGKeyword |
string |
|
|
|
null |
keyword that you want to omit |
| genreInformationFlag |
int |
0 |
1 |
|
0 |
No use. cf. searchItem() |
- searchCd() - search CDs. Uses CDSearch API
This method has same parameters like searchBook(). But the root id of the genreId must be 101311(CD).
- searchDvd() - search DVDs. Uses DVDSearch API
This method has same parameters like searchBook(). But the root id of the genreId must be 101354(DVD).
- for the Rakuten Auction
- searchAuctionItem() - Search items. Uses AuctionItemSearch API
| parameter |
type |
min |
max |
required |
default |
explanation |
|
|
|
|
|
|
|
following in params array |
| affiliateId |
string |
|
|
|
null |
affiliate id |
| callBack |
string |
|
|
|
null |
function name of Json call back |
| keyword |
string |
|
|
may required |
null |
key word. One of keyword or genreId is required |
| genreId |
int |
0 |
|
may required |
0 |
genre id. One of keyword or genreId is required. |
| hits |
int |
1 |
30 |
|
30 |
items per page. |
| page |
int |
1 |
100 |
|
1 |
page limits. |
| minPrice |
int |
0 |
|
|
null |
minimum price |
| maxPrice |
int |
0 |
|
|
null |
maximum price. It must be grater than minPrice. |
| sort |
string |
|
|
|
+endTime |
sort type. (mark)endTime, (mark)itemPrice, (mark)bidCount or (mark)affiliateRate. (mark) means plus or minus mark, each mark means Ascend and Descend. For example, +itemPrice |
| blowFlag |
int |
0 |
1 |
|
0 |
0:all items, 1:only items that you can buy without waiting auction's end. |
| itemType |
int |
0 |
3 |
|
0 |
0:all items, 1:only items that are sold by personal seller, 2:only items that are sold by shops, 3:only items that are sold by auction shops |
| newFlag |
int |
0 |
2 |
|
0 |
0:all items, 1:only used items, 2:only unused items |
| field |
int |
0 |
1 |
|
1 |
0:search widely, 1:search narrowly |
| carrier |
int |
0 |
1 |
|
0 |
0:PC, 1:mobile |
| imageFlag |
int |
0 |
1 |
|
0 |
0:all item, 1:only items that has image |
| orFlag |
int |
0 |
1 |
|
0 |
0:AND keywords, 1:OR keywords |
| NGKeyword |
string |
|
|
|
null |
keyword that you want to omit |
- searchAuctionItemCode() - Retrieve item's information by item code. Uses AuctionItemCodeSearch API
| parameter |
type |
min |
max |
required |
default |
explanation |
| code |
string |
|
|
required |
|
item code |
|
|
|
|
|
|
|
following in optparams array |
| affiliateId |
string |
|
|
|
null |
affiliate id |
| callBack |
string |
|
|
|
null |
function name of Json call back |
| carrier |
int |
0 |
1 |
|
0 |
0:PC, 1:mobile |
- for the Rakuten Travel
- searchSimpleHotel() - Search hotels. Uses SimpleHotelSearch API
| parameter |
type |
min |
max |
required |
default |
explanation |
|
|
|
|
|
|
|
following in params array |
| affiliateId |
string |
|
|
|
null |
affiliate id |
| callBack |
string |
|
|
|
null |
function name of Json call back |
| largeClassCode |
string |
|
|
may required |
null |
area code. It specifies most wide area. For example, country. You can get the class codes list with getAreaClass(). One of the class codes set, hotelNo or latitude/longitude pair is required. |
| middleClassCode |
string |
|
|
may required |
null |
area code. It is children of largeClassCode. |
| smallClassCode |
string |
|
|
may required |
null |
area code. It is children of middleClassCode. |
| detailClassCode |
string |
|
|
may required |
null |
area code. It is children of smallClassCode. |
| hotelNo |
integer |
|
|
may required |
null |
hotel number. One of the class codes set, hotelNo or latitude/longitude pair is required. |
| latitude |
float |
|
|
may required |
null |
latitude. One of the class codes set, hotelNo or latitude/longitude pair is required. Unit is specified with datumType. |
| longitude |
float |
|
|
may required |
null |
longitude. Unit is specified with datumType. |
| searchRadius |
float |
0.1 |
3.0 |
|
1.0 |
radius in searching. enable if you use the latitude/longitude pair. Unit is Km. |
| squeezeCondition |
string |
|
|
|
null |
condition of hotel. kinen?only hotels that have no smoking rooms, internet?only hotels where you can enjoy internet, daiyoku?only hotels that have swimming bath, onsen?only hotels that have hot springs. |
| carrier |
int |
0 |
1 |
|
0 |
0:PC, 1:mobile |
| hits |
int |
|
|
|
null |
limit hit counts. enable if you use the latitude/longitude pair. |
| datumType |
int |
1 |
2 |
|
2 |
1:Unit is degree, 2:Unit is second. |
- searchHotelDetail() - Retrieve hotel's information by hotel number. Uses HotelDetailSearch API
| parameter |
type |
min |
max |
required |
default |
explanation |
| hotelNo |
integer |
|
|
required |
|
hotel number |
|
|
|
|
|
|
|
following in optparams array |
| affiliateId |
string |
|
|
|
null |
affiliate id |
| callBack |
string |
|
|
|
null |
function name of Json call back |
| carrier |
int |
0 |
1 |
|
0 |
0:PC, 1:mobile |
| datumType |
int |
1 |
2 |
|
2 |
1:Unit is degree, 2:Unit is second. |
- searchVacantHotel() - Search hotels that have vacant room. Uses VacantHotelSearch
| parameter |
type |
min |
max |
required |
default |
explanation |
| type |
string |
|
|
required |
hotel |
information type. hotel or room. |
| checkinDate |
date |
|
|
required |
null |
YYYY-MM-DD in Asia/Tokyo time zone. |
| checkoutDate |
date |
|
|
required |
null |
YYYY-MM-DD in Asia/Tokyo time zone. |
|
|
|
|
|
|
|
following in optparams array |
| affiliateId |
string |
|
|
|
null |
affiliate id |
| callBack |
string |
|
|
|
null |
function name of Json call back |
| largeClassCode |
string |
|
|
may required |
null |
area code. It specifies most wide area. For example, country. You can get the class codes list with getAreaClass(). One of the class codes set, hotelNo or latitude/longitude pair is required. |
| middleClassCode |
string |
|
|
may required |
null |
area code. It is children of largeClassCode. |
| smallClassCode |
string |
|
|
may required |
null |
area code. It is children of middleClassCode. |
| detailClassCode |
string |
|
|
may required |
null |
area code. It is children of smallClassCode. |
| hotelNo |
integer |
|
|
may required |
null |
hotel number. One of the class codes set, hotelNo or latitude/longitude pair is required. |
| adultNum |
int |
1 |
99 |
|
1 |
adult members count |
| upClassNum |
int |
0 |
99 |
|
0 |
members count. The members are over elementary school higher students. |
| lowClassNum |
int |
0 |
99 |
|
0 |
members count. The members are under elementary school lower students. |
| infantWithMBNum |
int |
0 |
99 |
|
0 |
infant members count. They need foods and blankets. |
| infantWithMNum |
int |
0 |
99 |
|
0 |
infant members count. They need only blankets. |
| infantWithBNum |
int |
0 |
99 |
|
0 |
infant members count. They need only foods. |
| infantWithoutMBNum |
int |
0 |
99 |
|
0 |
infant members count. They no need foods and blankets. |
| roomNum |
int |
1 |
999 |
|
1 |
required room count |
| maxCharge |
int |
0 |
9999999999 |
|
null |
0:PC, 1:mobile. It must be grater than minCharge. |
| minCharge |
int |
0 |
9999999999 |
|
null |
0:PC, 1:mobile |
| latitude |
float |
|
|
may required |
null |
latitude. One of the class codes set, hotelNo or latitude/longitude pair is required. Unit is specified with datumType. |
| longitude |
float |
|
|
may required |
null |
longitude. Unit is specified with datumType. |
| searchRadius |
float |
0.1 |
3.0 |
|
1.0 |
radius in searching. enable if you use the latitude/longitude pair. Unit is Km. |
| squeezeCondition |
string |
|
|
|
null |
condition of hotel. kinen?only hotels that have no smoking rooms, internet?only hotels where you can enjoy internet, daiyoku?only hotels that have swimming bath, onsen?only hotels that have hot springs, breakfast:only hotels where you can take breakfast, dinner:only hotels where you can take dinner. |
| carrier |
int |
0 |
1 |
|
0 |
0:PC, 1:mobile |
| datumType |
int |
1 |
2 |
|
2 |
1:Unit is degree, 2:Unit is second. |
| hits |
int |
|
|
|
null |
limit hit counts. enable if you use the latitude/longitude pair. |
- getAreaClass() - Retrieve choices of area. Uses GetAreaClass API
| parameter |
type |
min |
max |
required |
default |
explanation |
|
|
|
|
|
|
|
following in optparams array |
| affiliateId |
string |
|
|
|
null |
affiliate id |
| callBack |
string |
|
|
|
null |
function name of Json call back |
- searchKeywordHotel() - Search hotels by word. Uses KeywordHotelSearch API
| parameter |
type |
min |
max |
required |
default |
explanation |
| keyword |
string |
|
|
required |
|
key word. |
|
|
|
|
|
|
|
following in optparams array |
| affiliateId |
string |
|
|
|
null |
affiliate id |
| callBack |
string |
|
|
|
null |
function name of Json call back |
| carrier |
int |
0 |
1 |
|
0 |
0:PC, 1:mobile |
| page |
int |
|
|
|
1 |
page limits. |
| hits |
int |
1 |
100 |
|
20 |
items per page. |
| sumDisplayFlag |
int |
0 |
1 |
|
0 |
0:not display features about the area and the hotel, 1:display. |
| middleClassCode |
string |
|
|
|
null |
area code. You can get the list with getAreaClass(). |
- Other purpose
- dynamicAd() - Retrieve dynamic advertisements that is suitable for content in URL that you specify. Uses DynamicAd API and DynamicAd API (travel)
| parameter |
type |
min |
max |
required |
default |
explanation |
| type |
string |
|
|
required |
item |
advertisement type. item or travel. |
| affiliateId |
string |
|
|
required |
|
affiliate id |
| url |
string |
|
|
required |
|
URL |
|
|
|
|
|
|
|
following in optparams array |
| carrier |
int |
0 |
1 |
|
0 |
0:PC, 1:mobile |
| callBack |
string |
|
|
|
null |
function name of Json call back |
3. Component Requirements, Constraints, and Acceptance Criteria
- Implements the "Rakuten Web Service" APIs.
- Returns server responses as lightweight data objects.
4. Dependencies on Other Framework Components
- Zend_Rest_Client
- Zend_Service_Exception
5. Theory of Operation
Returns server response as the SimpleXMLElement.
6. Milestones / Tasks
- Milestone 1: Class development and write proposal : Finished!
- Milestone 2: Unit tests and debugging : Now working.
- Milestone 3: Documentation : Now working
7. Class Index
8. Use Cases
Search 3 items by word, "Zend Studio". Its case is most simple case.
Retrieve hotels that have vacant room for 1 adult person in the kasukabe city from today to tommorow.
The kasukabe city is in the saitama ward, and the saitama ward is in japan.
The checkinDate and checkoutDate are in Asia/Tokyo (GMT +9) time zone.
Display advertisements that is suitable for www.zend.com .
dynamicAd() needs your affiliate ID from the Rakuten web service.
9. Class Skeletons
]]></ac:plain-text-body></ac:macro>]]></ac:plain-text-body></ac:macro>
30 Comments
comments.show.hideMar 22, 2007
Matthew Ratzloff
<p>Instead of:</p>
<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
protected $_rwsVersion = '1.4';
]]></ac:plain-text-body></ac:macro>
<p>Use:</p>
<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
const API_VERSION = 1.4;
]]></ac:plain-text-body></ac:macro>
<p>That eliminates all the repetitive <code>getVersion()</code> methods. Instead, the version can be retrieved with <code>Zend_Service_Rakuten::API_VERSION</code> in the event that someone needs it.</p>
<p>Minor class naming correction:</p>
<p><code>Zend_Service_Rakuten_CDSearch</code> => <code>Zend_Service_Rakuten_CdSearch</code><br />
<code>Zend_Service_Rakuten_DVDSearch</code> => <code>Zend_Service_Rakuten_DvdSearch</code></p>
<p>Is it possible to combine <code>HotelDetailSearch</code> and <code>VacantHotelSearch</code> into simply <code>HotelSearch</code>? Likewise for <code>ItemSearch</code> and <code>ItemCodeSearch</code>.</p>
Mar 28, 2007
TERUI Shingo
<p>Thank you for your comment.</p>
<p>class name of "Zend_Service_Rakuten_*" depends on the name of API of Rakuten Web Service.<br />
I am mending the design of these class now.<br />
I will renew the script and Wiki on the week first of April. </p>
<ac:macro ac:name="code"><ac:parameter ac:name="title">Example</ac:parameter><ac:parameter ac:name="borderStyle">solid</ac:parameter><ac:default-parameter>php</ac:default-parameter><ac:plain-text-body><![CDATA[
$item = new Zend_Service_Rakuten_Item($devId);
$itemResultSet = $item->keyword('DS-Lite')
>hits(3)>search();$itemCodeResult = $item->searchItemCode('ko-cho:570418');
$catalog = new Zend_Service_Rakuten_Catalog($devId);
$catalogResultSet = $catalog->keyword('display')
>hits(10)>search();$hotel = new Zend_Service_Rakuten_Hotel($devId);
$hotelDetailResult = $hotel->searchDetail('123456');
$hotelVacantResultSet = $hotel->largeClass('japan')
->middleClass('okinawa')
->checkinDate('2007-07-01')
->checkoutDate('2007-07-05')
->adultNum(2)
->chesearchVacant();
]]></ac:plain-text-body></ac:macro>
May 23, 2007
TERUI Shingo
<p>I updated wiki on May 21.</p>
<p>I classified inquiry classes in 'Zend_Service_Rakuten_Item' and 'Zend_Service_Rakuten_Travel'.<br />
'Zend_Service_Rakuten_Item' contains a function about shopping mall.<br />
'Zend_Service_Rakuten_Travel' contains a function about 'Rakuten Travel' service.</p>
Aug 07, 2007
Darby Felton
<p>Why are many methods indicated as <code>final</code>? Is there a good reason for this? Does this not hinder extensibility, or do we expect that no one would ever need to override these methods?</p>
<p>I have the same questions as above for all the <code>private</code> variables. Probably these should be <code>protected</code> unless there are good reasons?</p>
<p>I notice in the code inconsistent usage of <code>final</code> keyword with respect to its position in the function declaration (e.g., <code>final public</code> and <code>public final</code>). I would recommend to be consistent with <code>final public</code>, as documented in the PHP manual. (I admit that this is inconsistent with the recommendation of <code>public static</code>, since the keywords appear in different orders, but the consistency is with the PHP manual pages on these keywords. Either way may be fine, but we should be consistent.)</p>
<p>Here is an idea - what about having a <code>Zend_Service_Rakuten</code> class, through which both <code>Zend_Service_Rakuten_Item</code> and <code>Zend_Service_Rakuten_Travel</code> are readily accessible? This new class would conveniently provide access to all of the currently available Rakuten services and could support additional services released in the future. Maybe it could follow the spirit of the fluent interfaces already available throughout the proposed component:</p>
<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
require_once 'Zend/Service/Rakuten.php';
$rakuten = new Zend_Service_Rakuten(MY_RAKUTEN_ID);
$itemResultSet = $rakuten->item()
->keyword('DS-Lite')
->hits(3)
->search();
$itemCodeResult = $rakuten->item()
->searchItemCode('ko-cho:570418');
$simpleHotelResultSet = $rakuten->travel()
->largeClassCode('japan')
->middleClassCode('kanagawa')
->smallClassCode('hakone')
->search();
]]></ac:plain-text-body></ac:macro>
<p>The basic idea is to provide a single point of entry to the Rakuten web services consumer component for ZF. If this is not a good idea, why not?</p>
<p>If such a thing would be useful and convenient, would the first-level methods such as <code>item()</code> and <code>travel()</code> return new instances each time they are called, or are the instances cached within the class (e.g., as <code>static</code> members) for reuse?</p>
Sep 18, 2007
Akihiro Okabe
<p>> Why are many methods indicated as final?...</p>
<p>I read these scripts and can understand from these as follows.<br />
The all of final method are used in abstract class that are closely based on the specification of Rakuten API.<br />
I think that these should not be extended by end user. If someone needs to extend these, we will hear that the time when this component should have been changed come. Till then, he does not need to use this component by force. He can call Rakuten API directly.<br />
Please excuse since I did not necessarily ask Terui-san, when there is a misapprehension. But what do you think about my opinion?</p>
<p>> I notice in the code inconsistent usage of final keyword with respect to its position in the function declaration...</p>
<p>We have to repair this matter. I also think that sauce should follow the manual.</p>
<p>> Here is an idea...</p>
<p>Your idea looks excellent!! It seems that the reason for resisting this does not have anything. We may create new file 'Zend/Service/Rakuten.php' having Zend_Service_Rakuten class.</p>
Oct 30, 2007
Darby Felton
<p>Any word on updating the proposal to reflect the latest commentary?</p>
Nov 21, 2007
old of Satoru Yoshida
<p>Hello, I rewrited.<br />
Now we can use all methods by only including Zend_Service_Rakuten class.<br />
And no final and private keywords.</p>
Dec 19, 2007
old of Satoru Yoshida
<p>Oh! thank you for reading this pages and very quick response. <ac:emoticon ac:name="smile" /> I will think about it carefully.</p>
Nov 27, 2007
Simone Carletti
<p>What about returning a result object (and perhaps collected in a resultset object) instead of delegating to the developer the need to use an XPath query?<br />
I find the latter approach a little uncomfortable because requires the developer to have a deep knowledge of Rakuten XML response structure.</p>
<p>For instance, looking at UC-01 now I know that the following one is the best XPath expression for items</p>
<ac:macro ac:name="code"><ac:plain-text-body><![CDATA//itemSearch:ItemSearch/Items/Item]></ac:plain-text-body></ac:macro>
<p>But does it fit a <a href="http://webservice.rakuten.co.jp/api/catalogsearch/">catalog search</a> as well?</p>
<p>I would suggest to incorporate xpath query within the main class and let the user focus on reading result objects instead of querying XML.<br />
Additionally, the fact that API documentation is only available in Japanese requires to avoid (or at least reduce) the need for the developer to read it.</p>
<p>Reading previous feedbacks, it seems a similar proposal was posted by Darby Felton a few comments ago.</p>
Dec 05, 2007
Darby Felton
<p>I think that Simone deserves the credit for this suggestion, which I support. I definitely see added value from encapsulating the implementation (e.g., xpath queries) with easy-to-use, object-oriented goodness. <ac:emoticon ac:name="smile" /></p>
Dec 11, 2007
old of Satoru Yoshida
<p>Hello, Derby, Thank you for advice.</p>
<p>I improve this component just today, I expect advices from you if you have time to read this. <ac:emoticon ac:name="smile" /></p>
Dec 11, 2007
old of Satoru Yoshida
<p>Hello, Simone. Thank you for comment.</p>
<p>I change this component to move xpath() into each methods for developers having no need to querying XML.</p>
<p>Unfortunately, the Rakuten, Inc. has no english docments, but is used by 18 million peoples. (at Jan. 2006)<br />
It is greater than Amazon.co.jp that has 16 million customers.<br />
Therefore Zend_Service_Rakuten will be used by many Japanese , I think.</p>
Dec 11, 2007
Simone Carletti
<blockquote><p>I change this component to move xpath() into each methods for developers having no need to querying XML.</p></blockquote>
<p>It definitely looks more friendly now. <ac:emoticon ac:name="smile" /><br />
I have a few random feedbacks.</p>
<p><strong>1. method names</strong></p>
<p>I noticed method names doesn't seem to follow an unique guideline.<br />
Some method names originate from Rakuten API name </p>
<ul>
<li>searchItem --> ItemSearch</li>
<li>searchBook --> BookSearch</li>
<li>searchCd --> CdSearch</li>
</ul>
<p>but other names doens't seem to follow any convention</p>
<ul>
<li>getItemInfo <span style="text-decoration: line-through;">?</span>> ItemCodeSearch</li>
<li>getGenreInfo <span style="text-decoration: line-through;">?</span>> GenreSearch</li>
<li>searchHotel <span style="text-decoration: line-through;">?</span>> SimpleHotelSearch</li>
</ul>
<p>I would suggest to define a reasonable convention and follow it for naming all methods.<br />
For instance, according to initial standard the last three methods should be called</p>
<ul>
<li>searchItemCode <-- ItemCodeSearch</li>
<li>searchGenre <-- GenreSearch</li>
<li>searchSimpleHotel <-- SimpleHotelSearch</li>
</ul>
<p><strong>2. get vs search</strong></p>
<p>Some search methods uses are prefixed by <strong>get</strong> keyword while others by <strong>search</strong>.</p>
<p>Again, I would suggest to find a reasonable convention.<br />
You probably would use <strong>search</strong> instead of <strong>get</strong> and reserve the latter for attribute getter methods of an object.</p>
<p><strong>3. Use exceptions when applicable</strong></p>
<p>Looking at use cases I noticed the use of getErrorMessage() to check whether the response is successful.</p>
<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
$params = array('keyword' => 'Zend Studio', 'hits' => 3);
$results = $rakuten->searchItem($params);
$error = $rakuten->getErrorMessage();
if ($error !== null) {
/* error message from the Rakuten Web Service.
*/
echo $error;
}
]]></ac:plain-text-body></ac:macro>
<p>I personally find this approach a little uncomfortable because requires the developer to test the response against a collection of error messages.<br />
Additionally, it doesn't benefit from Exceptions and object oriented programming.</p>
<p>I would suggest to improve your search method(s) in order to raise an exception when an error occurs and let the developer use a try/catch block to handle the problem.<br />
The developer side code would be something like: </p>
<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
$params = array('keyword' => 'Zend Studio', 'hits' => 3);
try {
$results = $rakuten->searchItem($params);
} catch(Zend_Service_Rakuten_Exception $e) {
echo 'An error occured: ' . $e->getMessage();
// you may want to set result array to an empty array
$results = array();
}
]]></ac:plain-text-body></ac:macro>
<p><strong>4. _search() and Exceptions</strong></p>
<p>A similar approach to Exception usage (point 3) could be used for _<em>search</em> method.<br />
You may want to change _<em>search</em> method in order to return result object on success and raise an Exception on failure.</p>
<p>Catching the error will be in charge of the end user (developer) as described before and you don't need to perform the following check on each _search() request:</p>
<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[if($this->_search('GenreSearch', self::VERSION_GENRESEARCH, $params)) { // should be === true ]]></ac:plain-text-body></ac:macro>
<p>Additionally, this behavior allows you to convert _<em>search</em> method into a static method if you believe this approach fits your needs.</p>
<p><strong>5. helper response method</strong></p>
<p>Changes 3. and 4. provide you the ability to simplify search*() method.<br />
You can define a custom helper to run xpath() and return a normalized result that would be the array of data on success or an empty array if no result is available.</p>
<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
protected static function _run_xpath_and_normalize_response($path, SimpleXMLElement $simplexml)
{
$result = $simplexml->xpath($path);
return is_array($result) ? $result : array();
// the following statement would probably cause the same result
// return (array) $simplexml->xpath($path);
}
]]></ac:plain-text-body></ac:macro>
<p>All search method will be simplified to</p>
<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
public function searchItemByCatalog($params)
{
$response = self::_search('CatalogSearch', self::VERSION_CATALOGSEARCH, $params));
return $this->_run_xpath_and_normalize_response('//catalogSearch:CatalogSearch/Catalogs/Catalog', $response);
}
]]></ac:plain-text-body></ac:macro>
<p>As I said above, I just wanted to share with you some <strong>personal feedbacks</strong>. <ac:emoticon ac:name="smile" /><br />
Feel free to follow or ignore them.</p>
Dec 11, 2007
Darby Felton
<p>Thanks, Simone, for the excellent feedback! <ac:emoticon ac:name="smile" /></p>
Dec 14, 2007
old of Satoru Yoshida
<p>Hello, Simone. Thank you for advices. I make some responces to you <ac:emoticon ac:name="smile" /></p>
<p> about <strong>No.1</strong> .<br />
I think these API's name are japanized english <ac:emoticon ac:name="sad" /> . I name these functions by their definition.</p>
<p>At first, <strong>ItemCodeSearch</strong> API is described as "This API retrieves item's <strong>information</strong> by item's code." in the document.<br />
This API does not return more than one items, but only one item specified by the code. So, I use <strong>get</strong> instead of <strong>search</strong> in <strong>getItemInfo</strong>.</p>
<p>At second, <strong>GenreSearch</strong> does not usually mean "This API returns genre." . In the document, "This API returns name and structure of genre". <br />
Therefore, I name the one of methods <strong>getGenreInfo</strong> . </p>
<p>At last, <strong>SimpleHotelSearch</strong> is named to be contrasted with <strong>HotelDetailSearch</strong> , I think.<br />
But <strong>HotelDetailSearch</strong> does not search hotel in detail, but returns detailed information about hotel identified by hotel's No.<br />
So, SimpleHotelSearch does not mean search hotels <strong>simply</strong>.</p>
<p> about <strong>No.2</strong><br />
I understand your advice that <strong>get</strong> would be reserved for attribute getter method.<br />
For example, how about changing into following ?</p>
<p>retrieveItemInfo <-- ItemCodeSearch</p>
Dec 19, 2007
old of Satoru Yoshida
<p>Hello, Simone. I changed to use exception from getErrorMessage.<br />
And I add new methods as the Rakuten Inc. incleases APIs.</p>
Dec 19, 2007
Simone Carletti
<p>Great! <ac:emoticon ac:name="smile" /></p>
<p>I'm sorry, I just noticed I didn't answer your previous comment.</p>
<blockquote><p>At first, ItemCodeSearch API is described as "This API retrieves item's information by item's code." in the document.<br />
This API does not return more than one items, but only one item specified by the code. So, I use get instead of search in getItemInfo.</p></blockquote>
<p>Your explanation may appear correct, however IMHO it's quite difficult that an end user will read all the documentation provided by Rakuten and will be able to evaluate it as you did.<br />
He will probably read just the most common steps (if we are lucky, or he won't probably read it at all!) and will try to find a corrispondence between Rakuten names and Zend_Service_Rakuten class.</p>
<p>This is why I suggest to define a close correspondence between method calls and Rakuten API names.</p>
<p>I have a question for you.<br />
Does the following API call has some mandatory arguments?<br />
According to <a class="external-link" href="http://translate.google.com/translate?u=http%3A%2F%2Fwebservice.rakuten.co.jp%2Fapi%2Fdvdsearch%2F&langpair=ja%7Cen&hl=en&ie=UTF-8">http://translate.google.com/translate?u=http%3A%2F%2Fwebservice.rakuten.co.jp%2Fapi%2Fdvdsearch%2F&langpair=ja%7Cen&hl=en&ie=UTF-8</a> it seems that <em>Keyword</em> is requested.</p>
<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
/**
*
*/
public function searchDvd($params)
]]></ac:plain-text-body></ac:macro>
<p>If so, I would suggest to move mandatory arguments from $params array directly to method definition.<br />
This will cause PHP parser to raise an Exception at your place whether a mandatory element is not provided.</p>
<p>It seems you already used this technique elsewhere, for instance <em>getItemInfo</em> method.<br />
$code is included in method definition and $params is reserved for optional parameters.</p>
<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
/**
*
*/
public function getItemInfo($code, $optparams = array())
]]></ac:plain-text-body></ac:macro>
Dec 21, 2007
old of Satoru Yoshida
<p>Thank you for reading and advicing very quickly! <ac:emoticon ac:name="smile" /></p>
<p>At first, I agree about that end user may <strong>not</strong> read <strong>all</strong> documents.<br />
So, I will change names to useItemCodeSearch (use + API name) or like as searchItemCode.</p>
<p>At second, the code is usually mandatory arguments in the getItemInfo(), but unusually the keyword in searchDvd().<br />
In searchDvd(), one of keyword <strong>or</strong> genreId is needed.</p>
<p>Do you think it is better to check whether one of arguments is not null? </p>
Dec 11, 2007
Darby Felton
<p>I cannot see that there is any functionality provided by <code>Zend_Service_Rakuten_Abstract</code> (only constants), and it does not appear that any other classes besides <code>Zend_Service_Rakuten</code> would inherit from <code>Zend_Service_Rakuten_Abstract</code>. These things being the case, it seems that the abstract class does not add any value. I would recommend simply having those constants in the <code>Zend_Service_Rakuten</code> class and doing away with the abstract class, or am I missing something?</p>
<p>Another concern of mine is how to change the versions of the web services, when they are updated. Having to modify a class constant to do so is not so good. I understand that the constants could be used to set the <em>default</em> values, but probably there should be another way to change the version values, such as in the following:</p>
<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
$rakuten = new Zend_Service_Rakuten(YOUR_DEVELOPER_ID);
$rakuten->setVersion('genreSearch', '2008-01-01');
]]></ac:plain-text-body></ac:macro>
<p>The above is just an example; maybe there is a better way.</p>
<p>Probably several of the other values currently stored in constants should be modifiable through the class API, as well.</p>
Dec 19, 2007
old of Satoru Yoshida
<p>Hello, Darby.<br />
I rewrite this component to be able to specify version.<br />
I added getVersion and setVersion methods. </p>
May 14, 2008
Wil Sinclair
<p>I believe this proposal is at a stage that is most appropriate for our re-defined 'ready for review' section. I will move it there now.</p>
<p>Satoru, this proposal seems relatively mature. Are you still working on it? I would love to see you drive this to inclusion in one of the libraries; it seems to be very much in demand with our Japanese users.</p>
<p>Thanks.<br />
,Wil</p>
May 15, 2008
old of Satoru Yoshida
<p>Thank you for your comment, Wil. I agree to move this component to the 'ready for review' section.</p>
<p>However, unfortunately, I am not working on this proposals.<br />
If anyone want to work on this, I will be happy.</p>
<p>Satoru.</p>
Nov 27, 2008
old of Satoru Yoshida
<p>At first, I made APIs correspond from version 1.10 to 1.12.</p>
<p>1) The ItemRanking() is new API.<br />
2) The VacantHotelSearch API request new required parameters.<br />
3) URI format of the DynamicAd API was extended.</p>
<p>At second, I unified several functions.<br />
1)searchGenreParent() and searchGenreChildren() into searchGenre().<br />
searchGenre() requires new parameter, $type.</p>
<p>2)searchVacantHotelRoom() into searchVacantHotel().<br />
searchVacantHotel() also requires new parameter, $type.</p>
<p>At last, I implemented the checking of the required parameters on many functions.</p>
Dec 30, 2008
Ralph Schindler
<ac:macro ac:name="note"><ac:parameter ac:name="title">Zend Official Comment</ac:parameter><ac:rich-text-body>
<p>This component has been accepted for development inside the <strong>Extras Incubator</strong>.</p>
<p>It appears as though this component has been very well thought out and as such, (along with the popularity of this service within specific regions), it is accepted to the ZendX extras incubator.</p>
<p>There are two concerns I would additionally like to discuss:</p>
<ul>
<li>there are a few methods that indicate they will be "doing some action" but do not contain any verbs, is it possible to review this part of the API? For example:
<ul>
<li>There are a few methods in the use cases that are not preceded by "search" or "get", this makes it hard to understand what the methods is intending to do and return.</li>
</ul>
</li>
<li>Can you address how the API on the server side changes over time and what _apiVer does and what it provides. Does this mean that the server API changes in such a way that is hard to maintain?</li>
</ul>
<p>Aside from those concerns, please feel free to get this in the Extras incubator to facilitate development.</p>
<p>-ralph</p>
</ac:rich-text-body></ac:macro>
Dec 31, 2008
old of Satoru Yoshida
<p>Thank you for accepting.</p>
<p>At first, I think you take care of the itemRanking() and the dynamicAd().</p>
<p>If method name can be differ from API name, I have an idea that itemRanking() may be changed to getRanking() and dynamicAd() also may be changed to getAdvertisements().<br />
(Please refer comments from Mr Simone Carletti last year)</p>
<p>At second, the server changes will be shown leftside in <a class="external-link" href="http://webservice.rakuten.co.jp/">http://webservice.rakuten.co.jp/</a> .<br />
And I will write document how to know the new values of API versions.</p>
<p>For example, we can find the version of the ItemSearch API by looking topside of <a class="external-link" href="http://webservice.rakuten.co.jp/api/itemsearch/">http://webservice.rakuten.co.jp/api/itemsearch/</a> .<br />
We can find a string '(version:2008-09-01)' there. The string '2008-09-01' is the value of _apiVer(<ac:link><ri:page ri:content-title="'ItemSearch'" /></ac:link>).</p>
<p>And we can find the value of 'api_rws' in bottom side of <a class="external-link" href="http://webservice.rakuten.co.jp/document/index.html">http://webservice.rakuten.co.jp/document/index.html</a> .<br />
There is explanation of url format, and version of the Rakuten Web Service is shown as following.</p>
<p>'<ac:link><ri:page ri:content-title="version" /></ac:link>xxxxxxxxxxxxxxxxxxxxxxxx1.12xxxxx' (x is instead of Japanese characters)<br />
The sentence means, '<ac:link><ri:page ri:content-title="version" /></ac:link> is version of the Rakuten Web Service. The last value is 1.12 now.'</p>
<p>At last, I will be happy if this responce will be useful. </p>
<p>Satoru Yoshida</p>
Mar 18, 2009
Wil Sinclair
<p>Satoru, do you plan to finish this for the 1.8 release?</p>
Mar 18, 2009
old of Satoru Yoshida
<p>Hello, Wil.</p>
<p> I will finish to make unit tests at May 10th .<br />
Sadly, now I am caught by oci extension trouble from my customer long time.</p>
<p> I should schedule to end more early ?</p>
Mar 19, 2009
Wil Sinclair
<p>Did you mean May or March? We'll probably have 1.8 code freeze in the middle of April.</p>
<p>,Wil</p>
Mar 22, 2009
old of Satoru Yoshida
<p>Hi, Wil.</p>
<p>I schedule to work from 29/April/2009 to 10/May/2009.</p>
<p>Unfortunately, I am in trouble now. <ac:emoticon ac:name="sad" /></p>
<p>Satoru Yoshida</p>
May 11, 2009
old of Satoru Yoshida
<p>Hello, <br />
I will be happy if you will close and archive this .</p>