Zend Certified Engineer
Seit Montag gehöre ich zu den aktuell 371 zertifizierten PHP5-Entwicklern in Deutschland, ich darf mich nun also „Zend Certified Engineer“ nennen *jubel*! Hier ist der Beweis, meine eigene Seite in den Zend-Yellow-Pages.
Bereits letztes Jahr kam die Idee, sich an diese Aufgabe zu wagen, doch nachdem ich mir Lektüre besorgt hatte (PDFs mit mehreren hundert Seiten) sowie einige gute Blogeinträge zu dem Thema gefunden hatte, habe ich es doch wieder einige Monate schleifen lassen, man hat ja „wichtigeres zu tun“. Ich hatte mir außerdem 10 „Online Praxis Tests“ gekauft, die Mitte diesen Jahres ablaufen, und so habe ich mich die letzten 2 Wochen nochmal intensiv reingekniet. Nachdem alle ausgedruckten Seiten durchgearbeitet waren habe ich 4 Online-Praxis-Tests gemacht, die ich alle direkt mit „Excellent“ bestanden habe, und so habe ich kurzerhand am Sonntag Nachmittag einen Termin für die Prüfung festgemacht: Montag morgen 9 Uhr in Bielefeld. Weiterlesen »
Sockets, Streams und Streamfilter
In einem älteren Artikel schrieb ich bereits über Socket Server in PHP, heute möchte ich etwas sehr ähnliches vorstellen, jedoch mittels Streams, wo uns andere Möglichkeiten zur Verfügung stehen.
Ich möchte nun also auf einen Socket, sprich häufig einen TCP-Port, zugreifen und ihn als Datenstrom behandeln. Dazu erstellen wir erstmal einen Server, der auf Port 1037 lauscht und bei einer Verbindung einen String zurückliefert.
<?php $socket = stream_socket_server('tcp://0.0.0.0:1037'); while ($conn = stream_socket_accept($socket)) { fwrite($conn, "Hallo, hier spricht der Server.\n"); fclose($conn); } fclose($socket);
Linkpool Nummer 5
Was für eine aufregende Woche: Polen verliert ihr Präsidentenpaar, in Afghanistan fallen deutsche Soldaten, eine Aschewolke nebelt Europa ein, ein Video „Collateral Murder“ aus dem Irak taucht bei Wikileaks auf. Aber auch in der IT-Welt gibt es hier und da interessante News und Blogeinträge:
Deployment kurz und gut zusammengefasst in einer Präsentation:
Mit HTML5 verlieren wir einige alte HTML-Tags:
Mocks beim Testen:
OAuth für IMAP und SMTP:
Daten rauszugeben an ein Medium das nicht vergisst kann Schaden verursachen:
Ein Zend_Form Validator über mehrere Felder (Passwort wiederholen):
Ich hatte leider noch keine Zeit, Googles neue Sicherheits-Test–Software auszuprobieren:
phpMyAdmin Timeout erhöhen:
Mit der eBay-API seine Auktionen beobachten
Nach dem letzten Artikel über die eBay-API und das Erstellen von Auktionen wollen wir nun unsere Auktionen beobachten und Informationen periodisch abfragen. Damit können wir uns selbst beispielsweise eine tägliche Übersicht senden oder die Auktionen auf unserer Webseite darstellen.
Die entsprechende API-Funktion heißt GetSellerList, sie liefert uns Informationen über unsere Auktionen eines bestimmten Zeitraums. Wenn man detaillierte Informationen über bereits verkaufte Artikel haben möchte muss man GetSellerTransactions nutzen. Hier stelle ich erstere vor.
Wie bereits im ersten Artikel stelle ich euch hier ein Basis-Script vor, natürlich sollte man das noch umbauen und erweitern, aber zur Erklärung der Funktionalität reicht es aus. Wir bereiten hier einen XML-Request vor mit den entsprechenden Parametern und erhalten eine XML-Antwort, die wir mittels DomDocument auseinander nehmen und die Informationen extrahieren. Hier also das Script:
<?php $addItem = new eBayGetSellerList(); $addItem->callEbay(); $addItem->printResult(); class eBayGetSellerList { private $_siteId = 77; // default: Germany private $_environment = 'sandbox'; // toggle between sandbox and production private $_eBayApiVersion = 661; private $_call = 'GetSellerList'; private $_keys = array( 'production' => array( 'DEVID' => '', 'AppID' => '', 'CertID' => '', 'UserToken' => '', 'ServerUrl' => 'https://api.ebay.com/ws/api.dll' ), 'sandbox' => array( 'DEVID' => '6daxxxxxxxxxxxxxxxxxxxxxxxxxx1e4622', 'AppID' => 'Mixxxxxxxxxxxxxxxxxxxxxxxxxxxxxx930', 'CertID' => '68xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx00e', 'UserToken' => 'AgAxxxxxxxxlaaaangxxxxxxxxxxIrGgYZ', 'ServerUrl' => 'https://api.sandbox.ebay.com/ws/api.dll' ) ); private function _getRequestBody() { $apiValues = $this->_keys[$this->_environment]; $dateNow = time(); $date4weeksAgo = $dateNow-60*60*24*28; $search = array( '%%USER_TOKEN%%', '%%EBAY_API_VERSION%%', '%%STARTTIMEFROM%%', '%%STARTTIMETO%%' ); $replace = array( $apiValues['UserToken'], $this->_eBayApiVersion, date('Y-m-d\TH:i:s.000\Z', $date4weeksAgo), date('Y-m-d\TH:i:s.000\Z', $dateNow) ); $requestXmlBody = file_get_contents('GetInfo.xml'); $requestXmlBody = str_replace($search,$replace, $requestXmlBody); return $requestXmlBody; } public function callEbay() { $apiValues = $this->_keys[$this->_environment]; $connection = curl_init(); curl_setopt($connection, CURLOPT_URL, $apiValues['ServerUrl']); curl_setopt($connection, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($connection, CURLOPT_SSL_VERIFYHOST, 0); $headers = array ( 'X-EBAY-API-COMPATIBILITY-LEVEL: ' . $this->_eBayApiVersion, 'X-EBAY-API-DEV-NAME: ' . $apiValues['DEVID'], 'X-EBAY-API-APP-NAME: ' . $apiValues['AppID'], 'X-EBAY-API-CERT-NAME: ' . $apiValues['CertID'], 'X-EBAY-API-CALL-NAME: ' . $this->_call, 'X-EBAY-API-SITEID: ' . $this->_siteId, ); curl_setopt($connection, CURLOPT_HTTPHEADER, $headers); curl_setopt($connection, CURLOPT_POST, 1); $requestBody = $this->_getRequestBody(); curl_setopt($connection, CURLOPT_POSTFIELDS, $requestBody); curl_setopt($connection, CURLOPT_RETURNTRANSFER, 1); $responseXml = curl_exec($connection); curl_close($connection); $this->_responseXml = $responseXml; var_dump($responseXml); } public function printResult() { //Xml string is parsed and creates a DOM Document object $responseDoc = new DomDocument(); $responseDoc->loadXML($this->_responseXml); //get any error nodes $errors = $responseDoc->getElementsByTagName('Errors'); //if there are error nodes if($errors->length > 0) { echo '<P><B>eBay returned the following error(s):</B>'; //display each error //Get error code, ShortMesaage and LongMessage $code = $errors->item(0)->getElementsByTagName('ErrorCode'); $shortMsg = $errors->item(0)->getElementsByTagName('ShortMessage'); $longMsg = $errors->item(0)->getElementsByTagName('LongMessage'); //Display code and shortmessage echo '<P>', $code->item(0)->nodeValue, ' : ', str_replace(">", ">", str_replace("<", "<", $shortMsg->item(0)->nodeValue)); //if there is a long message (ie ErrorLevel=1), display it if(count($longMsg) > 0) { echo '<BR>', str_replace(">", ">", str_replace("<", "<", $longMsg->item(0)->nodeValue)); } } else { //no errors //get results nodes $responses = $responseDoc->getElementsByTagName("GetSellerListResponse"); foreach ($responses as $response) { $acks = $response->getElementsByTagName("Ack"); $ack = $acks->item(0)->nodeValue; echo "Ack = $ack <BR />\n"; // Success if successful $totalNumberOfEntries = $response->getElementsByTagName("TotalNumberOfEntries"); $totalNumberOfEntries = $totalNumberOfEntries->item(0)->nodeValue; echo "totalNumberOfEntries = $totalNumberOfEntries <BR />\n"; $items = $response->getElementsByTagName("Item"); for($i=0; $i<$totalNumberOfEntries; $i++) { $itemId = $items->item($i)->getElementsByTagName('ItemID')->item(0)->nodeValue; $itemUrl = $items->item($i)->getElementsByTagName('ViewItemURL')->item(0)->nodeValue; $startTime = $items->item($i)->getElementsByTagName('StartTime')->item(0)->nodeValue; $endTime = $items->item($i)->getElementsByTagName('EndTime')->item(0)->nodeValue; $bidCount = $items->item($i)->getElementsByTagName('BidCount')->item(0)->nodeValue; $priceInEUR = $items->item($i)->getElementsByTagName('ConvertedCurrentPrice')->item(0)->nodeValue; $status = $items->item($i)->getElementsByTagName('ListingStatus')->item(0)->nodeValue; $title = $items->item($i)->getElementsByTagName('Title')->item(0)->nodeValue; $watchCount = $items->item($i)->getElementsByTagName('WatchCount')->item(0)->nodeValue; echo "itemID = $itemId <BR />\n"; echo "itemURL = $itemUrl <BR />\n"; echo "startTime = $startTime <BR />\n"; echo "endTime = $endTime <BR />\n"; echo "bidCount = $bidCount <BR />\n"; echo "priceInEUR = $priceInEUR <BR />\n"; echo "status = $status <BR />\n"; echo "title = $title <BR />\n"; echo "watchCount = $watchCount <BR />\n"; } } } } }
Die GetInfo.xml sieht folgendermaßen aus:
<?xml version="1.0" encoding="UTF-8"?> <GetSellerListRequest xmlns="urn:ebay:apis:eBLBaseComponents"> <RequesterCredentials> <eBayAuthToken>%%USER_TOKEN%%</eBayAuthToken> </RequesterCredentials> <ErrorLanguage>en_US</ErrorLanguage> <Version>%%EBAY_API_VERSION%%</Version> <GranularityLevel>Coarse</GranularityLevel> <IncludeWatchCount>true</IncludeWatchCount> <StartTimeFrom>%%STARTTIMEFROM%%</StartTimeFrom> <StartTimeTo>%%STARTTIMETO%%</StartTimeTo> <Pagination> <EntriesPerPage>200</EntriesPerPage> <PageNumber>1</PageNumber> </Pagination> <WarningLevel>High</WarningLevel> </GetSellerListRequest>
Bevor es funktioniert muß man natürlich noch seine API-Keys einfügen, siehe erster Artikel. Um die printResult() Funktion besser zu verstehen hier ein Bespiel des $responseXml:
<?xml version="1.0" encoding="UTF-8"?> <GetSellerListResponse xmlns="urn:ebay:apis:eBLBaseComponents"> <Timestamp>2010-04-3T11:25:37.003Z</Timestamp> <Ack>Success</Ack> <Version>661</Version> <Build>E661_INTL_BUNDLED_10949245_R1</Build> <PaginationResult> <TotalNumberOfPages>1</TotalNumberOfPages> <TotalNumberOfEntries>8</TotalNumberOfEntries> </PaginationResult> <HasMoreItems>false</HasMoreItems> <ItemArray> <Item> <AutoPay>false</AutoPay> <BuyerProtection>ItemIneligible</BuyerProtection> <Country>US</Country> <Currency>USD</Currency> <GiftIcon>0</GiftIcon> <HitCounter>NoHitCounter</HitCounter> <ItemID>110044434434</ItemID> <ListingDetails> <StartTime>2010-03-27T12:44:13.000Z</StartTime> <EndTime>2010-03-28T12:44:13.000Z</EndTime> <ViewItemURL>http://cgi.sandbox.ebay.de/ws/eBayISAPI.dll?ViewItem&item=110044434434&category=14111</ViewItemURL> <HasUnansweredQuestions>false</HasUnansweredQuestions> <HasPublicMessages>false</HasPublicMessages> <BuyItNowAvailable>true</BuyItNowAvailable> <ExpressListing>false</ExpressListing> </ListingDetails> <ListingDuration>Days_1</ListingDuration> <Location>San Jose, CA</Location> <PrimaryCategory> <CategoryID>14111</CategoryID> <CategoryName>Everything Else:Test Auctions:General</CategoryName> </PrimaryCategory> <Quantity>1</Quantity> <ReviseStatus> <ItemRevised>false</ItemRevised> </ReviseStatus> <SellingStatus> <BidCount>0</BidCount> <BidIncrement currencyID="USD">0.25</BidIncrement> <ConvertedCurrentPrice currencyID="EUR">1.26</ConvertedCurrentPrice> <CurrentPrice currencyID="USD">1.71</CurrentPrice> <MinimumToBid currencyID="USD">1.71</MinimumToBid> <QuantitySold>0</QuantitySold> <SecondChanceEligible>false</SecondChanceEligible> <ListingStatus>Completed</ListingStatus> </SellingStatus> <ShippingDetails> <TaxTable/> </ShippingDetails> <ShipToLocations>US</ShipToLocations> <Site>US</Site> <TimeLeft>PT0S</TimeLeft> <Title>TTTEST IN SANDBOX BEFORE PROD - DO NOT BID</Title> <WatchCount>0</WatchCount> <PostalCode></PostalCode> <PictureDetails> <PhotoDisplay>None</PhotoDisplay> </PictureDetails> <ProxyItem>false</ProxyItem> <BuyerGuaranteePrice currencyID="EUR">20000.0</BuyerGuaranteePrice> <ReturnPolicy> <ReturnsAcceptedOption>ReturnsNotAccepted</ReturnsAcceptedOption> <ReturnsAccepted>Returns Not Accepted</ReturnsAccepted> </ReturnPolicy> <PaymentAllowedSite>US</PaymentAllowedSite> </Item> ..... ..... </ItemArray> <ItemsPerPage>200</ItemsPerPage> <PageNumber>1</PageNumber> <ReturnedItemCountActual>8</ReturnedItemCountActual> </GetSellerListResponse>
Man erkennt natürlich einige Parallelen zur Auktionserstellung und kann das schön in eine Elternklasse auslagern.
Nachdem ich diese Funktion umgesetzt hatte, habe ich noch GetMyeBaySelling gefunden, mit der man die einzelnen Listen (ActiveList, BidList, DeletedFromSoldList, DeletedFromUnsoldList, ScheduledList, SoldList und UnsoldList) erhält, was natürlich sehr viel nützlicher ist.
International PHP Conference in Berlin und PHP Unconference in Hamburg
Letztes Wochenende wurde der Ticketverkauf der PHP Unconference 2010 in Hamburg gestartet, und nur 6 Tage später waren die 200 Tickets ausverkauft, Wahnsinn! Auch dieses Jahr werde ich wieder mit von der Partie sein, letztes Jahr war spitze und ich bin mir sicher dass ich auch dieses Jahr wieder viel Neues mit nach Hause nehmen werde.
Gestern habe ich noch eine gute Nachricht bekommen: Ich werde dieses Jahr auch zur International PHP Conference Spring Edition 2010 fahren, mein Arbeitgeber mail.de hat mir das OK gegeben und spendiert mir einen mehrtägigen Besuch in Berlin. Danke Fabian, du bist der Beste!
Jetzt muß ich nur noch für die jeweiligen Termine Hotels finden in Berlin bzw. Hamburg. Falls jemand einen Geheimtipp für günstige Unterkünfte hat, nur her damit, ansonsten werd ich es über die zahlreichen Hotel-Bewertungs-Such-Seiten versuchen.
Wer von euch ist noch auf einer der beiden Konferenzen, dann kann man sich evtl. die Gesichter schonmal bei Xing und Co. angucken. Ich hoffe den ein oder anderen Leser dort zu treffen und vielleicht ein kleines Pläuschchen zu halten.