Oct 31
Digg
Stumbleupon
Technorati
Delicious

Postcrossing symfony-driven site review

[ratings]

Today we’ve randomly selected for the review this symfony-driven site (mentioned in list of applications developed with symfony symfony sites):

http://www.postcrossing.com

So first of all it has simple but cool idea of postcards sharing. Site works fast, has clean and simple design and navigation w/o any noticeable bugs or disadvantages. Blog area is implemented using general site engine (we can’t state 100% though that it’s symfony-driven site b/c the only thing we found which reminds symfony framework is multilevel urls like /user/symfonian/gallery).

Forum area is driven though with XMB forum software which is a bit outdated and did not have updates since 02/28/2009. There must be created bridge between main “symfony” site and forum engine.

There were a few other things we’ve learned from this site for ourselves.

First of all we’ve found out from code that it uses unusual adsense inclusions and investigated that it’s because it uses “Google Ad Manager” to inject ads. It’s another one cool google service which we’ve heard about but only today had a chance to look into it more closely.

The other thing is ajax-driven live updates in style of popular nowadays “live search”, it appears when you login to user area under “What is happening now?”, here is the code which implements it and with slight changes you can use it for your own purposes (e.g. twitter like live updates, etc):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
 
<div id="liveEvents" style="overflow: hidden; height: 18em; width: 31em;"></div>
 
<script type="text/javascript">
//<![CDATA[
Effect.ScrollVertical = Class.create();
 
Object.extend(Object.extend(Effect.ScrollVertical.prototype, Effect.Base.prototype),
{
	initialize: function(element)
	{
		if(typeof element == "string")
		{
			this.element = $(element);
			if(!this.element)
			{
				throw(Effect._elementDoesNotExistError);
			}
		}
 
		var options = Object.extend({
			from: this.element.scrollTop || 0,
			to:   this.element.scrollHeight
		}, arguments[1] || {});
 
		options.to = options.to == this.element.scrollHeight ? options.to : options.from + options.to;
 
		this.start(options);
	},
 
	update: function(position)
	{
		this.element.scrollTop = position;
	}
});
 
var requests = 0;
var events = [...];
var lastId = 5926263;
var pullInterval = 30;
 
for($i = 1; $i < 8; $i++) {
    if (events.length) {
        printEvent(events.pop(), false);
    } else {
        break;
    }
}
 
startFetcher();
 
 
 
/* pullEvents(); */
 
function updateJSON(request, json) {
	json.each(function(txt){
				events.unshift(txt);
				lastId = Math.max(lastId, txt[0]);
			  });
}
 
function printEvent(eventToAdd, highlight) {
	spanId = 'event-' + eventToAdd[0];
	new Insertion.Bottom('liveEvents', '<div class="liveEvent"id=\"' + spanId + '\">' + eventToAdd[1] + '<\/div>');
	new Insertion.Bottom('liveEvents', '');
 
	if (highlight) {
	   new Effect.Highlight(spanId, {duration: 4});
	}
	new Effect.ScrollVertical('liveEvents', { });
}
 
printer = new PeriodicalExecuter(
			function() {
				if (events.length) {
					printEvent(events.pop(), true);
				}
			},
			3);
 
function pullEvents() {
	new Ajax.Request('/liveEvents/getLast',
					 { 	asynchronous:true,
						evalScripts:false,
						method:'get',
                      	parameters:'lastEventId=' + lastId,
						onComplete:function(request, json) {
									  updateJSON(request, json)
								   }
					 }
	);
}
 
function startFetcher() {
	fetcher = new PeriodicalExecuter(
				function() {
					if(events.length < 7) {
						requests = requests + 1;
						pullEvents();
					}
					fetcher.stop();
					if (requests < 6) {
						pullInterval = pullInterval + 10;
						startFetcher();
					}
				},
				pullInterval);
}
//]]>
</script>
</div>

The other thing which worth to mention here is site urls, until now we did not see good enough symfony plugin which would automatically generate clean SEO proven route-to-page.html URLs.
Obviously, anyone may use powerful symfony route mechanism but it always take time to go through each URL and make them look better way. Ideal solution would be some kind of plugin which would generate URLs based on some pattern like this route-to-page.html

Wish you guys all the best with this site, good job!


Author: symfonian

No Comments

No comments yet.

Comments RSS TrackBack Identifier URI

Leave a comment