You must pass arguments in the order that you declare in your method signature, whether they're optional or not. That means you must specify $x before $y, no matter what.
If you don't need to pass any other value of $x, you'll have to pass null. You can still skip the remaining optional arguments, of course:
$object->doSomething(NULL, 3)
Additionally, PHP does not support named arguments. Therefore, you cannot explicitly write $y in the calling code because in PHP that actually sets $y within the scope of the calling code, and not the scope of doSomething()'s method body.
EDIT: per dpk's suggestion, as an alternative route you can change the method to accept a hash (associative array) instead, and optionally overwrite some defaults and extract() the values of it into scope:
public function doSomething(array $args = array()) {
$defaults = array('x' => NULL, 'y' => NULL, 'a' => NULL, 'b' => NULL);
extract(array_merge($defaults, $args));
// Use $x et al as normal...
}
In your calling code:
$object->doSomething(array('y' => 3));