preg_replace can accept arrays:
$new_name = preg_replace(array('/\s+/', '/\W/'), array('_', '-'), $old_name);
This is more eloquent, but I do not think it is more effective. Documents do not indicate the order in which regular expressions are applied. Since space characters are not word characters, a safer version:
$new_name = preg_replace(array('/\s+/', '/[^\s\w]/'), array('_', '-'), $old_name);
source share