Этот код чрезвычайно трудно читать, потому что вы объединили побочные эффекты (назначения) со сложными условиями, включающими несколько логических операторов. Давайте попробуем записать это в виде набора отдельных операций:
// First condition to be evaluated is isset($user)
$haveUser = isset($user);
// If that condition is false, the && will lazily skip the next part
if ( $haveUser ) {
// Now we conditionally assign $carrinho ...
$carrinho = $user->getCarrinho();
// ... and test its value
$haveCarrinho = ($carrinho != null);
}
// Having done all that, we combine the two conditions
$haveBoth = $haveUser && $haveCarrinho;
// Now we invert that condition for our if statement
if ( ! $haveBoth ) {
// We know here that $carrinho has either never been set (because $haveUser was false) ...
// ... or it was null (setting $haveCarrinho to false)
// Line 3 - another if statement to unpack
$haveIdInData = isset($data['carrinho_id']);
// If that condition is false, the || will shortcut
if ( ! $haveIdInData ) {
$carrinho = Carrinho::salvar([]);
}
// If we don't short-cut, the rest of line 3 runs
else {
// Try finding it by the ID in $data
$carrinho = Carrinho::find($data['carrinho_id']);
// If it's null, we short-cut at the next ||
if ($carrinho == null) {
$carrinho = Carrinho::salvar([]);
}
else {
// Else we make the next check
if ($carrinho->usuario_id != null) {
$carrinho = Carrinho::salvar([]);
}
}
}
// On to line 4! Reusing our condition from above, since the state of $user won't have changed
if ( $haveUser ) {
// This will give a horrible error if $carrinho is null
$carrinho->setUsuario($user->id);
}
}
// We've reached line 5, and expect $carrinho to be set, but we have no guarantee of that at all!
Это много логики c для 4 строк кода!
Немного убирая, не делая это как crypti c как оригинал, я думаю, что это эквивалентно:
$carrinho = null;
if ( isset($user) ) {
// Now we conditionally assign $carrinho ...
$carrinho = $user->getCarrinho();
}
if ( $carrinho == null ) {
if ( isset($data['carrinho_id']) ) {
$carrinho = Carrinho::find($data['carrinho_id']);
if ($carrinho == null || $carrinho->usuario_id != null) {
$carrinho = Carrinho::salvar([]);
}
}
if(isset($user)) {
$carrinho->setUsuario($user->id);
}
}
Теперь мы можем видеть то, что, вероятно, предполагалось: строка Carrinho::salvar
должна быть резервной для любого другого неопределенного состояния, скорее чем вложенный в других условиях.
Приложив немного усилий, мы можем полностью устранить вложенные условия, предоставив нечто гораздо более читабельное, например:
// Initialise variables to a known state
$carrinho = null;
$loadedFromUser = false;
// Try on user object
if ( isset($user) ) {
$carrinho = $user->getCarrinho();
$loadedFromUser = ($carrinho != null);
}
// Not found? Try looking up by input data
if ( $carrinho == null && isset($data['carrinho_id']) ) {
$carrinho = Carrinho::find($data['carrinho_id']);
}
// Discard if it already has a user ID, but wasn't loaded from user
if (!$loadedFromUser && $carrinho != null && $carrinho->usuario_id != null) {
$carrinho = null;
}
// Still not found? Create an empty one
if ($carrinho == null) {
$carrinho = Carrinho::salvar([]);
}
// Now we know we have an object some way or another, and can assign a user ID to it
if(isset($user) && !$loadedFromUser) {
$carrinho->setUsuario($user->id);
}
Некоторые из этих условий могут быть не совсем такими, как предполагалось, но разделив их, теперь мы можем намного проще следовать логике c и вносить соответствующие изменения.