ru
Feedback
PHP | Вопросы собесов

PHP | Вопросы собесов

Открыть в Telegram
2 347
Подписчики
+124 часа
-87 дней
-2430 день
Архив постов
🤔 Как сделать так, чтобы приложение разворачивалось быстрее в Docker`е? При развёртывании приложения в Docker важно минимизировать время сборки и оптимизировать слои контейнера. 🟠Использовать `.dockerignore` Не копировать лишние файлы в контейнер (например, node_modules, .git, vendor, .env).
.git
node_modules
vendor
.env
*.log
🟠Оптимизировать `Dockerfile` (Меньше слоёв, кэширование) Плохо (лишние слои, без кэширования)
FROM php:8.2-cli

WORKDIR /app

COPY . .      # Копирует ВСЕ файлы (долго и некэшируемо)
RUN composer install
RUN npm install
RUN npm run build
Хорошо (разделение слоёв, кэширование)
FROM php:8.2-cli

WORKDIR /app

COPY composer.json composer.lock ./
RUN composer install --no-dev --prefer-dist # Используем кэширование слоёв

COPY package.json package-lock.json ./
RUN npm install --only=production && npm cache clean --force

COPY . . # Копируем код ПОСЛЕ установки зависимостей (чтобы кэширование работало)
RUN npm run build
🟠Использовать `multi-stage builds` (если контейнер весит много) Позволяет уменьшить размер конечного образа, убрав ненужные файлы и инструменты.
# 1-й этап: сборка зависимостей (Node.js)
FROM node:18 as frontend
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm install
COPY . .
RUN npm run build

# 2-й этап: финальный образ
FROM php:8.2-cli
WORKDIR /app
COPY --from=frontend /app/dist /app/public # Берём только готовые файлы
COPY . .
CMD ["php", "artisan", "serve", "--host=0.0.0.0"]
🟠Использовать `docker build --cache-from` Позволяет использовать кеш из предыдущих сборок.
docker build --cache-from=myapp:latest -t myapp .
🟠Оптимизировать `docker-compose` (если используется) Перенести volume для vendor и node_modules на хост, чтобы не скачивать их в контейнере.
services:
  app:
    build: .
    volumes:
      - .:/app
      - /app/vendor  # Чтобы composer install не запускался каждый раз
      - /app/node_modules # Чтобы npm install не замедлял перезапуск
🟠Использовать `Alpine Linux` (если важен размер образа) Alpine – лёгкая версия Linux (~5 MB), подходит для PHP, Nginx, Node.js.
FROM php:8.2-fpm-alpine
Ставь 👍 и забирай 📚 Базу знаний

🤔 Что такое динамическая типизация Динамическая типизация — это свойство языка программирования, где тип переменной определяется во время выполнения, а не во время компиляции. Это позволяет использовать одну переменную для хранения данных разных типов, упрощая код, но также увеличивая вероятность ошибок, так как проверки типов происходят в процессе выполнения. Языки с динамической типизацией, такие как Python и JavaScript, предлагают большую гибкость, но требуют внимательности при работе с типами. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний

🤔 Что такое абстрагирование? Это принцип программирования и проектирования, который позволяет выделить важные характеристики объекта или системы и скрыть их сложные детали. Основная цель абстрагирования – упростить сложные системы, делая их более понятными и управляемыми, сосредоточив внимание на их основных аспектах и поведении. 🚩Зачем нужно абстрагирование 🟠Снижение сложности Сокращает количество деталей, с которыми нужно работать, что облегчает понимание и работу с системой. 🟠Повышение читаемости кода Упрощает код, делая его более читаемым и легким для поддержки. 🟠Повторное использование кода Создаёт возможность повторного использования общих функций и логики. 🟠Инкапсуляция Позволяет скрывать реализацию и представлять только необходимые интерфейсы для взаимодействия. 🟠Гибкость и расширяемость Облегчает добавление новых функциональностей без изменения существующего кода. 🚩Как используется абстрагирование Абстрагирование в программировании часто реализуется через классы и интерфейсы. Ниже приведены примеры абстракции в объектно-ориентированном программировании (ООП). 🚩Пример абстракции с использованием классов и интерфейсов 🟠Интерфейс Определяет набор методов, которые должны быть реализованы, не указывая, как именно они должны быть реализованы.
interface Shape {
    public function draw();
}
🟠Классы, реализующие интерфейс Реализуют методы, определённые в интерфейсе.
class Circle implements Shape {
    public function draw() {
        echo "Drawing a circle";
    }
}

class Square implements Shape {
    public function draw() {
        echo "Drawing a square";
    }
}
Использование абстракции
function renderShape(Shape $shape) {
    $shape->draw();
}

$circle = new Circle();
$square = new Square();

renderShape($circle); // Вывод: Drawing a circle
renderShape($square); // Вывод: Drawing a square
🚩Плюсы и минусы ➕Снижение сложности Абстракция скрывает сложные детали реализации, облегчая работу с системой. ➕Улучшение читаемости Код становится более понятным и структурированным. ➕Гибкость и расширяемость Облегчает добавление новых функций и изменений. ➕Повторное использование Позволяет использовать общий код в разных частях программы. ➖Избыточность Иногда может приводить к избыточной сложности, если абстракции слишком сложные или используются неправильно. ➖Накладные расходы Может потребоваться больше времени и усилий на создание абстракций и их поддержку. Ставь 👍 и забирай 📚 Базу знаний

🤔 Что такое интерфейсы? Интерфейсы в PHP определяют набор методов, которые должны быть реализованы в классах, использующих этот интерфейс. Интерфейсы обеспечивают абстракцию, позволяя разработчикам определять общий функционал для классов, не предоставляя реализации методов. Классы могут реализовывать несколько интерфейсов, что делает их гибким инструментом для организации архитектуры кода. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний

🤔 Как устроен типичный тест на opening point? Тест на Opening Point (OP-тест) используется для проверки скорости, с которой игрок или программа находят критически важное первое решение в задаче. Такой тест чаще всего применяется в шахматах, игровых стратегиях, а также в программировании при оценке эвристик. 🚩Как устроен тест на Opening Point? 🟠Задаётся начальная позиция или состояние Например, шахматная позиция, игровая ситуация или входные данные для алгоритма. 🟠Требуется найти оптимальный (или хороший) первый шаг В шахматах это может быть лучший ход. В алгоритмах — первое удачное разбиение задачи. 🟠Замеряется время и корректность ответа Важно, насколько быстро испытуемый (или программа) нашёл первый ход. Проверяется, соответствует ли он эталону (оптимальному решению). 🚩Пример из шахмат В шахматах Opening Point тест оценивает, насколько быстро игрок или движок могут найти правильный ход в дебюте. Например: > Позиция: > 1. e4 e5 > 2. Nf3 Nc6 > 3. Bb5 a6 > 4. ? Ожидаемый ход: Ba4 (Испанская партия). Программа должна как можно быстрее выбрать этот ход, а тест фиксирует время поиска. 🚩Пример из программирования Допустим, у нас есть массив чисел, и нужно быстро найти первый элемент, который удовлетворяет определённому условию.
function findOpeningPoint($arr, $condition) {
    foreach ($arr as $item) {
        if ($condition($item)) {
            return $item;
        }
    }
    return null; // Если не найдено
}

$array = [1, 3, 7, 10, 15];
$condition = fn($x) => $x > 5;

echo findOpeningPoint($array, $condition); // Выведет 7
Ставь 👍 и забирай 📚 Базу знаний

🤔 Какие типы БД бывают? Базы данных делятся на реляционные (SQL) и нереляционные (NoSQL). Реляционные базы данных (например, MySQL, PostgreSQL) хранят данные в виде таблиц и используют SQL для запросов. Нереляционные базы данных (например, MongoDB) используют разные модели данных (документы, ключ-значение и т.д.), что делает их более гибкими для работы с большими объёмами данных и неструктурированной информацией. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний

🤔 Зачем придумали анонимные классы? Анонимные классы в PHP были введены в версии 7.0 и позволяют создавать одноразовые объекты без необходимости предварительного объявления класса. Они имеют несколько преимуществ и предназначены для решения ряда задач в программировании. Вот основные причины и случаи, для которых они были придуманы: 🚩Зачем придумали анонимные классы 🟠Упрощение кода Анонимные классы позволяют создать класс на месте, в том же файле, где он используется, без необходимости его предварительного определения. Это упрощает и сокращает код, особенно для одноразовых задач.
$logger = new class {
public function log($message) {
echo $message;
}
};

$logger->log("Hello, World!"); // Выведет: Hello, World!
🟠Инкапсуляция и уменьшение загрязнения пространства имен Поскольку анонимные классы не имеют имен, они не добавляют новых имен в глобальное пространство имен, что помогает избежать конфликтов имен и делает код более чистым. 🟠Использование одноразовых объектов Анонимные классы удобны, когда нужно создать объект для одноразового использования, например, в тестах, или для передачи в функции или методы.
function handleRequest($handler) {
$handler->process();
}

handleRequest(new class {
public function process() {
echo "Processing request";
}
}); // Выведет: Processing request
🟠Более гибкая реализация интерфейсов и абстрактных классов: Анонимные классы могут реализовывать интерфейсы или наследовать от абстрактных классов, предоставляя быстрый способ создать конкретные реализации на месте.
interface Logger {
public function log($message);
}

$logger = new class implements Logger {
public function log($message) {
echo $message;
}
};

$logger->log("Logging message"); // Выведет: Logging message
🟠Улучшение тестирования В юнит-тестах анонимные классы позволяют быстро создавать мок-объекты (mock objects) для тестирования без необходимости создавать отдельные классы для каждой тестовой ситуации.
class Service {
private $logger;

public function __construct($logger) {
$this->logger = $logger;
}

public function execute() {
$this->logger->log("Service executed");
}
}

$mockLogger = new class {
public function log($message) {
echo "Mock: " . $message;
}
};

$service = new Service($mockLogger);
$service->execute(); // Выведет: Mock: Service executed
Ставь 👍 и забирай 📚 Базу знаний

🤔 Что такое блокировки и зачем они? Это механизм синхронизации доступа к данным, предотвращающий одновременное изменение записей. 1. Они используются для обеспечения целостности данных в многопользовательских системах. 2. Различают уровни блокировок: строковые, табличные и на уровне транзакций. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний

🤔 Какие могут быть проблемы от Join'а? Использование JOIN в SQL может привести к нескольким проблемам, особенно при работе с большими таблицами. Рассмотрим основные из них. 🟠Производительность (нагрузка на БД) Чем больше данных соединяется, тем больше ресурсов требуется. Проблема: JOIN создаёт временную таблицу в памяти, что замедляет запрос. Если нет индексов, соединение идёт через полный перебор (Nested Loop Join), что очень медленно. Решение: Добавить индексы на поля, по которым идёт соединение. Использовать EXPLAIN для анализа запроса.
EXPLAIN SELECT * FROM users JOIN orders ON users.id = orders.user_id;
🟠Дублирование строк (Картезианское произведение) Если используется JOIN, но нет условия соединения (ON), запрос создаст все возможные комбинации строк. Проблема:
SELECT * FROM users, orders;
Решение Всегда указывать ON или USING:
SELECT * FROM users JOIN orders ON users.id = orders.user_id;
🟠Потеря данных при `INNER JOIN` INNER JOIN возвращает только совпадающие строки, из-за чего можно потерять данные. Проблема
SELECT users.id, users.name, orders.id AS order_id  
FROM users  
INNER JOIN orders ON users.id = orders.user_id;
Решение: Использовать LEFT JOIN, если нужны все пользователи, даже без заказов:
SELECT users.id, users.name, orders.id AS order_id  
FROM users  
LEFT JOIN orders ON users.id = orders.user_id;
🟠Медленный `JOIN` на `TEXT` или `VARCHAR` JOIN по строковым полям (VARCHAR, TEXT) работает медленнее, чем по числовым (INT). Проблема
SELECT * FROM users JOIN orders ON users.email = orders.email;
🟠Несовместимость типов данных Если соединяются таблицы с разными типами данных (INT vs VARCHAR), может быть скрытое приведение типов, которое замедляет запрос. Проблема
SELECT * FROM users  
JOIN orders ON users.id = orders.user_id;  
Решение - Убедиться, что типы данных совпадают (INT = INT). - Привести к нужному типу:
SELECT * FROM users  
JOIN orders ON users.id = CAST(orders.user_id AS INT);
Ставь 👍 и забирай 📚 Базу знаний

🤔 Какие паттерны знаешь? В программировании и разработке ПО существует множество паттернов проектирования, включая: - Порождающие: Singleton, Factory, Builder, Prototype. - Структурные: Adapter, Decorator, Facade, Proxy, Bridge. - Поведенческие: Observer, Strategy, Command, State, Template Method, Iterator, Mediator. Эти паттерны помогают решать общие проблемы проектирования, повышая уровень абстракции и уменьшая связность компонентов? Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний

🤔 Что такое middleware? Это ПО, которое располагается между веб-сервером и приложением. Оно обрабатывает входящие запросы до того, как они достигнут вашего приложения, или обрабатывает исходящие ответы после того, как приложение их сгенерировало. 🚩Зачем нужен Middleware 🟠Управление запросами Может изменять или проверять запросы перед передачей их в приложение. Например, оно может проверять наличие валидных токенов доступа для аутентификации или осуществлять проверку прав доступа. 🟠Перехват ответов Также может изменять ответы перед тем, как они будут отправлены пользователю, например, добавлять нужные заголовки HTTP или сжимать данные. 🟠Логирование и мониторинг Оно может записывать информацию о запросах и ответах для анализа трафика или обнаружения ошибок. 🟠Обработка ошибок Часто используется для централизованной обработки ошибок, позволяя управлять ошибками элегантно и единообразно.
namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Auth;

class CheckAuthenticated
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if (!Auth::check()) {
            return redirect('/login');
        }

        return $next($request);
    }
}
Ставь 👍 и забирай 📚 Базу знаний

🤔 В чём суть абстрактного класса? Абстрактный класс — это класс, который нельзя инстанцировать напрямую, и он предназначен для того, чтобы служить базой для других классов. Он может содержать абстрактные методы, которые должны быть реализованы в классах-наследниках. Абстрактный класс позволяет определять общую функциональность для всех наследников, предоставляя возможность переопределять или дополнять её. Это помогает улучшить структуру кода и избежать дублирования. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний

🤔 Что делают self и static? В PHP self и static используются внутри классов для обращения к их свойствам и методам, но работают по-разному. Давайте разберёмся в их назначении и отличиях. 🚩self Используется для обращения к собственным методам и свойствам класса. Оно не учитывает наследование и всегда ссылается на тот класс, в котором написано.
class A {
    public static function who() {
        echo "Я класс A\n";
    }

    public static function call() {
        self::who(); // Вызываем метод who() внутри того же класса
    }
}

class B extends A {
    public static function who() {
        echo "Я класс B\n";
    }
}

B::call(); // Выведет: "Я класс A", а не "Я класс B"
🚩static Работает динамически, учитывает класс, из которого вызван метод. Это полезно в наследовании.
class A {
    public static function who() {
        echo "Я класс A\n";
    }

    public static function call() {
        static::who(); // Используем static вместо self
    }
}

class B extends A {
    public static function who() {
        echo "Я класс B\n";
    }
}

B::call(); // Выведет: "Я класс B"
Ставь 👍 и забирай 📚 Базу знаний

🤔 Как настроить autoload через Composer? Composer предоставляет механизм автоматической загрузки классов (autoload), который позволяет не писать вручную require. Основные шаги: 1. Использовать PSR-4 или PSR-0 – правила именования классов. 2. Настроить autoload в composer.json – указать, какие пространства имен использовать. 3. Выполнить composer dump-autoload – обновить автозагрузку после изменения файлов. 4. Использовать require 'vendor/autoload.php' – подключить автозагрузку в проекте. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний

🤔 Что такое acid? Это акроним, описывающий четыре ключевых свойства транзакций в системах управления базами данных (СУБД), обеспечивающие надежное выполнение транзакций даже в условиях ошибок, сбоев и множественного доступа. Эти свойства важны для обеспечения правильности и устойчивости данных. Он состоит из следующих компонентов: 🟠Атомарность (Atomicity) Гарантирует, что все операции в рамках одной транзакции либо выполняются полностью, либо не выполняются вообще. Если какая-либо часть транзакции не может быть завершена, система откатит все уже выполненные операции, возвращая базу данных в состояние, которое существовало до начала транзакции. Это "всё или ничего". 🟠Согласованность (Consistency) Означает, что каждая транзакция переводит базу данных из одного согласованного состояния в другое. Согласованность обеспечивает соблюдение всех правил и ограничений базы данных, таких как ключи, ограничения целостности и триггеры, после завершения транзакции. 🟠Изолированность (Isolation) Определяет способ одновременного выполнения множества транзакций без оказания влияния друг на друга. Это свойство предотвращает проблемы, связанные с одновременным доступом, такие как "грязное чтение", "неповторяющееся чтение" и "фантомное чтение". СУБД обычно предлагают различные уровни изоляции, которые могут быть настроены в зависимости от нужд приложения. 🟠Долговечность (Durability) Гарантирует, что как только транзакция была подтверждена, все изменения, сделанные транзакцией, сохраняются и остаются в базе данных даже в случае сбоя, например, при потере питания. Это означает, что система должна сохранять все записи в надежное, неизменяемое хранилище. Ставь 👍 и забирай 📚 Базу знаний

🤔 Сколькими способами можно создать ветку в Git? Создать ветку в Git можно: 1. Командой git branch <имя> – создаст новую ветку. 2. git checkout -b <имя> – создаст и сразу переключится. 3. git switch -c <имя> – альтернатива checkout. 4. В графических интерфейсах (GitKraken, SourceTree) – создание через UI. 5. В удаленном репозитории (GitHub, GitLab) – через web-интерфейс Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний

🤔 Что такое типизация? Типизация в программировании — это механизм, который определяет, как значения различных типов (например, целые числа, строки, объекты и т.д.) обрабатываются и взаимодействуют в языке программирования. Типизация помогает предотвратить ошибки, связанные с некорректным использованием данных, и улучшает читаемость и поддержку кода. 🚩Виды типизации 🟠Статическая типизация: Типы переменных известны и проверяются на этапе компиляции. Примеры языков: Java, C++, TypeScript. 🟠Динамическая типизация: Типы переменных определяются и проверяются во время выполнения программы. Примеры языков: Python, JavaScript, PHP. 🟠Сильная типизация: Язык строго следит за типами, не позволяя неявные преобразования между ними. Примеры языков: Haskell, Java. 🟠Слабая типизация: Язык допускает неявные преобразования между типами. Примеры языков: PHP, JavaScript. PHP — язык с динамической и слабой типизацией, но с версией 7.0 и выше появилась возможность использовать строгую типизацию.
$number = 10;
$number = "ten"; // PHP позволяет это, так как тип переменной может изменяться
С PHP 7.0 можно использовать строгую типизацию для функций и методов. Это позволяет явно указывать, какого типа аргументы и возвращаемое значение должны быть.
declare(strict_types=1); // Включает строгую типизацию

function add(int $a, int $b): int {
    return $a + $b;
}

echo add(2, 3); // Работает
// echo add(2, "3"); // Ошибка, так как второй аргумент не является целым числом
🚩ПлюсыПредотвращение ошибок: Типизация помогает обнаруживать ошибки на ранних этапах разработки, таких как попытка выполнения некорректных операций с данными. ➕Улучшение читаемости и поддержки кода: Явное указание типов делает код более понятным и предсказуемым, что облегчает его поддержку и развитие. ➕Оптимизация выполнения: Статически типизированные языки позволяют компиляторам оптимизировать выполнение кода, так как типы известны на этапе компиляции. ➕Документирование кода: Типизация служит дополнительной документацией, помогая разработчикам понять, какие данные ожидаются и возвращаются функциями и методами. Ставь 👍 и забирай 📚 Базу знаний

🤔 Для чего нужно пространство имен? Пространства имен используются для группировки функций, классов и переменных, чтобы избежать конфликтов имен в больших проектах. Это позволяет нескольким разработчикам работать над проектом, не беспокоясь о пересечении имен. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний

🤔 Какими способами организовать порции? В PHP можно организовать обработку данных порциями разными способами, в зависимости от того, с чем именно мы работаем: с базой данных, файлами или массивами. Основные методы: SQL-запрос с LIMIT и OFFSET Чтение файла построчно (fgets(), SplFileObject) Итерация по массиву с array_chunk() Использование генераторов (yield) 🟠Постраничная выборка в SQL (`LIMIT` + `OFFSET`) При работе с базой данных мы можем загружать данные порциями с помощью LIMIT и OFFSET
$limit = 10;  // Количество записей на страницу  
$offset = 0;  // Смещение (номер страницы * $limit)  

$sql = "SELECT * FROM users ORDER BY id LIMIT $limit OFFSET $offset";
$result = $pdo->query($sql)->fetchAll();
Альтернативный вариант – постраничная выборка без OFFSET
$last_id = 0;
$sql = "SELECT * FROM users WHERE id > $last_id ORDER BY id LIMIT $limit";
🟠Чтение файла порциями (`fgets()`, `SplFileObject`) При работе с большими файлами можно читать их построчно, а не загружать в память целиком.fgets() – чтение построчно
$handle = fopen("large_file.txt", "r");
while (($line = fgets($handle)) !== false) {
    echo $line;
}
fclose($handle);
SplFileObject – более удобный способ
$file = new SplFileObject("large_file.txt");
while (!$file->eof()) {
    echo $file->fgets();
}
🟠Разделение массива на порции (`array_chunk()`) Если у нас массив данных, можно разбить его на части
$data = range(1, 100);
$chunks = array_chunk($data, 10);

foreach ($chunks as $chunk) {
    print_r($chunk); // Выведет массивы по 10 элементов
}
🟠Генераторы (`yield`) – ленивый способ Генераторы позволяют возвращать элементы по одному, не загружая всё в память сразу.
function getData() {
    for ($i = 1; $i <= 100; $i++) {
        yield $i; // Возвращает по одному значению
    }
}

foreach (getData() as $num) {
    echo $num . "\n";
}
Ставь 👍 и забирай 📚 Базу знаний

🤔 Какие известны распространенные способы кодирования в разработке? 1. Base64: для передачи бинарных данных в текстовом формате. 2. URL Encoding: преобразование специальных символов в безопасный формат для URL. 3. ASCII и Unicode: для кодировки символов. 4. JSON и XML: для структурирования данных. 5. UTF-8: стандарт кодировки текста. Ставь 👍 если знал ответ, 🔥 если нет Забирай 📚 Базу знаний