- Старайтесь делать отступы как можно меньше
- Удаляйте ненужные блоки в условиях
- Меняйте местами условия, чтобы уменьшить отступы
- Используйте switch вместо if там, где это возможно
- Разбивайте сложные уравнения для краткости
- Расставляйте условия в логическом порядке в операторах if
- Предпочитайте именованные методы флагам
- Используйте деструктуризацию массива
- array_column для маппинга данных
- Не используйте array_merge в циклах
- Не используйте isset() для проверки существования элемента массива
До
class DiscountApplier
{
private DiscountCalculator $calculator;
public function __construct(DiscountCalculator $calculator)
{
$this->calculator = $calculator;
}
public function apply(Basket $basket): void
{
if ($basket->hasItems()) {
$discount = 0.0;
foreach ($basket->getItems() as $basketItem) {
if ($basketItem->isTaxable()) {
if ($basketItem->getPrice() > 0) {
$discount += $this->calculator->getDiscount($basketItem);
}
}
}
$basket->applyDiscount($discount);
}
}
}
После
class DiscountApplier
{
private DiscountCalculator $calculator;
public function __construct(DiscountCalculator $calculator)
{
$this->calculator = $calculator;
}
public function apply(Basket $basket): void
{
if (!$basket->hasItems()) {
return;
}
$discount = 0.0;
foreach ($this->getDiscountableItems($basket) as $basketItem) {
$discount += $this->calculator->getDiscount($basketItem);
}
$basket->applyDiscount($discount);
}
/**
* @return iterable<BasketItem>
*/
private function getDiscountableItems(Basket $basket): iterable
{
foreach ($basket->getItems() as $basketItem) {
if (!$basketItem->isTaxable() || $basketItem->getPrice() === 0) {
continue;
}
yield $basketItem;
}
}
}
До
function mapOrderStatusToLabel(Order $order): string
{
if ($order->isComplete()) {
return 'Completed';
} elseif ($order->isPending()) {
return 'In transport';
} else {
return 'New';
}
}
После
function mapOrderStatusToLabel(Order $order): string
{
if ($order->isComplete()) {
return 'Completed';
}
if ($order->isPending()) {
return 'In transport';
}
return 'New';
}
До
function act(bool $success)
{
if ($success) {
// towering block of code
// towering block of code
// towering block of code
// towering block of code
// towering block of code
// towering block of code
// towering block of code
} else {
// one liner
}
}
После
function act(bool $success)
{
if (!$success) {
// one liner
return;
}
// towering block of code
// towering block of code
// towering block of code
// towering block of code
// towering block of code
// towering block of code
// towering block of code
}
До
function mapOrderStatusToLabel(Order $order): string
{
$label = 'unknown';
if ('complete' === $order->getStatus()) {
$label = 'Completed';
}
if ('pending' === $order->getStatus()) {
$label = 'In transport';
}
if ('new' === $order->getStatus()) {
$label = 'New';
}
return $label';
}
После
function mapOrderStatusToLabel(Order $order): string
{
switch ($order->getStatus()) {
case 'complete':
return 'Completed';
case 'pending':
case 'in_transport':
return 'In transport';
case 'new':
return 'New';
default:
return 'unknown';
}
}
До
function getTotalWithTax(Payment $payment, int $taxPercent): float
{
// is the order correct at all?
return (float) (int) $payment->getTotal() * (1 + $taxPercent / 100);
}
После
function getTotalWithTax(Payment $payment, int $taxPercent): float
{
// descriptive variables with intermediary values for easier debugging
$paymentAmount = (int) $payment->getAmount();
$taxCoefficient = 1 + ($taxPercent / 100);
$totalWithTax = $paymentAmount * $taxCoefficient;
return (float) $totalWithTax;
}
До
if ($httpApi->hasAccess($user) && $user->isActive() && $isSuccess) {
// all conditions must be met in order for this condition to execute
// in case of 'and' we should keep the heaviest conditions last
// and the fastest to execute in front
}
После
if ($isSuccess && $user->isActive() && $httpApi->hasAccess($user)) {
// if $isSuccess is false
// other conditions will not be evaluated
}
До
class UserRepository
{
public function getUsers(?bool $includingDeleted = false): array
{
}
}
После
class UserRepository
{
public function getUsers(): array
{
}
public function getUsersIncludingDeleted(): array
{
}
}
До
$workers = [
['id' => 1, 'name' => 'John Doe'],
['id' => 3, 'name' => 'Jane Doe'],
['id' => 4, 'name' => 'Monica Trullo'],
['id' => 5, 'name' => 'Jonathan Bank'],
];
foreach ($workers as $worker) {
$workerId = $worker['id'];
$workerName = $worker['name'];
// …
}
После
$workers = [
['id' => 1, 'name' => 'John Doe'],
['id' => 3, 'name' => 'Jane Doe'],
['id' => 4, 'name' => 'Monica Trullo'],
['id' => 5, 'name' => 'Jonathan Bank'],
];
foreach ($workers as ['id' => $workerId, 'name' => $workerName]) {
// …
}
До
$userAvatars = [];
foreach ($users as $user) {
$userAvatars[$user['id']] = $user['avatar'];
}
После
$userAvatars = array_column($users, 'avatar', 'id');
На каждой итерации PHP копирует массив в другой временный массив, что приводит к временному выделению памяти. С каждой последующей итерацией объем используемой памяти увеличивается.
До
$result = array();
foreach ($sources as $source) {
$result = array_merge($result, $source);
}
После
$result = array_merge(...$sources);
До
$moneyInTheBank = [
'John' => 10,
'Alex' => 0,
'Jenna' => 69,
'Olivia' => null
];
if (!isset($moneyInTheBank['Olivia'])) {
$moneyInTheBank['Olivia'] = 20;
}
echo $moneyInTheBank['Olivia'];
// outputs 20
После
$moneyInTheBank = [
'John' => 10,
'Alex' => 0,
'Jenna' => 69,
'Olivia' => null
];
if (!array_key_exists('Olivia', $moneyInTheBank)) {
$moneyInTheBank['Olivia'] = 20;
}
echo $moneyInTheBank['Olivia'];
// outputs NULL