Monday, November 22, 2010

Борис Гребенщиков

Reminder, good songs:
Psi (Пси) - Аквариум (CD)
Сварог

/////////////////

Bardo - Русско-Абиссинский Оркестр (CD)

/////////////////

Прибежище - БГ, Gabroelle Roth & The Mirrors (CD)

Example of using fastcgi_finish_request() in php 5.3

Warning: this technique will work only when php is run as fastcgi and controlled by php-fpm

http://php-fpm.org/


fastcgi_finish_request() is extremely powerful optimization trick. It's even more powerful if you use it together with closure functions in php 5.3
This is how I started using it now:
suppose I have a method somewhere in the middle of my script that has to call some API, let's say Facebook API, download recent user data and if something changed in user's Facebook profile, then update my database.

Since facebook API response time is unpredictable, I don't want to hold up the page load waiting, so I want to defer this call till after the page is rendered.

But how do I do this if the Facebook api check is somewhere in the middle of my script and the page has not finished rendering yet?

The way this can be done is with closure.

Pass anonymous function as callback to register_shutdown_function() like this:

This script snipped is somewhere inside a class method which is called about half way through the script:
Note: the d() and e() functions are for logging debug and error messages,
you can ignore these...


$oAuthFB = new clsExternalAuthFb($oGlobal, $sAppId, $aCookieParams);
register_shutdown_function(function() use ($oAuthFB){

try{
d('before facebook auth post precessing $oAuthFB: '.$oAuthFB);
$oAuthFB->getFbData()->getFacebookUserObject();
d('after facebook auth post precessing');
} catch (Exception $e){
e('Unable to run post processing of FB data: '.$e->getFile().' '.$e->getLine().' '.$e->getMessage());
}
});


See what's going on here? I am basically cutting out the piece of code and sticking it to be executing all the way at the end of the script, after the php is done parsing everything else.

The only thing left to do is to add

fastcgi_finish_request();
somewhere after the output is sent to browser.

For example, in my index.php I have

$oController = new Controller();
echo $oController->getHtml();
fastcgi_finish_request();


That would ensure that all registered shutdown functions are run after the output is sent.

Because of the closure, the context, the object $oAuthFB is remembered it the state it was just before the callback anonymous function was created, all instance variables are in place, so the shutdown function is executed with the complete context of $oAuthFB object in the same state it was back in the middle of that method where I registered the shutdown callback.

This is extremely powerful way to basically cut out the code from the middle of you script and defer its execution till after the page has been rendered.

Tuesday, November 16, 2010

To update classes to make use of php 5.3 static magic

Something for my own user only, some changes to make to program
Even better have clsEmailRecord::factory($oRegistry)->get($email)
Then we can also create new record this way! it should extend clsMongoDocument

Just extend static class MongoDocument then use get_calling_class()
and call_static() magic
then it will be as easy as just
creating blank classes than extend clsMongoDocument
Heck, we can even make it serializable, just
use clsRegistry::getInstance() in unserialize and we good to go

clsMongoDocument::getByEmail($email)
clsMongoEmail::getByEmail($oMongo, $email)

clsMongoEmail::create($oMongo, $aData);

clsMongoEmail::factory($oMongo, $aData); the normal object

Monday, October 18, 2010

How to setup Apache with php on home Windows PC

If you want to install Apache server and php on Windows for your php development, then the best thing to do is to install WAMP.


It has own installer, so its very easy to download/install

Don't install Apache from official Apache website, MAMP is much easier and it installs php, apache and mysql all at once and has a nice little control panel where you can start and stop the server.

You can still install extra php pecl modules later by just copying the .dll files to appropriate dir, I'll show you how to do it later.

Sunday, September 26, 2010

Sick on MySQL Lockups

Pardon my French but MySql is a cunt.

Tuesday, September 21, 2010

Php class for simulating Auto Increment in MongoDB




/**
* Static class for generating and
* maintaining records of per-collection
* auto-increment ids
*
* @author Dmitri Snytkine
*
*/
class MongoIncrementor
{
/**
* Name of collection where to
* store the auto-increment values
* You can change it but only before you
* store your first value.
* Once you begin storing values of you
* auto-increments, it's best not to change this, ever!
*
* @var string name of collection
*/
const COLLECTION_NAME = 'Autoincrement';

/**
* The pseudo auto increment handling is done
* by storing collectionName => id
* in Autoincrements collection
*
* We get value, increment it and resave it
* but watch for Errors/Exceptions in order
* to prevent race condition
*
* @param obj $db must pass object of type MongoDB
*
* @param string $collName which collection this id
* is for. This has nothing to do with the name of the collection
* where these generated sequence numbers are stored.
* For example if you need the next id for collection 'STUDENTS',
* then you pass the 'STUDENTS' as $collName value
* This way different values of 'next id' are maintained
* per collection name
*
* @param int initialId if there is no record
* for the collection yet, then start the increment counter
* with this value.
*
* @param int $try this is used for recursive calling this method
* You should NEVER pass this value yourself
*
* @return int value of next id for the collection
*/
public static function nextValue(MongoDB $db, $collName, $minId = 0, $try = 1)
{

if( $try > 100 ){
throw new RuntimeException('Unable to get nextID for collection '.$collName.' after 100 tries');
}

$prevRecordID = null;
$coll = $db->selectCollection(self::COLLECTION_NAME);
$coll->ensureIndex(array('coll' => 1, 'id' => 1), array('unique' => true));

/**
* We use find() instead of findOne() for a reason!
* It's just more reliable this way
*/
$cursor = $coll->find(array('coll' => $collName))->sort(array('id' => -1))->limit(1);
if($cursor && $cursor->hasNext()){
$a = $cursor->getNext();
$prevRecordID = $a['_id'];
} else {
$a = array('coll' => $collName, 'id' => $minId);
}

$prevID = $a['id'];
$newId = ($a['id'] + 1);

/**
* Remove the _id from record, otherwise
* we will be unable to insert
* a new record if it already has the same _id
* This way a new _id will be auto-generated for us
*/
unset($a['_id']);
$a['id'] = $newId;


/**
* Wrapping this inside try/catch so that if
* another process inserts the same value of coll/id
* between the time we selected and updated this
* it will throw exception or return false and then
* we will try again up to 100 times
*
* In Case of duplicate key Mongo throws Exception,
* but just in case it will change in the future,
* we also test if $ret is false
*/
try{
/**
* Using fsync=>true because its very critically important
* to actually write the row to disc, otherwise if database
* goes down we will lose the correct value
* of our increment ID
*/
$ret = $coll->insert($a, array('fsync' => true));
if(!$ret){
$try++;

return self::nextValue($db, $collName, $initialId, $try);
}

/**
* Insert successfull
* now delete previous record(s)
*/
if(null !== $prevRecordID){
$removed = $coll->remove(array('_id' => $prevRecordID)); //, array('fsync' => true) // not very important to fsync
}

} catch (MongoException $e){

$try++;

return self::nextValue($db, $collName, $initialId, $try);
}

return $newId;
}
}

Monday, September 20, 2010

In Java always use braces

Warning: Python programmers must NOT read this post.

This is funny: from Standford Java course professor Mehram Sahami
In Java programming follow the rule of orthodontist:
"You need braces"
Orthodontist will always say this to EVERY patient!

What he means is: don't write a shorthand "no braces" code blocks,
like these:
if(num % 2 == 0)
println ('num is even');

always use braces:
if(num % 2 == 0){
println ('num is even');
}

It's just easier for another programmer to read.

Saturday, September 18, 2010

random.h library in C++ but not in php

Useful function from C++ random.h library:
RandomChance(doublce probability)
You pass it a probability chance like 0.25
and the it will return true 1/4 of the times, other times
if will return false.

There is no such function in php, so that's one more area where php could improve,
perhaps add the "Random" class into SPL and include all the functions from the C++ random.h

Strings in Java, php and C++

Strings in C++ are mutable
Strings in php are also mutable
Strings in Java are immutable, but there is a string builder class
to make string building in mutable fashion.

Sunday, September 12, 2010

sorry, you must have a tty to run sudo

If you are unable to run sudo command,
check the /var/log/secure log

If you are seeing this message:

"sorry, you must have a tty to run sudo"

Then you should edit /etc/sudoers file and comment out this line:

Defaults requiretty
(just add the # in front of this line and save the file)

This this will fix your sudo error.

Saturday, September 11, 2010

Unable to login to mysql as root user access denied

Just got a new server from theplanet webhost

Could not login to mysql as root user

Kept getting messages access denied for user 'root'@'localhost'
using password yes

I tried with and without the password for root user

I then tried instructions for resetting the mysql root user password from
mysql website


Nothing worked!

Finally what I did was:
Stopped mysql
/etc/rc.d/init.d/mysqld stop

Deleted everything from /var/lib/mysql
so the default database 'mysql' was removed

Then reinstalled mysql and mysql-server from yum

yum reinstall mysql
yum reinstall mysql-server

Then started the mysql server again
/etc/rc.d/init.d/mysqld start

This time the startup automatically created
brand new 'mysql' database.

This time I was able to login to mysql with as root user and without a password:
/usr/bin/mysql -u root

Once Logged in I changed password:
mysql> UPDATE mysql.user SET Password = PASSWORD('newpwd')
-> WHERE User = 'root';
mysql> FLUSH PRIVILEGES;

Done!

How to build and install Postfix on 64 Bit CentOS or RedHat

How to build latest postfix from source with MySQL and PCRE support on
64 bit Linux (CentOS or RHEL)

First make sure you have Mysql and pcre libraries installed, in not, then install them

#yum install mysql-devel pcre-devel

Then download the latest source for Postfix, cd into the Postix directory,
it should have several fines, and MUST have Makefile.init

From this directory type:

make -f Makefile.init makefiles \
'CCARGS=-DHAS_MYSQL -I/usr/include/mysql -DHAS_PCRE -I/usr/include' \
'AUXLIBS=-L/usr/lib64/mysql -lmysqlclient -lz -lm -L/usr/lib64 -lpcre'

Then type make
then "make install"

if will ask several questions, just accept defaults by hitting "Enter"
This is it

Now stop and restart your sendmail
/etc/rc.d/init.d/sendmail stop
/etc/rc.d/init.d/sendmail start

Now check to make sure that mysql and pcre are on the list
of supported posfix maps:

type: /usr/sbin/postconf -m

You should see mysql and pcre in the list of maps

Of cause make sure to properly edit the configuration files
in the /etc/postfix directory.

That's a whole new big article (more like a small book), so I am not going to explain about postix
configuration here.

Friday, September 10, 2010

php 5.3.3 skipping incompatible /usr/lib/mysql/libmysqlclient.so

If you having problem building php 5.3 on 64 bit Linux and getting some errors about
skipping incompatible /usr/lib/mysql/libmysqlclient.so when searching for -lmysqlclient

You just need to specify the correct path to where the 64bit libs are for mysql

Do this before running ./configure:

export LDFLAGS=-L/usr/lib64/mysql

Sunday, August 29, 2010

Php suddenly died, no error messages


A very nasty error occurs in php is you declare the same instance variable more than once
in the same class (you know, if the beginning of the class file)
or for that matter the method with the same name is declared twice in the same class

This is an easy mistake to make, but it causes the php to die with very little
error. In fact, depending on your error reporting level you may never even see
any errors in the error log, no errors on the screen, nada!

All you will see is that suddenly your script is dead. I mean completely dead, objects
not even instantiating.

This is nasty, so watch our for that!

Saturday, August 28, 2010

How to make php DOMDocument Serializable

The default DOMDocument class in php is not serializable.
That is, if you run $myDOM = serialize($oDOM), then unserialize($myDOM)
you will get back the object of type DOMDocument, but the data
will be lost, so you will basically get back the empty DOM Document,
not even the root element will be there, nada!

But it's easy to fix that. All you have to do is
extend the DOMDocument and implement Serializable interface

This is how you do it:

class MyDOMDocument extends DOMDocument implements Serializable
{

public function __construct(){

parent::__construct();

}

public function serialize(){
$s = $this->saveXML();
return $s;
}

public function unserialize($serialized)
{
$this->loadXML($serialized);

}
}

Ok, now if you serialize() and then unserialize() you will get back
the object of type MyDOMDocument and it will have the same data
as it had before serialization.

Of cause this will only work with PHP 5.2 or better and SPL libraries enabled (they are by default in php5)

Friday, August 27, 2010

Weird stuff with ArrayObject after exchangeArray()

OK so if you have extended php ArrayObject

then set extra property in object,
then exchangeArray() with new array

What happends to that extra property?
Right now it looks like that property is gone, which is odd
because only the internal array should be changed but it looks
like as if the whole object has been recreated.

Interesting to know. I must do an experiment and
get a definitive answer.

Monday, August 9, 2010

Common mistake that prevents Google from using your sitemap.xml file

According to official specification from sitemaps.org
(here: http://sitemaps.org/protocol.php#lastmoddef )
the format of the lastmod element in sitemaps file should be in the W3C Datetime format
but the actual time can be omitted.

One common mistake people make when generating sitemap file is to make the lastmod value in a format like this: YYYY-DD-MM HH:MM:SS
This is a wrong format and will not be understood by Google.
The correct W3C timestamp format is quite ugly, and looks like this:
(example) 1997-07-16T19:20:30.45+01:00

The best advice I can give you is to remove the HH:MM:SS and only leave the date part of the datetime, like this for example: 2010-03-23

This format is understood by all search engines and will not cause any problems.

Tuesday, July 6, 2010

How to get LogCat view pane in Eclipse Android SDK

In Eclipse with Android SDK installed:

Window > Show View > Other
Then expand Android and then select LogCat
You may also select other useful Views like Threads and Emulator Controls

Tuesday, June 29, 2010

Norton support phone number

Norton support phone number

800-745-6061

Monday, June 28, 2010

Firefox browser freezes up a lot

Have you ever had sex with a dead woman? Then you know what I mean. It's like you are trying to do something, waiting for it to respond but it just does not respond, ever...

This is what it feels like when using Firefox with many tabs opened. I don't mean too many, I mean like 5 or 6 tabs, especially if one tab was using flash player like maybe you were watching youtube in one tab.

I just keep restarting Firefox like 5 times a day or more, while I never have to restart the Chrome, I mean in days and even weeks, my Chrome is just open, many tabs are running, no problem.

Sunday, June 6, 2010

Best source for Apache server discussion lists

Apache server foundation is home to many interesting open source projects, not just web server related. Some are frameworks, some are CMS, and many are Java related projects.

If you want to keep up with all the discussions about these projects, there is a superb web based archive for the Apache projects mailings lists and forums, here is the url:

apacheserver.net

Check it out.

Sunday, May 30, 2010

New blog for Apache server admin tips

I started a new blog for tips about Apache server administration, including some tips for Apache on Windows as part of XAMPP package and also for Apache on Linux topics.

Here is the url: http://apacheservertips.blogspot.com/

Sunday, March 28, 2010

SQL_BUFFER_RESULT may return stale result

Careful with SQL_BUFFER_RESULT in your mysql SELECT statement
While this may speed up the selects (sometimes by a lot), it will also get you the cached result, in some cases the result may be stale, not reflecting the changes that took place after the previous result was cached.

This was probably not intended to be like that, may be just a weird behavior when using PDO and somehow temporary table that was created for that BUFFER_RESULT was not removed. I don't know why, I am not a mysql developer, I just know what I see - when using SELECT HIGH_PRIORITY SQL_BUFFER_RESULT .... with php PDO class, the result may be stale.

Thursday, March 25, 2010

MySQL table locks up

Another day, another total lockup of MySQL, when it locks up, it locks up and stays locked like a dead cunt - forewer.

Saturday, March 20, 2010

Looks like memcached was freezing Apache 2.2

Very bad idea to have both php extensions - memcache and memcached to be loaded at the same time.

I think this was causing the unexplained freezing of Apache 2.2

It was very difficult to track down the cause of Apache just freezing - no timeout error, no errors at all, just sitting there waiting forever for page to load.

After trying everything else, I decided to comment out loading memcached php extension and only load and use the good old reliable memcache extension.

Some tests claim that memcached is faster than memcache, but the difference is basically in single milliseconds, like who cares.... Not important when you usually saving couple of seconds worth of complex sql selects (some long sql selects that have several LEFT JOINS sometimes take 15 seconds when mysql has to create temporary table).

Anyway, I don't know if the problem was that some of the sites on the server were using memcache and some were using memcached, so I needed to load both extensions in php.ini

After ditching the memcached and only using memcache, the problems with Apache seemed to go away. Keeping my fingers crossed, so far so good.

Wednesday, March 17, 2010

Eclipse PDT freezes like a cunt

The eclipse PDT freezes on my brand new Windows 7 PC the same way it used to freeze on XP, just like a good old CUNT it is.

Google friend connect integration thoughts

When you have value of fcauth cookie from Google Friend Connect
but user has unjoined your site, then when you
request the data from gfc server you get the 401 error status with this message:

Anonymous requests are not allowed to fetch data
Error 401

This is an easy way to know that the fcauth cookie is not good anymore and you should delete it from the table in case you are storing that value in a table.

It also indicates that user is not a member of your site via his GFC thingy.

What is the best way to auto-login GFC user to your site? The oblivious choice is via fcauth cookie, get data from GFC server and login/create oViewer object.
But this can slow down the page load in case the GFC server is slow to respond.

A faster choice is to log him in via your own uid cookie, then add some DIV tag to your page and then have JavaScript on your page to make ajax call back to your server, on your server check with GFC server and upon success return a couple of links to the browser. The links will be to 'Friend connect settings' and 'invite friends', then have your JavaScript callback to add these links to the page

If GFC auth in unsuccessful then remove fcauth cookie from user record, indicating that user in not subscribed to your site anymore. In this case have your http response to delete the fcauth cookie so you don't have to go through this again.

The downside to this is that you have to make an extra request to server right after the page renders (via ajax this time)

Tuesday, March 16, 2010

php setcookie for array of cookie

On the php manual page for setcookie() function
is says you can use setcookie() to set array of cookies

http://us2.php.net/manual/en/function.setcookie.php

This is convenient, but also a bit misleading. It leads you to believe that you are setting just one cookie with the array of values, but in fact the browser actually setting new cookie for each new array element.

So you may be setting 10 different cookies and not even knowing about it. A better solution is to set just one cookie with the name/value pairs like
userid=12331&name=john&group=admins&firstvisit=20091010

You can use http_build_query() to build a string that will then become your cookie value.

See, it looks similar to url.

To get values from the cookie, just get the cookie using the
$val = $_COOKIE['cookiename'];
and then:
parse_str($val, $aVars);
now the $aVars contains the name => value pairs
Just treat the values with caution just like any other user-passed variables. Validate, sanitize, whatever you normally do with values passed by user.

Friday, March 12, 2010

username-less paradigm

Just found out that on Facebook the username is optional
Everyone is known by their real first and last name. So Facebook API in most cases does not return value for username because it's optional and most people never set it up.
I just find this unusual but at the same time they may be on to something.
This makes it so much easier to integrate the Facebook Connect into your existing login system - because there could not be any name collisions with existing users in your database

Wednesday, March 10, 2010

Php can only count to 10 (sort of)

Careful when casting large number to integer in php
You probably used to do this $val = (int)$val;
in php as a way to be sure that $val is an integer.

Some people do this for added security, since integers cannot contain any type of
script or html tags, so it's an easy way to sort-of sanitize the string.

But.. but... but ..... but....

Php like a child that can only count to 10, can only count to 2147483647
That's right, I did not expect this either.

Any number larger than 2147483647 php just does not know!
This means when you try to case any number larger than 2147483647 to integer using (int)$val, php will just return 2147483647

This is terribly wrong, certainly should be considered a bug!

If php does not know any integers larger than 2147483647, then it should raise error when you try to convert a larger number, not return the largest number it knows!

This can cause some weird problems in your code.
In my case I discovered this bug when working with Twitter API
The Twitter has billions of status messages, so all the latest status_ids are larger than 2147483647, so I was doing what I thought was a good practice and casting these status ids to integer with (int), but php was quietly replacing all the actual values with the 2147483647

By the way, it was php version 5.2.9, which is fairly new version. I mean, I would not be surprised to see this bug in php prior to 5, but in 5.2.9?!

That's crazy.

Monday, March 8, 2010

Some near-term todos for qod site

Some feature to add to qod soon:
use javascript api to see if logged in user is following question owner and if not, then add "Follow " button which will point to user server and we can follow the user of behalf of the logged in user.

Add 'Other questions by this member'

Add 'Invite friends to join' but not sure how this will work - show a list of friends or just tweet about the link?

Sunday, March 7, 2010

Normalizing utf-8 string for Twitter API

In order to send Unicode (utf-8 to be exact) text to Twitter via Twitter app, you must first run the string through the php Normalizer class

This class comes with php 5.3 but before the 5.3 you need to build the lib yourself and then install extension from pecl

Then, once you have the Normalizer class, just do this:
Normalize::normalize($string,Normalizer::FORM_C)

This is not always necessary as most utf-8 strings and chars are already "just fine", it's just that some fairly rare chars can be considered 'not normalized'.

This means that Twitter will still accept them, they will even be rendered by the end user browser in most cases, it's just that Twitter may count such chars as 2 chars instead of just one, and you know in Twitter every char counts.

Basically you really want to make sure that utf-8 strings are normalized before you send then to Twitter from your API because otherwise you may run into situation that your message unexpectedely exceeds 140 chars and will be rejected by Twitter API.

Normalize::normalize($string,Normalizer::FORM_C)

And here is the info from php
http://www.php.net/manual/en/book.intl.php

http://php.net/manual/en/class.normalizer.php

Saturday, February 20, 2010

changing value of meta tag with javascript

Interesting:
if you assign value of meta tag element in javascript
using the
eMeta.setAttribute('content', somenewvalue);

it will not be found if looking for for it this way:
eMeta.content but the attribute value of 'content' will actually
be set and could be seen in Firebug right away.

But it will work if just setting value by assignment, like this
eMeta.content = 'somenewval';

This is in Firefox, not sure how it will work in other browsers

Tuesday, February 16, 2010

oAuth Signin with Twitter via popup window design pattern

It looks like couple of well made sites use the same pattern for logging in with twitter via the popup window:

The DISCUSS widgets have this pattern:
Dsq.Twitter = new function() {
var that = this;

this.startTwitterConnect = function() {
var popupParams = 'location=0,status=0,width=800,height=400';
that._twitterWindow = window.open(Dsq.jsonData.settings.disqus_url + '/_ax/twitter/begin/', 'twitterWindow', popupParams);
that._twitterInterval = window.setInterval(that.completeTwitterConnect, 1000);
};

this.completeTwitterConnect = function() {
if (that._twitterWindow.closed) {
window.clearInterval(that._twitterInterval);
window.location.reload();
}
};
};


and the twitgoo.com also have very similar pattern:

TG.util.oauth = {
win: null,
timer: null,
loginUpdate: function() {
$.getJSON('/-login/check?format=json', TG.util.oauth.loginCallback);
},
loginCallback: function(data) {
if (data && data.loggedin) {
TG.util.login.update(data);
}
},
winCheck: function() {
if (!TG.util.oauth.win || TG.util.oauth.win.closed) {
window.clearInterval(TG.util.oauth.timer);
return TG.util.oauth.loginUpdate();
}
},
loginClick: function() {
TG.util.oauth.win = window.open('/-oauth-twitter/request?gotoafter=1&gotor=oauthtwitter&gotop=action%3Dwindowend',
'OAuthTwitterRequest',
'width=800,height=450,modal=yes,alwaysRaised=yes');
if (!TG.util.oauth.win) return true;

TG.util.oauth.timer = window.setInterval(TG.util.oauth.winCheck, 300);
return false;
}
};


This means that the callback url - the one that Twitter redirects to after the oAuth dance is complete contains ONLY the window.close() javascript and basically does nothing else at the browser. It's main job is do populate the oViewer object on the server so that when the main window is reloaded it will determine that user is now logged in. OK, one more thing that callback window can do is to set some sort of cookie.

I can see a legitimate reason to do this because what if user closes the browser popup window manually? Then we will never get to the part where the JS in the popup window calls the window.opener
So there is a very small chance that user will be successfully logged in but because he closed what window manually, the main window will never know.

I guess I'll go with that pattern now, after all, I've seen in on 2 well built sites and also the same pattern is recommended on Google OpenSocial developers page.

This is actually very easy to code because you don't need anything special as far as in php of the callback url, only static HTML and OK, possibly setting of cookie, but I'm not even sure that it's even necessary to set this cookie.

Monday, February 15, 2010

CakePHP pages shows ads for wedding cakes

Google shows ads for wedding cakes, birthday cakes,
even geo-targeted bakeries based on my IP address when I view the page about CakePHP

Another proof that Google is not very smart when it comes to parsing words that have more than one meaning.

in reference to: Re: Reg: How to learn cakephp (view on Google Sidewiki)

Tuesday, February 9, 2010

Firefox consumes too much memory

Firefox is a memory-hungry cunt. I have to restart it every couple hours otherwise it keeps consuming up to 800Megs of RAM

Thursday, January 28, 2010

Google live search is shockingly stupid

Can't beleive how dump the Google live search is!
Ok, I searched for "REST or RPC" which are the 2 technical terms for protocols, so I was looking for find the answer which one I should be using in my application.

So, Google added results from live twitter stream on the first page, some of them go like this "I should go get some rest"
or "the rest of the album is..."

Com'on Google, my son can write a smarter search engine - just filter out the VERY common words or at least don't show results for words that can have more than one meaning if you don't know which one of the meanings I am searching for.

What's the name for such words anyway, (words with more than one meaning)? I forgot, I better go Google it.

Thursday, January 21, 2010

Programming discussions tips

A convenient way to follow the latest discussions of the most
popular php and javascript projects is to keep an eye on the
mailing lists.

One good place to watch the latest lists is on this discussions site
It's updated in real time as soon as any new message arrives to any of the many programming lists they track.

There is also a way to reply, you just need to register and you good to go.

Friday, January 15, 2010

Enhances Search Results on Yahoo Serp pages

Just want to bookmark this page.
It contains valuable info on how to enhance the site markup to allow extra cool snippets on yahoo search results page - right on SERPS.

I especially like the Discussion, News and Video section, but Documents and Events and even Games look very promising too. The Games, however require them to be written in flash. I am not 100% sure but at least the example on Yahoo site is in flash.

It would be cool if Javascript games were also allowed.

Very interesting: at the bottom of the page there is a link to "Build a Custom App", so basically Yahoo also allows to build custom app and have it included in enhances SERP.

in reference to: SearchMonkey - Getting Started (view on Google Sidewiki)

Yahoo allows microformats to hint discussion

Very interesting. Yahoo allows to add
a microsofmat or RDF to indicate that a blog with comments or a forum discussion takes place.
Yahoo will then include this data in the enhanced search results page.

http://developer.search.yahoo.com/help/objects/discussion

in reference to:

"Description Display blog or forum information directly in Yahoo! Search. Add code to indicate to Yahoo! that a discussion exists on your page, and when we next crawl your site, we'll take care of the rest. From your markup, we’ll be able to extract structured data from your site and render it automatically in an enhanced result in search results."
- SearchMonkey - Discussion (view on Google Sidewiki)

Wednesday, January 13, 2010

2 Interfaces cannot contain the same method names

Impotrant: 2 Interfaces cannot contain the same method name and be
implemented in the same class

For example:

interface LampcmsResourceInterface
{
/**
* Returnes id of user (USERS.id)
* who owns the resource
*
* @return int
*/
public function getOwnerId();

public function getResourceId();

}


and then a
interface Zend_Acl_Resource_Interface
{
/**
* Returns the string identifier of the Resource
*
* @return string
*/
public function getResourceId();
}

This is not a problem as long as you don't try to implement
both in the same class.

You may assume that if your class has a method

getResourceId() then you can safely say it implements both LampcmsResourceInterface and Zend_Acl_Resource_Interface
but this is not true

if you try to write a class like this

class MyResource implements LampcmsResourceInterface, Zend_Acl_Resource_Interface
{

protected $resourceID = 100;

public function getResourceId(){

return $this->resourceID;
}



}

You will get fatal error when you try to instantiate this class:

Fatal error: Can't inherit abstract function Zend_Acl_Resource_Interface::getResourceId() (previously declared abstract in LampcmsResourceInterface)

The best course of action now would be to
change the LampcmsResourceInterface to only have one required method getOwnerId();

Then if you need an object that MUST have getOwnerID() and getResourceId()

just make a class and declare it as implements LampcmsResourceInterface, Zend_Acl_Resource_Interface

Thursday, January 7, 2010

Correct way to handle deleted messages and posts

The right way to delete message is to just mark it as deleted in the database.
Sure, we can also delete a record from MESSAGE_BODY if we keep a separate table just for message bodies.

Don't just mark it as deleted, but actually use a timestamp value for the 'deleted_ts' column.

The reason for that is that we will them be able to spot that the message has been deleted and not just 'does not exist'.

One advantage of knowing that it has actually been deleted and not just 'not found' is that we will be able to return a 410 response code instead of the normal 404

The difference between 410 and 404 is that search engines will not attempt to retry getting the same page again and again. The 410 basically says 'gone permanently' instead of just 'not found'

It may actually cause Google to delete this page from Google cache very fast.
Actually we can even give Google another hint to remove such page from cache. When we catch the 410 exception we may add an extra meta tag NOCACHE or NOARCHIVE, whatever it is that Google understands as 'don't use cached version'

This can be very helpful. And of cause by marking message as deleted instead of actually deleting it, we are not breaking the 'next', 'previous' navigation.

The 'next'/'previous' nav is another story, and maybe we actually should not use the 'next'/'prev' links of deleted pages because if many messages have been deleted we don't want to point to 'prev' which has also been deleted, we want to point to the first non-deleted page, but that will require a different logic. Later...

Also when we know that timestamp of when the message has been deleted we can show it to the user on the 410 page. So, we not only sending 410 response code but we can also show 'message was deleted on Dec 12, 2009' for example

This is also extremely helpful to the user.

Monday, January 4, 2010

Google's official paid links ban policy

Very interesting post (from google employee) about their take on paid links:

http://www.mattcutts.com/blog/how-to-report-paid-links/

It also explains how to report paid links to google, which is great!

Sunday, January 3, 2010

You can have your blog included on Google news

You know you can have your own news included
in the Google news.

I did not know that, but here it is:

http://www.google.com/support/news_pub/bin/answer.py?hl=en&answer=40787


Submitting Your Content: Google News
Print

If you'd like your news site or blog to be included in Google News, please send us the URL and we'll be happy to review it. Please note, however, that we can't guarantee we'll be able to include your site in Google News.

Shocking rel nofollow abuse by major players

nofollow is sort of like reverse cloaking: it presents different
content to the search engine than to the average user:

To the average user it looks like a link, yet to the search engine it looks like
it's not a link.

This is indeed a reverse cloaking - a reverse because it's initiated not by
a user with the purpose to trick, scam, screw! the search engine, but it was invented
by a search engine with a purpose to screw the user.

What do you think? Do you think I'm right?

Anyway, the nofollow originally was made popular by google, so other search
engines agreed that it was a good idea and decided to follow suit.


nofollow abuse:
digg
twitter
stubledupon

but also: (just a random example) http://stackoverflow.com/users/191837/kevin-peno
On personal pages of registered user!

How lame is that! If admin suspects that a user is a spammer, he should
just remove the user.

Also, stackoverflow has such thing as ;reputation;
so they at the very least should remove nofollow from
members with decent reputation!

I like the stackoverflow but I wold not give them
my time of day and contribute anything to them
if all I get in return is a lame 'nofollow' link
back to me.


===============

Also on github.com

How lame is that - accounts on github are basically
open source software projects. If I contribute an open
source project, then the least you can do is give me a fully
normal link, not a nofollow shit.

you want me as another user of github, you want me
to link to you, yet you treat me like a spammer?
No, thank you. You can keep your github to yourself
and I will just setup my own site to host my own project.

-----------------

At least DIGG has some in-house algorythm that would remove nofollow links
once they establish a repuration for your resource, but it's not clear
how this works. Once thing is clear that if your have many diffs (like 100+)
then the nofollow is gone. What is not clear is what they take into account
They should take into account the user who submitted the diggs - an old
user who has not been flagged as spammer and submitted certain number of diggs should
be able to submit dofollow links.

By the way, do you know why they call it dofollow? You know, there is no such thing as
dofollow attribute,.... it's just because the other way to describe links without a nofollow tag
is to call them nonofollow link. And that sounds pretty stupid.

========================

The right way to use nofollow is ONLY in comment or user submitted content like
a forum. Even then, a system should be in place that would allow good members to
post good links. Period! Don't slap a cookie-cutter nofollow attribute on all
links!

==============

Who else got it wrong? Probably the blogger. They are right to add nofollow to links
in comments, but they probably should not be slapping the nofollow to links
to other members who commented. I mean if it's a spam fighting technique, then
Blogger should be able to develop the best anti comment spam in the world, after all
they have access to real-time blog comments from millions of users.

If a user is a spammer, then blogger can just remove the whole user's account, making
all the hard work the user made in adding comments totally useless.

==================


Who's got it right? youtube! Then don't slap nofollow to links to user accounts from comments,
to links to friends and subscribers.

They even allow 1 normal link to your external website from youtube account page. More than one
link is OK, you can just add it by the way of editing the HTML of your channel description
but all such links are indeed nofollow links.

Who else got it right? livejournal does not add nofollow links to members from the comment pages
but it also does not add nofollow to any links in comments. This creates comment spam problem on
livejournal which they fight by letting user to require captcha on their comment pages.

=======================================


Who else is abusing it? Some forum software like vbulletin usually adds nofollow
to all incoming posts and there is no way to use any intelligent algorythm to
no add nofollow from trusted members.

also they seem to add a nofollow link even to links from personal profile pages
and many webmasters don't even allow viewing a profile page for not logged in user.

=======================

Once forum sofware that is pretty good with not abusing nofollow is simplemachines forum
The link from profile page is a normal link and is usually seen by not logged in user

require_once inside the method in php class

I've heard on some discussion list that if you have
require_once inside one of your methods in a php class then php will still evaluate
this require_once statement at compile time.

What these people were trying to say is that you should not have require_once or any other
similar statement inside your methods because it will slow down your script since php
will have to look at every such statement and make sure that there files are actually available.

I don't know, but I think it's a myth.

I took one of the classes from Zend, the Zend_Acl class
and inside the add() method there is a statement:

if (!$role instanceof Zend_Acl_Role_Interface) {
require_once 'Zend/Acl/Exception.php';
throw new Zend_Acl_Exception('addRole() expects $role to be of type Zend_Acl_Role_Interface');
}

So I just changed the require_once 'Zend/Acl/Exception.php';
to require_once 'nd/Acl/Exception.php';
This of cause points to non-existent php file, and would raise an error.

But php loaded my Acl class just fine. Not only it loaded my Acl class fine, but it even allowed
me to call the add() method. So as long as my script did not
pass this test: if (!$role instanceof Zend_Acl_Role_Interface)
php did not complain at all.

So there you have it, a proof that php does not care about your require_once statements until it actually executes these statements.

So, don't worry about this silly issue then - it is OK to have require_once inside the methods
but it's just as OK to completely rely on autoloader.

Personally I always use autoloader, so when I decided to use Zend_Acl class my first instinct was to just comment out all the require_once statements since they really hurt my eyes. Hey, I am not used to seeing require_once in my classes at all - that's what the spl_autoload and __autoload are for.

But then I though that I am going to be a good programmer and will not mess with an existing class - if I need some changes in the class, then I will extended like any good programmer should. And that what lead me to this test - I just wanted to be sure that having require_once inside the method will not cause any type of performance penalty. And it did not.

OK, I said too much already about this tiny issue.

Bye now.