menu
Krylan | Krzysztof Koperkiewicz
Blog

RSS – jak samemu napisać generator kanałów?

2017-07-01 / Inne / Komentarze (0) / Wyświetleń: 1694

Dziś prezentuję Wam kolejny post na temat RSS. Tym razem jednak skupimy się na tym temacie od strony web developerów, a nie użytkowników. O tym, czym jest RSS i jak z niego korzystać, przeczytać możecie w moim poprzednim poście: "RSS – jak z niego korzystać?". Zanim jednak zaczniemy pisać kod, trzeba uzupełnić wiedzę dotyczącą tego tematu oraz wybrać sposób, w jaki zastosujemy kanały na swojej stronie.

Jeśli chodzi o rozwinięcie skrótu RSS, to jest to dosyć ciężkie, ponieważ w każdej wersji brzmi ono inaczej. Zaczynając od najstarszej, jest to (za Wikipedią): 

- RDF Site Summary (RSS 1.x, RSS 0.90)
- Rich Site Summary (RSS 0.91/RSS 0.92/RSS 0.93)
- Robust Site Syndication (RSS 0.99)
- Really Simple Syndication (RSS 2.0)

Możemy więc uznać, że aktualnym rozwinięciem skrótu RSS jest "Really Simple Syndication". RSS wykorzystuje format XML do przekazywania informacji (głównie zalążków artykułów) ze swojej strony, aby użytkownik był na bieżąco powiadamiany, że jest coś nowego na obserwowanych przez niego witrynach. RSS to jednak historia. Dlaczego? Przeszłość RSS jest zawiła, ponieważ był on rozwijany w dwóch równoległych wersjach. Ostatecznie jednak prawa do tej technologii trafiły do Uniwersytetu Harvarda. Z tych właśnie powodów postanowiono podejść do tego tematu jeszcze raz, aby znaleźć zastępstwo dla pozostawionego przez uczelnię, "nieotwartego" quasi-standardu. I tak właśnie powstał Atom. I choć to właśnie z Atomu się korzysta, to często nazywa się te kanały ogólnikowo RSS. I nie widzę w tym nic dziwnego, ponieważ nazwa "Atom" jest dosyć... pospolita. Użytkownicy natomiast są przyzwyczajeni do oryginalnego skrótu RSS oraz białej ikony na pomarańczowym (#FA9B39) tle, która została zaprojektowana w 2005 przez Stephena Horlandera, designera Mozilli.

Odstawiając historię na bok: mamy RSS oraz Atom. Oba oparte są o XML i w zasadzie są do siebie podobne. Co więc powinniśmy zrobić? Używać Atoma. Jest on oficjalnym, otwartym standardem, który naprawia błędy starego i pogmatwanego RSS-a. Dla użytkowników nie sprawi to żadnego problemu, ponieważ obecnie każdy czytnik powinien obsługiwać format Atom. Mamy więc same plusy i nie ma powodu, aby z tego nie korzystać. Nic także nie stoi na przeszkodzie, aby opisać nasz kanał na stronie jako "RSS" lub "Atom/RSS".

Teraz, gdy już mamy teorię za sobą (i poznaliśmy przy okazji trochę historii), możemy zająć się implementacją kanałów RSS na naszej stronie internetowej. Poniżej pokażę Wam, jak samodzielnie napisać skrypt w PHP, który będzie generował pliki XML ze składnią standardu Atom. W przypadku blogów na Wordpress czy innych systemach takie kanały są tworzone automatycznie. Jeśli jednak chcemy zrobić je samemu, lub dodać je do swojego autorskiego rozwiązania (tak jak na przykład ja to zrobiłem), to taki plik generujący kanały nam pomoże. Skryptu możemy użyć jako zadania cron (aby aktualizował kanały co jakiś czas) lub sprawić, że będzie je tworzył w momencie, gdy dokonamy jakichś zmian w poście. Zaczynamy!

Na początku pamiętajmy o tym, aby mieć dostęp do bazy danych i móc wykonywać zapytania, dzięki którym wyciągniemy pożądane przez nas posty. Następnie napiszemy funkcję, która po otrzymaniu obietku z danymi zwróci przygotowany dla nas wpis do kanału. Pojedynczy wpis wygląda mniej więcej tak (niektóre elementy są opcjonalne):

<entry>
	<title>[Photoshop] Zadania – jak zautomatyzować pracę?</title>
	<link type="text/html" href="https://krylan.ovh/portfolio/pl/blog/b_27,photoshop_zadania_jak_zautomatyzowac_prace"/>
	<id>tag:krylan.ovh,2017-06-24:27</id>
	<updated>2017-06-24T09:58:23+02:00</updated>
	<author>
		<name>Krylan</name>
	</author>
	<summary>
		Czasami zdarza się, że macie do przetworzenia w taki sam sposób wiele plików. Na przykład seria zdjęć prosto z aparatu ma trafić na stronę internetową. Ich wielkość i waga jednak są przeszkodą, która powstrzymuje nas nad załatwieniem sprawy szybko, przenosząc te zdjęcia bezpośrednio na serwer. Z drugiej strony mając 60 zdjęć, gdzie na każdym z nich trzeba ręcznie wykonać czynność zmniejszenia jego rozmiaru, może być monotonne i czasochłonne. Dlatego lepiej będzie użyć zadań, które nam cały ten proces ułatwią.
	</summary>
	<content type="image/jpg" src="http://krylan.ovh/portfolio/img/post/27.jpg"/>
</entry>


Zadaniem naszej funkcji będzie wstawienie danych pomiędzy tagi XML i zwróceniu gotowego bloku, który wraz z innymi wpisami zostanie zapisany do pliku *.xml. U mnie ta funkcja wygląda tak:

$domain_name = 'http://'.$_SERVER['HTTP_HOST'];
$feed_path = '/portfolio/rss/blog.xml';
$now = date('c');
$lang = 'pl';

function blog_xml($show_blog){
	global $actual_entry, $domain_name, $lang;
	$domain_name = 'http://'.$_SERVER['HTTP_HOST'];
	$entry_date = date('c', strtotime($show_blog->date_creation));
	$entry_date_id = date('Y-m-d', strtotime($show_blog->date_creation));
	if(file_exists('../img/post/'.$show_blog->id.'.jpg')){
		$entry_image = '<content type="image/jpg" 
    src="'.$domain_name.'/portfolio/img/post/'.$show_blog->id.'.jpg" />';
	}else{ $entry_image = ''; }
	$actual_entry = '<entry>
		<title>'.$show_blog->title.'</title>
		<link type="text/html" href="'.$domain_name.'/portfolio/'.$lang.'/blog/b_'.$show_blog->id.','.friendly_url($show_blog->title).'"/>
		<id>tag:krylan.ovh,'.$entry_date_id.':'.$show_blog->id.'</id>
		<updated>'.$entry_date.'</updated>
		<author>
			<name>Krylan</name>
		</author>
		<summary>'.$show_blog->short_content.'</summary>
		'.$entry_image.'
	</entry>';
	return $actual_entry;
}


Przekazany jako argument został jeden z wpisów z bazy danych. W środku zaczynamy od ustalenia potrzebnych nam zmiennych (tych z zewnątrz jak i używanych tylko w tej funkcji). Zmienna $entry_date zawiera datę z formatem 'c' (jest to data ISO 8601, od PHP 5, jednak można używać także równoznacznego DATE_ATOM, od PHP 5.1, lub 'Y-m-d\TH:i:sO' dla starszych wersji) – jest to format zgodny ze standardem. W moim przypadku do wpisów są dołączane obrazki; Sprawdzam więc, czy obraz do konkretnego posta istnieje. Jeśli tak, to zmieszczam dodatkowy tag w zmiennej z adresem obrazka, a w innym przypadku pozostawiam tą zmienną pustą. Następnie mamy już tworzenie samego wpisu, który jest objęty tagiem '<entry></entry>'.

Tag <title> jest konieczny dla naszego wpisu. Jest to oczywiście tytuł posta.

Tag <link> jest odnośnikiem, dzięki któremu nasz czytelnik po zobaczeniu wpisu w swoim czytniku RSS może przenieść się na naszą stronę, gdzie przeczyta całość.

Tag <id> jest bardzo ważny. Jest on unikalnym identyfikatorem, dzięki któremu można rozróżnić wszystkie kanały i wpisy. Ważne jest, aby ten identyfikator się nie zmieniał i był dla każdego wpisu unikalny. W moim przpadku początkiem jest domena, a następnie data wpisu oraz jego identyfikator w bazie (po wygenerowaniu wygląda to tak: tag:krylan.ovh,2017-06-24:27).

Tag <updated> to data, kiedy wpis został ostatnio zaktualizowany (u mnie jest to po prostu data powstania wpisu).

Następnie mam zagnieżdżony tag <author>, w którym możemy znaleźć kolejny tag zawierający mój pseudonim. W przypadku gdy bloga/serwis prowadzi więcej osób, taką informację warto zamieścić, aby było wiadomo, kto jest autorem wpisu.

Tag <summary> zawiera streszczenie wpisu. Najlepiej zamieścić tam pierwszy akapit naszego posta, który użytkownik będzie mógł przeczytać w swoim czytniku, zanim zdecyduje się przejść na naszą stronę. Możemy także użyć tagu <content>, gdzie umieszczamy całą treść wpisu – wtedy użytkownik może przeczytać wszystko u siebie.

Na sam koniec zamieszczam zmienną, w której znajduje się tag z obrazkiem, o ile ten istnieje, a potem zamykam wpis przez </entry>.

Kiedy już mamy ten blok zapisany, możemy go zwrócić. W ten sposób mamy napisaną funkcję, która każdy wpis wyciągnięty z bazy zamieni nam na wpis Atom.

Kiedy mamy już to gotowe, możemy utworzyć zapytanie, które wyciągnie nam te informacje o postach, które chcemy. Na przykład wyciągamy 20 ostatnich postów, które nie są ukryte przed użytkownikami, sortując je po dacie dodania. Kiedy zapytanie zostało wykonane, możemy utworzyć pętlę, gdzie zapiszemy całą listę wpisów do zmiennej, używając napisanej wcześniej funkcji.

if($get_blog->num_rows > 0){
	while($show_blog = $get_blog->fetch_object()){
		$entries_list .= blog_xml($show_blog);
	}
}


Teraz wykorzystamy tę naszą listę, umieszczając ją w kanale. Musimy najpierw utworzyć strukturę kanału, a w środku umieścić wszystkie tagi <entry>:

$feed_content = '<?xml version="1.0" encoding="utf-8"?>
<feed xml:lang="pl" xmlns="http://www.w3.org/2005/Atom">
	<title>Krylan Blog</title>
	<subtitle>Informacje, nowości, ciekawostki dla web developerów.</subtitle>
	<link href="'.$domain_name.$feed_path.'" rel="self"/>
	<updated>'.$now.'</updated>
	<author>
	  <name>Krylan</name>
	</author>
	<id>'.$domain_name.$feed_path.'</id>
	'.$entries_list.'
</feed>';


Na samym początku deklarujemy, że używamy XML-a z kodowaniem utf-8. Tag <title>, tak jak w powyższym przypadku, definiuje tytuł kanału. Tag <subtitle> jest jego krótkim opisem. W tagu <link> z rel="self" zamieszczamy link do miejsca, w którym znajduje się plik xml kanału. Następnie w kanale zamieszczamy takie tagi jak przy wpisach: <updated>, <author>, <id>. Ostatecznie umieszczamy całą listę wpisów i zamykamy całość znacznikiem </feed>. Kiedy już mamy to wszystko zapisane, należy już tylko zapisać to jako plik w wybranym przez nas miejscu. Zrobimy to tak:

file_put_contents('../rss/blog.xml', mb_convert_encoding($feed_content, 'UTF-8', 'OLD-ENCODING'));

 
W ten sposób utworzyliśmy kanał i za każdym razem, gdy skrypt będzie się wykonywał, plik z kanałem RSS/Atom będzie nam się aktualizował. Możemy oczywiście po tym wykonać kolejne zapytania MySQL i utworzyć inne kanały, na przykład dla innych kategorii, czy konkretnych autorów.

To jest mój sposób na stworzenie i aktualizowanie automatyczne kanałów RSS. Macie może inne propozycje w tym temacie? Koniecznie napiszcie o tym w komentarzu i podzielcie się opinią.


Poprzedni post
[Photoshop] Zadania – jak zautomatyzować pracę?
Następny post
[Prezentacja] WebRTC i historia komunikacji w przeglądarkach

Wygląda na to, że nic tu nie ma
Uszczęśliw kotka i napisz komentarz