<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>TheGeek.de &#187; api</title>
	<atom:link href="http://thegeek.de/t/api/feed" rel="self" type="application/rss+xml" />
	<link>http://thegeek.de</link>
	<description>WordPress, PHP, JavaScript, Web 2.0, Gaming, Motorräder, Fotografie, Piratenpartei, Privates</description>
	<lastBuildDate>Tue, 09 Mar 2010 16:09:05 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Twempy der twitternde Software Roboter</title>
		<link>http://thegeek.de/twempy-der-twitternde-software-roboter</link>
		<comments>http://thegeek.de/twempy-der-twitternde-software-roboter#comments</comments>
		<pubDate>Sat, 12 Dec 2009 12:49:36 +0000</pubDate>
		<dc:creator>Marc</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[bot]]></category>
		<category><![CDATA[chat]]></category>
		<category><![CDATA[ki]]></category>
		<category><![CDATA[selbstlernend]]></category>
		<category><![CDATA[twempy]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://thegeek.de/?p=411</guid>
		<description><![CDATA[Ich habe meine Idee, ein selbstständig twitterndes Programm zu schreiben, nun weitgehend in die Tat umgesetzt. Twempy arbeitet im Augenblick an seiner Antwort-Datenbank, antwortet aber bereits auf Anfragen, gibt gelegentlich seinen Status bekannt und twittert sogar manchmal seine Gedanken und Gefühle. ;-)
Die Qualität der Antworten lässt im Moment teilweise noch etwas zu wünschen übrig, da [...]]]></description>
			<content:encoded><![CDATA[<p>Ich habe meine Idee, ein <a href="http://thegeek.de/selbstlernender-chat-bot-mit-der-twitter-api">selbstständig twitterndes Programm</a> zu schreiben, nun weitgehend in die Tat umgesetzt. <a href="http://twitter.com/twempy">Twempy</a> arbeitet im Augenblick an seiner Antwort-Datenbank, antwortet aber bereits auf Anfragen, gibt gelegentlich seinen Status bekannt und twittert sogar manchmal seine Gedanken und Gefühle. ;-)<br />
Die Qualität der Antworten lässt im Moment teilweise noch etwas zu wünschen übrig, da die Datenbank der Antworten erst rund 220 Einträge umfasst, aber in der Stunde kommen im Schnitt 20 bis 30 neue Antworten hinzu.</p>
<p>Und so funktioniert es: Twempy sucht alle 5 Minuten nach Tweets mit bestimmten Schlüsselwörtern wie &#8220;und, er, sie, das, &#8230;&#8221;. Findet er einen passenden Tweet, ermittelt der Bot, ob es eine Antwort auf einen anderen Tweet war. Ist dies der Fall wird die Ursprungnachricht geladen und die Wörter extrahiert. Die Wörter werden danach verknüfpt mit dem Antwort-Tweet in einer Datenbank gespeichert. So bildet sich eine Relation von Wörtern zu tweets. Das schöne dabei ist, das Twempy im Grunde jetzt Sprache lernen kann, denn seine Datenbasis wird nicht durch den Programmierer beeinflusst, sondern ausschließlich aus echten Konversationen gebildet.</p>
<p>Erhält Twempy eine @reply (mention), extrahiert er die Wörter und schlägt in der Datenbank nach, welche Antworten passen könnten. Gibt es mehrere gleichwertige Antwortmöglichkeiten, wird zufällig eine mögliche Antwort ausgewählt und getwittert. Ich hoffe, dass die Qualität der Antworten mit wachsender Datenbank besser wird.</p>
<p>Ein weiteres nettes Feature ist, dass beim Lernen die Tweets, die nicht an einen anderen Twitter-Account gerichtet waren ebenfalls in der Datenbank gespeichert werden. Von Zeit zu Zeit twittert Twempy zufällig einen dieser Tweets. Danach wird die Nachricht gelöscht, damit er auf keinen Fall zwei Mal das gleiche sagt.</p>
<p>Offen ist noch, ob ich dieses Verfahren auch auf die Antworten, die der Bot sendet anwenden sollte, so dass auch niemals zwei Mal die gleiche Antwort gesendet werden könnte. Twempy würde seinen Antworten damit wieder verlernen, was aber auch das Risiko birgt, dass er irgendwann keine Antworten mehr parat hat. Da bin ich noch unschlüssig.</p>
<p>Wenn der Quellcode ausgereift ist, werde ich ihn veröffentlichen, aber ich muss noch etwas abwarten. Einige Dinge sind noch unklar, zum Beispiel die Frage, ob die Datenbasis besser wird, wenn nur Anworten gespeichert werden, die einen Ursprungstweet als Auslöser hatten, der nicht selbst ebenfalls eine Antwort auf einen anderen Tweet war. Mir ist nämlich aufgefallen, dass diese mitten aus der Konversation gegriffenen Antworten teilweise in keinem logischn Zusammenhang zu den verwendeten Wörtern stehen.</p>
<p>Es wird noch einige Tests benötigen, warten wir mal ab&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://thegeek.de/twempy-der-twitternde-software-roboter/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Spaß mit der Twitter API und Ausdruck des Protests gegenüber Harley Davidson</title>
		<link>http://thegeek.de/spas-mit-der-twitter-api-und-ausdruck-des-protests-gegenuber-harley-davidson</link>
		<comments>http://thegeek.de/spas-mit-der-twitter-api-und-ausdruck-des-protests-gegenuber-harley-davidson#comments</comments>
		<pubDate>Wed, 09 Dec 2009 12:54:30 +0000</pubDate>
		<dc:creator>Marc</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[buell]]></category>
		<category><![CDATA[harley davidson]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[protest]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://thegeek.de/?p=398</guid>
		<description><![CDATA[@moto1203 hat mich über Twitter kontaktiert und gefragt, ob es nicht irgendwie möglich sei ein Programm zu schreiben, dass bei bestimmten Hashtags eine @reply erzeugt. Thematisch ging&#8217;s konkret um den bekannten Motorradhersteller &#8220;Harley Davidson&#8221;, der kürzlich die Tochter- und Traditionsfirma &#8220;BUELL&#8221; einfach so dicht gemacht hat. Buell Motorräder wurden &#8220;nicht oft genug&#8221; verkauft, was aber [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://twitter.com/moto1203">@moto1203</a> hat mich über Twitter kontaktiert und gefragt, ob es nicht irgendwie möglich sei ein Programm zu schreiben, dass bei bestimmten Hashtags eine @reply erzeugt. Thematisch ging&#8217;s konkret um den bekannten Motorradhersteller &#8220;Harley Davidson&#8221;, der kürzlich die Tochter- und Traditionsfirma &#8220;BUELL&#8221; einfach so dicht gemacht hat. Buell Motorräder wurden &#8220;nicht oft genug&#8221; verkauft, was aber nichts daran ändert, das die Kisten ihren Markt hatten. Das fanden wir jedenfalls schon ziemlich kacke von Harley Davidson.</p>
<p>Also habe ich kurzerhand einen neuen Twitter-Account mit dem klangvollen Namen &#8220;<a href="http://twitter.com/subversives">@subversives</a>&#8221; erstellt und ein kleines PHP-Skript geschrieben, dass neue Tweets mit einem #harley Hashtag sucht und eine zufällig ausgewählte Antwort erstellt. Natürlich konfigurierbar. :-)<span id="more-398"></span></p>
<p>Dazu gibt es zwei kleine Funktionen. Die erste Funktion sucht Tweets nach einem bestimmten Suchbegriff:</p>
<pre class="brush:php">
// Twitter search api
function twt_search( $username, $password, $search, $since_id = 0, $rpp = 30, $page = 1 )
{
	// Curl init
	$curl = curl_init();

	// Curl basic settings
	curl_setopt( $curl, CURLOPT_URL, 'http://search.twitter.com/search.json' );
	curl_setopt( $curl, CURLOPT_RETURNTRANSFER, 1 );
	curl_setopt( $curl, CURLOPT_USERPWD, "$username:$password" );
	curl_setopt( $curl, CURLOPT_POST, true );

	// Build POST parameters
	$post_arr = array();
	$post_arr[] = "q=" . urlencode( $search );
	if( !empty( $since_id ) )
		$post_arr[] = "since_id=" . $since_id;
	if( !empty( $rpp ) )
		$post_arr[] = "rpp=" . $rpp;
	if( !empty( $page ) )
		$post_arr[] = "page=" . $page;
	curl_setopt( $curl, CURLOPT_POSTFIELDS, implode( '&#038;', $post_arr ) );

	// Exec, set return
	$return = json_decode( curl_exec( $curl ) );

	// Close curl
	curl_close( $curl );

	return $return;
}
</pre>
<p>Übergeben werden Benutzername, Passwort, der Suchbegriff und &#8211; wenn bekannt &#8211; auch die &#8220;since_id&#8221;, welche es ermöglicht nur Tweets mit einer höheren ID zu ermitteln. Das ist für unser lustiges Protest-Skript wichtig, denn wir wollen die Leute ja nicht zuspammen und immer wieder auf die gleichen Tweets antworten. Nur neue Tweets seit der letzten Suche sollen berücksichtigt werden, also merken wir uns einfach die höchste Tweet ID und übergeben diese wieder bei der nächsten Suche. Der Parameter &#8220;rpp&#8221; steht übrigens für &#8220;results per page&#8221; &#8211; mit der Voreinstellung werden also maximal 30 Tweets zurückgegeben.</p>
<p>Technisch wird die Abfrage über die CURL-Bibliothek realisiert, theoretisch ginge es aber auch mit &#8220;file_get_contents&#8221; oder &#8220;fopen&#8221;, aber ich mag CURL. Ist ganz praktisch.</p>
<p>Die zweite benötigte Funktion erstellt über die Twitter API einen neuen Tweet. Auch hier stehen wieder einige Parameter zur Verfügung:</p>
<pre class="brush:php">
// Twitter update api
function twt_update( $username, $password, $status, $in_reply_to_status_id = '', $lat = '', $long = '' )
{
	// Curl init
	$curl = curl_init();

	// Curl basic settings
	curl_setopt( $curl, CURLOPT_URL, 'http://twitter.com/statuses/update.json' );
	curl_setopt( $curl, CURLOPT_RETURNTRANSFER, 1 );
	curl_setopt( $curl, CURLOPT_USERPWD, "$username:$password" );
	curl_setopt( $curl, CURLOPT_POST, true );

	// Build POST parameters
	$post_arr = array();
	$post_arr[] = "status=" . urlencode( $status );
	if( !empty( $in_reply_to_status_id ) )
		$post_arr[] = "in_reply_to_status_id=" . $in_reply_to_status_id;
	if( !empty( $lat ) )
		$post_arr[] = "lat=" . $lat;
	if( !empty( $long ) )
		$post_arr[] = "long=" . $long;
	curl_setopt( $curl, CURLOPT_POSTFIELDS, implode( '&#038;', $post_arr ) );

	// Exec, set return
	$return = json_decode( curl_exec( $curl ) );

	// Close curl
	curl_close( $curl );

	return $return;
}
</pre>
<p>Neben Nutzername und Passwort können an diese Funktion der Statustext (Tweet) und der sehr wichtige Parameter &#8220;in_reply_to_status_id&#8221; übergeben werden. Wird die ID eines Tweets mit diesem Parameter übergeben, erkennt Twitter, dass es sich um eine @rely zu dem Tweet mit der übergebenen ID handelt. Da wir ja Antworten senden wollen, genau das richtige! Die Parameter &#8220;lat&#8221; und &#8220;long&#8221; sind übrigens nur schmückendes Beiwerk und werden von mir nicht genutzt. Ich habe das nur der Vollständigkeit halber mit rein genommen.</p>
<p>Nun zur Anwendung der Funktionen:</p>
<pre class="brush:php">
// Twitter account settings
$username = 'user';
$password = 'pass';

// Configure some reply variations in english and german
$replys_en = array(
	'Always remember #BUELL if you talk about Harley Davidson!',
	'Hey, remember #BUELL if you talk about Harley Davidson!',
	'Remember #BUELL FOREVER! Harley Davidson? NEVER!',
	'It makes me sick, that you dont talk about #BUELL ;-)',
	'#BUELL #BUELL #BUELL remember the Harley Davidson #FAIL',
	'#BUELL killed by Harley Davidson in 2k9. Remember that!',
	'#BUELL will never die. Harley Davidson will.'
);
$replys_de = array(
	'Erinner dich an #BUELL wenn du über Harley Davidson sprichst!',
	'Harley Davidson? Die Firma, die #BUELL zerstört hat?',
	'#BUELL FOREVER! Harley Davidson? NEVER!',
	'Es macht mich krank, dass nicht auch über #BUELL sprichst!',
	'#BUELL #BUELL #BUELL denk an den Harley Davidson #FAIL',
	'#BUELL wurde von Harley Davidson 2k9 geschlossen. HD is next!',
	'#BUELL wird niemals sterben, aber Harley Davidson. #Rentnerchopper'
);

// Load last parsed tweet id
if( file_exists( 'harley_since_id.dat' ) )
	$harley_since_id = file_get_contents( 'harley_since_id.dat' );
else
	$harley_since_id = 0;

// Search for tag harley
$harley = twt_search( $username, $password, '#harley', $harley_since_id );
if( is_object( $harley ) )
{
	if( count( $harley -> results ) )
	{
		foreach( $harley -> results AS $rkey => $tweet )
		{
			// Descending order, so the first array element has the highest id!
			if( $rkey == 0 )
				$harley_since_id = $tweet -> id;
			// Only reply if buell not found
			if( stripos( $tweet -> text, 'buell' ) === false &#038;&#038; $tweet -> from_user != $username )
			{
				if( $tweet -> iso_language_code != 'de' )
					$reply = "@{$tweet->from_user} " . $replys_en[ array_rand( $replys_en ) ];
				else
					$reply = "@{$tweet->from_user} " . $replys_de[ array_rand( $replys_de ) ];

				echo "$reply\n";

				// Send reply
				twt_update( $username, $password, $reply, $tweet -> id );
			}
		}
	}
	else	echo "No new tweets to tag #harley\n";
}

// Store last parsed tweet id
file_put_contents( 'harley_since_id.dat', $harley_since_id );
</pre>
<p>Zuerst werden in zwei Arrays englische bzw. deutsche Ausdrücke des Protests definiert, danach wird aus einer kleinen Datendatei die ID des letzten gefundenen Tweets geladen und die Suche ausgeführt.<br />
Die Suchfunktion gibt ein Objekt zurück, dass in der Eigenschaft &#8220;results&#8221; die gefundenen Tweets als Array enthält, welches anschließend durchlaufen wird. Beim ersten gefundenen Tweet wird die &#8220;since_id&#8221; neu gesetzt. Warum beim ersten? Na, weil die Tweets absteigend sortiert sind &#8211; der Erste ist also immer der Aktuellste.<br />
Enthält der Tweet nicht das Wort &#8220;buell&#8221;, wird in der entsprechenden Sprache (deutsch oder englisch) eine @reply an den Twitter-Account des Tweets gesendet.</p>
<p>Tja, das war&#8217;s eigentlich schon. Wer es mal probieren und einen Spruch reingedrückt bekommen will, der zwitschert einfach mal was mit dem Hashtag #harley &#8211; es dauert allerdings ein wenig, bis die Antwort kommt, das Skript läuft nur alle 15 Minuten.</p>
<p>Ich bin gespannt, wie lange der Account aktiv ist, ohne als Spam gemeldet zu werden. ;-)</p>
]]></content:encoded>
			<wfw:commentRss>http://thegeek.de/spas-mit-der-twitter-api-und-ausdruck-des-protests-gegenuber-harley-davidson/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SOAP Dienste programmieren mit PHP</title>
		<link>http://thegeek.de/soap-dienste-programmieren-mit-php</link>
		<comments>http://thegeek.de/soap-dienste-programmieren-mit-php#comments</comments>
		<pubDate>Tue, 10 Nov 2009 13:28:11 +0000</pubDate>
		<dc:creator>Marc</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[soap]]></category>
		<category><![CDATA[web-service]]></category>

		<guid isPermaLink="false">http://thegeek.de/?p=323</guid>
		<description><![CDATA[Wer für seine eigene Anwendung eine Web-API anbieten möchte, hat vielfältige Möglichkeiten dies zu realisieren. Per einfachem HTTP GET oder POST Request und einer Rückgabe als XML/RSS/CSV/JSON/whatever, oder &#8211; was ich etwas eleganter finde &#8211; per SOAP. Dabei ist das Entwickeln eines eigenen SOAP Dienstes mit PHP gar nicht so kompliziert, wie vielleicht vermutet. Zumindest [...]]]></description>
			<content:encoded><![CDATA[<p>Wer für seine eigene Anwendung eine Web-API anbieten möchte, hat vielfältige Möglichkeiten dies zu realisieren. Per einfachem HTTP GET oder POST Request und einer Rückgabe als XML/RSS/CSV/JSON/whatever, oder &#8211; was ich etwas eleganter finde &#8211; per SOAP. Dabei ist das Entwickeln eines eigenen SOAP Dienstes mit PHP gar nicht so kompliziert, wie vielleicht vermutet. Zumindest finde ich SOAP schöner als die weitere Alternative XML-RPC.<span id="more-323"></span></p>
<p>Aber nun zur Definition von SOAP (Quelle: Wikipedia): SOAP (ursprünglich für Simple Object Access Protocol) ist ein Netzwerkprotokoll, mit dessen Hilfe Daten zwischen Systemen ausgetauscht und Remote Procedure Calls durchgeführt werden können. SOAP stützt sich auf andere Standards: XML zur Repräsentation der Daten und Internet-Protokolle der Transport- und Anwendungsschicht (vgl. TCP/IP-Referenzmodell) zur Übertragung der Nachrichten. Die gängigste Kombination ist SOAP über HTTP und TCP.</p>
<p>In der Praxis bedeutet das folgendes: In einer XML Datei (WSDL) werden Nachrichten-Typen definiert und an Operationen gebunden. Dabei gibt es Input-Nachrichten und Output-Nachrichten, sprich Übergaben und Rückgaben. Die WSDL Datei (WSDL = Web Services Description Language) wird dabei vom Client, als auch vom Server genutzt und regelt so die Kommunikation dieser beider Stellen.</p>
<p>Die Vorgehensweise um einen neuen Web-Service zu erstellen ist bei mir immer zuerst die WSDL zu erzeugen, danach die Operationen im Server abzubilden, um diese anschließend mit dem Client zu testen. Eine Beispiel WSDL könnte z.B. so aussehen:</p>
<pre class="brush:xml">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;definitions name=&quot;TheGeek&quot;
	targetNamespace=&quot;http://thegeek.de/wp-soap/thegeek.wsdl&quot;
	xmlns:tns=&quot;http://thegeek.de/wp-soap/thegeek.wsdl&quot;
	xmlns=&quot;http://schemas.xmlsoap.org/wsdl/&quot;
	xmlns:soap=&quot;http://schemas.xmlsoap.org/wsdl/soap/&quot;
	xmlns:xsd=&quot;http://www.w3.org/2001/XMLSchema&quot;&gt;

	&lt;!-- GET LATEST POSTS --&gt;
	&lt;message name=&quot;RequestGetPostsIn&quot;&gt;
		&lt;part name=&quot;apikey&quot; type=&quot;xsd:string&quot;/&gt;
		&lt;part name=&quot;num&quot; type=&quot;xsd:integer&quot;/&gt;
	&lt;/message&gt;
	&lt;message name=&quot;RequestGetPostsOut&quot;&gt;
		&lt;part name=&quot;returncode&quot; type=&quot;xsd:integer&quot;/&gt;
		&lt;part name=&quot;error&quot; type=&quot;xsd:string&quot;/&gt;
		&lt;part name=&quot;posts&quot; type=&quot;xsd:struct&quot;/&gt;
		&lt;part name=&quot;posts_count&quot; type=&quot;xsd:integer&quot;/&gt;
	&lt;/message&gt;
	&lt;portType name=&quot;RequestGetPosts_PortType&quot;&gt;
		&lt;operation name=&quot;GetPosts&quot;&gt;
			&lt;input message=&quot;tns:RequestGetPostsIn&quot;/&gt;
			&lt;output message=&quot;tns:RequestGetPostsOut&quot;/&gt;
		&lt;/operation&gt;
	&lt;/portType&gt;
	&lt;binding name=&quot;GetPosts_Binding&quot; type=&quot;tns:RequestGetPosts_PortType&quot;&gt;
		&lt;soap:binding style=&quot;rpc&quot; transport=&quot;http://schemas.xmlsoap.org/soap/http&quot;/&gt;
		&lt;operation name=&quot;GetPosts&quot;&gt;
			&lt;soap:operation soapAction=&quot;GetPosts&quot;/&gt;
			&lt;input&gt;
				&lt;soap:body
					encodingStyle=&quot;http://schemas.xmlsoap.org/soap/encoding/&quot;
					namespace=&quot;urn:thegeek-getpostsservice&quot;
					use=&quot;encoded&quot;/&gt;
			&lt;/input&gt;
			&lt;output&gt;
				&lt;soap:body
					encodingStyle=&quot;http://schemas.xmlsoap.org/soap/encoding/&quot;
					namespace=&quot;urn:thegeek-getpostsservice&quot;
					use=&quot;encoded&quot;/&gt;
			&lt;/output&gt;
		&lt;/operation&gt;
	&lt;/binding&gt;
	&lt;service name=&quot;GetPosts_Service&quot;&gt;
		&lt;documentation&gt;Return latest posts&lt;/documentation&gt;
		&lt;port binding=&quot;tns:GetPosts_Binding&quot; name=&quot;GetPosts_Port&quot;&gt;
			&lt;soap:address location=&quot;http://thegeek.de/wp-soap/index.php&quot;/&gt;
		&lt;/port&gt;
	&lt;/service&gt;

&lt;/definitions&gt;
</pre>
<p>Diese WSDL definiert eine einfache Funktion &#8220;GetPosts&#8221; mit einer eingehenden Nachricht und einer ausgehenden Nachricht. Für die einzelnen Felder der Nachrichten sind entsprechende Typen definiert. Nachdem die Nachrichten an die Operation &#8220;GetPosts&#8221; gebunden wurden, wird mit dieser Operation ein Soap-Service definiert. Ein Service besteht also aus einem Binding, welches wiederum aus eine Input- und/oder Output-Message besteht. Das klingt nun zugegeben ziemlich kompliziert, ist aber in der Praxis wirklich einfach nachzuvollziehen, wenn wir uns mal den Server-Quellcode zu dieser WSDL Definition ansehen.</p>
<pre class="brush:php">
&lt;?php

// SOAP config array
$soap_config = array( 'encoding' =&gt; 'UTF-8' );

// Don't cache WSDL files, mandatory for development
ini_set( 'soap.wsdl_cache_enabled', '0' );

class thegeek_soapserver
{
	function __construct( $parameters )
	{

	}

	public function GetPosts( $apikey = '', $num = 10 )
	{
		if( $apikey == 'demoapikey' )
		{
			$posts = array( 	array( 'title' =&gt; 'Demo Post 1', 'body' =&gt; 'Demo content 1' ),
						array( 'title' =&gt; 'Demo Post 2', 'body' =&gt; 'Demo content 2' ),
						array( 'title' =&gt; 'Demo Post 3', 'body' =&gt; 'Demo content 3' ),
						array( 'title' =&gt; 'Demo Post 4', 'body' =&gt; 'Demo content 4' )
			);
			return array(	'return' =&gt; true,
					'error' =&gt; '',
					'posts' =&gt; $posts,
					'posts_count' =&gt; 0
			);
		}
		// API KEY FAIL
		else
		{
			return array(	'return' =&gt; false,
					'error' =&gt; 'API KEY INVALID',
					'posts' =&gt; array(),
					'posts_count' =&gt; 0
			);
		}
	}
}

// Run SOAP server
$soapserver = new SoapServer( 'http://thegeek.de/wp-soap/thegeek.wsdl', $soap_config );
$soapserver -&gt; setClass( 'thegeek_soapserver', 'some parameters for the constructor (example only...)' );
$soapserver -&gt; handle();

?&gt;
</pre>
<p>Nachdem die Soap-Config für die PHP Klasse &#8220;SoapServer&#8221; definiert und das caching von WSDL Dateien per &#8220;ini_set&#8221; ausgeschaltet wurde, folgt unsere eigene Klasse, die den Web-Service abbildet. Der Konstruktor kann wie gewohnt definiert werden, auch beim Initialisieren unserer Klasse über die PHP Klasse &#8220;SoapServer&#8221;, können beliebige Parameter übergeben werden. Übrigens sind auch extends problemlos möglich.</p>
<p>Dann findet sich in der Klasse eine Methode, welche unseren SoapService &#8220;GetPosts&#8221; abbildet, als Übergabeparameter sind die Variablen unserer Input-Nachricht angegeben. Wie die Variablennamen in der Methode gewählt werden ist egal, aber die Methode muss genau so heißen, wie in der WSDL angegeben (soap:operation soapAction=&#8221;GetPosts&#8221;). Der Code in der Methode dient natürlich nur der Verdeutlichung, wie Rückgaben erfolgen, nämlich als assoziatives Array, welches die in der WSDL definierte Output-Nachricht abbildet.</p>
<p>Um unsere Server-Klasse dann zu initialisieren, wird die PHP Klasse &#8220;SoapServer&#8221; mit entsprechenden Parametern (Web-Pfad zur WSDL, SoapConfig) aufgerufen. Danach wird mit Hilfe der Methode &#8220;setClass&#8221; unsere Klasse als Handler ausgewählt und der Server letztendlich mit der Methode &#8220;handle&#8221; konstruiert.</p>
<p>Fehlt eigentlich nur noch ein kleiner Test-Client:</p>
<pre class="brush:php">
&lt;?php

// Create new SOAP client
$soap_client = new SoapClient( 'http://thegeek.de/wp-soap/thegeek.wsdl', array( 'encoding' =&gt; 'UTF-8' ) );
if( is_object( $soap_client ) )
{
	$soap_result = $soap_client -&gt; GetPosts( 'demoapikey', 10 );
	// Debug output
	echo &quot;&lt;pre&gt;&quot;;
	print_r( $soap_result );
	echo &quot;&lt;/pre&gt;&quot;;
}
else	die( 'SOAP Server not available' );

?&gt;
</pre>
<p>Der Client ist ziemlich problemlos umzusetzen: Einfach mit der PHP Klasse &#8220;SoapClient&#8221; ein Client-Objekt erzeugen (Web-Pfad zur WSDL übergeben) und die Methoden (= Operationen) wie in der WSDL definiert nutzen. Obiges Beispiel gibt folgendes aus:</p>
<pre class="brush:plain">
Array
(
    [returncode] =&gt;
    [error] =&gt;
    [posts] =&gt; Array
        (
            [0] =&gt; Array
                (
                    [title] =&gt; Demo Post 1
                    [body] =&gt; Demo content 1
                )

            [1] =&gt; Array
                (
                    [title] =&gt; Demo Post 2
                    [body] =&gt; Demo content 2
                )

            [2] =&gt; Array
                (
                    [title] =&gt; Demo Post 3
                    [body] =&gt; Demo content 3
                )

            [3] =&gt; Array
                (
                    [title] =&gt; Demo Post 4
                    [body] =&gt; Demo content 4
                )

        )

    [posts_count] =&gt; 0
)
</pre>
<p>So schwierig ist das mit SOAP und PHP also nicht. Wichtig ist allerdings noch: PHP muss mit der Option &#8220;&#8211;enable-soap&#8221; kompiliert werden, um die SOAP Extension nutzen zu können. Alternativ kann aber auch das SOAP PEAR Paket genutzt oder auf die Klasse nuSoap zurückgegriffen werden.</p>
<p>Wer selbst mal von seinem Webspace aus testen will: <a href="http://thegeek.de/wp-soap/thegeek.wsdl">http://thegeek.de/wp-soap/thegeek.wsdl</a></p>
<p>Wer Fragen hat: Comments are open.</p>
]]></content:encoded>
			<wfw:commentRss>http://thegeek.de/soap-dienste-programmieren-mit-php/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Twitter Listen als RSS/Atom Feed abonnieren</title>
		<link>http://thegeek.de/twitter-listen-als-rssatom-feed-abonnieren</link>
		<comments>http://thegeek.de/twitter-listen-als-rssatom-feed-abonnieren#comments</comments>
		<pubDate>Mon, 09 Nov 2009 12:17:53 +0000</pubDate>
		<dc:creator>Marc</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[atom]]></category>
		<category><![CDATA[listen]]></category>
		<category><![CDATA[rss]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://thegeek.de/?p=317</guid>
		<description><![CDATA[Die neue Listenfunktion bei Twitter ist klasse, denn damit lassen sich endlich die Leute denen man folgt thematisch gruppieren. Da die Listen nun auch per Twitter API angesprochen werden können, ist es möglich die Tweets einer Liste per RSS bzw. Atom zu abonnieren. Eine praktische Sache.
Einfach im Browser oder RSS Reader eine dem folgenden Format [...]]]></description>
			<content:encoded><![CDATA[<p>Die neue Listenfunktion bei Twitter ist klasse, denn damit lassen sich endlich die Leute denen man folgt thematisch gruppieren. Da die Listen nun auch per Twitter API angesprochen werden können, ist es möglich die Tweets einer Liste per RSS bzw. Atom zu abonnieren. Eine praktische Sache.</p>
<p>Einfach im Browser oder RSS Reader eine dem folgenden Format entsprechende URL eingeben:</p>
<p><strong>http://api.twitter.com/1/ACCOUTNAME/lists/LISTENNAME/statuses.atom</strong></p>
<p>Wobei &#8220;<strong>ACCOUNTNAME</strong>&#8221; durch den Twitternamen z.B. &#8220;motorradblogger&#8221; zu ersetzen ist. Das gleiche gilt natürlich für &#8220;<strong>LISTENNAME</strong>&#8220;.</p>
<p>Zum Beispiel so: <a href="http://api.twitter.com/1/motorradblogger/lists/motorradblogger/statuses.atom">Meine Liste von Motorradbloggern</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://thegeek.de/twitter-listen-als-rssatom-feed-abonnieren/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Spielerei mit der Twitter API</title>
		<link>http://thegeek.de/spielerei-mit-der-twitter-api</link>
		<comments>http://thegeek.de/spielerei-mit-der-twitter-api#comments</comments>
		<pubDate>Mon, 26 Oct 2009 11:58:12 +0000</pubDate>
		<dc:creator>Marc</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://thegeek.de/?p=214</guid>
		<description><![CDATA[Kürzlich habe ich ein wenig mit der Twitter API gespielt. Ich wollte mal sehen, welche Follower meiner Follower auch mir folgen. Dazu habe ich mir eine kleine Funktion geschrieben die ermittelt, welche anderen Twitterer von einem Account verfolgt werden. Die Ergebnisse habe ich in einer Datenbank-Tabelle gespeichert und später ausgewertet.
Die Funktion ist zwar nicht perfekt, [...]]]></description>
			<content:encoded><![CDATA[<p>Kürzlich habe ich ein wenig mit der Twitter API gespielt. Ich wollte mal sehen, welche Follower meiner Follower auch mir folgen. Dazu habe ich mir eine kleine Funktion geschrieben die ermittelt, welche anderen Twitterer von einem Account verfolgt werden. Die Ergebnisse habe ich in einer Datenbank-Tabelle gespeichert und später ausgewertet.</p>
<p>Die Funktion ist zwar nicht perfekt, mir reichte sie jedoch.</p>
<pre class="brush:php">
&lt;?php
function get_friends( $screen_name, $page_limit = 200 )
{
	$screen_names = array();
	for( $page = 1; $page < $page_limit; $page++ )
	{
		ob_start();
		$friends_json = file_get_contents( 'http://twitter.com/statuses/friends.json?screen_name=' . $screen_name . '&#038;page=' . $page );
		$errors = ob_get_contents();
		ob_end_clean();
		if( $friends_json !== false )
		{
			$friends = json_decode( $friends_json );
			if( is_array( $friends ) &#038;&#038; count( $friends ) )
			{
				foreach( $friends AS $friend )
					$screen_names[ $friend -> id ] = $friend -> screen_name;
			}
			else
			if( !count( $friends ) )
			{
				break;
			}
			else
			{
				$screen_names = array();
				break;
			}
		}
		else	break;
	}
	if( count( $screen_names ) || $errors == '' )
	{
		return $screen_names;
	}
	else
	{
		if( strpos( $errors, '401 Unauthorized' ) !== false )
			return false;
		else
			return null;
	}
}

// Example usage
print_r( get_friends( 'motorradblogger' ) );
?&gt;
</pre>
<p>Schade übrigens, dass die Anzahl der Requests pro Stunde bei Twitter limitiert ist, sonst ließen sich ziemlich schnell, ziemlich viele Twitter-Accounts crawlen. ;-)</p>
<p>Die Benutzung ist sehr simpel: Einfach den Accountnamen übergeben, die Funktion läd Seitenweise alle Accounts, denen gefolgt wird und gibt diese in einem assoziativen Array (Schlüssel: Account-ID, Wert: Accountname) zurück. Im Falle eines Fehlers wird &#8216;false&#8217; zurückgegeben, bei einem unbekannten Fehler &#8216;null&#8217;.</p>
]]></content:encoded>
			<wfw:commentRss>http://thegeek.de/spielerei-mit-der-twitter-api/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
