array_shift() expects parameter 1 to be array, boolean given in include()
How do you mean by "that doesn't work"? The problem is likely because field_get_items returns FALSE if the field doesn't exist on that node. Checking if $foo is empty (using empty) should work.  So something like:

$foo = field_get_items('node', $node, 'field_foo');
if (!empty($foo)) {
  $foo_shift = array_shift($foo);
  $foo_value = $foo_shift['value'];
}


Alternately, because field_get_items returns false when it doesn't have a value to return, you could just put the $foo = ... line in the if statement itself:

if ($foo = field_get_items('node', $node, 'field_foo')) {
  $foo_shift = array_shift($foo);
  $foo_value = $foo_shift['value'];
}


The problem with isset is that it's just checking if the variable has a value attached to it. FALSE doesn't ping it as not being set, whereas FALSE is included in the list of values that are considered empty for empty.

The "Just to Remind" section of this posts: http://alexchernomaz.com/2014/10/14/php-empty-isset-is_null/ provides an excellent table of what values are considered empty/null/set for each function (empty, is_null, and isset), if you're interested in learning more.