❓Вопрос от пользователя
Всем привет, я новичок в докере и в laravel, хотел протестировать laravel octane, через sail,
у самого window использовал wsl2 ubuntu, создал проект установил sail, запустил докер контейнеры, позже установил laravel octane, но при запуске сервера каждый раз пишет "Server is already running" - при том что сам не запускал, переход на 127.0.0.0:8000 не даёт результатов, можете подсказать в чем дело?
пробывал и перезапускать docker, и пересоздавать проект, и ставить по многу раз octane.
PHP задачи с собеседований
Ошибка запуска laravel octane через sailВсем привет, я новичок в докере и в laravel, хотел протестировать laravel octane, через sail,
у самого window использовал wsl2 ubuntu, создал проект установил sail, запустил докер контейнеры, позже установил laravel octane, но при запуске сервера каждый раз пишет "Server is already running" - при том что сам не запускал, переход на 127.0.0.0:8000 не даёт результатов, можете подсказать в чем дело?
пробывал и перезапускать docker, и пересоздавать проект, и ставить по многу раз octane.
PHP задачи с собеседований
❓Вопрос от пользователя
Не запускается geckodriver во время выполнения cron на Bitrix
Написал модуль для Bitrix с использованием Selenium и geckodriver в частности. Использую php-библиотеку php-webdriver.
При установке модуля в систему создается агент. Агенты выполняются по крону (при переводе агентов на крон делал все по инструкции с курсов разработчика Битрикса).
После установки модуля обнаружил что мой агент не выполняется. Начал копать и пришел к тому, что при попытке запустить процесс geckodriver выдается исключение
File is not executable. Make sure the path is correct or use environment variable to specify location of the executable. ("geckodriver").
Что делать в этом случае? Сам geckodriver в системе установлен. Права на него установил 777, владельцем поставил пользователя bitrix.
До этого агенты запускались на хитах и этот агент отлично запускал geckodriver.
Также проверял вызов функции, которая вызывается в агенте. Вызывал ее через консоль и через браузер (открывал страницу). В первом и во втором случае все работает хорошо.
В чем может быть причина такого поведения, и как это исправить?
PHP задачи с собеседований
Не запускается geckodriver во время выполнения cron на Bitrix
Написал модуль для Bitrix с использованием Selenium и geckodriver в частности. Использую php-библиотеку php-webdriver.
При установке модуля в систему создается агент. Агенты выполняются по крону (при переводе агентов на крон делал все по инструкции с курсов разработчика Битрикса).
После установки модуля обнаружил что мой агент не выполняется. Начал копать и пришел к тому, что при попытке запустить процесс geckodriver выдается исключение
File is not executable. Make sure the path is correct or use environment variable to specify location of the executable. ("geckodriver").
Что делать в этом случае? Сам geckodriver в системе установлен. Права на него установил 777, владельцем поставил пользователя bitrix.
До этого агенты запускались на хитах и этот агент отлично запускал geckodriver.
Также проверял вызов функции, которая вызывается в агенте. Вызывал ее через консоль и через браузер (открывал страницу). В первом и во втором случае все работает хорошо.
В чем может быть причина такого поведения, и как это исправить?
PHP задачи с собеседований
❓Вопрос от пользователя
Как отфильтровать правильно данные в Laravel?
Хочу отфильтровать данные так:
чтобы фильтровалось сначала по source , а потом уже по search
То есть, как и last_name (Киселев) так и first_name (Олег) так и вместе.
Попытки к этому есть: Но этот запрос не работает так как надо, находит только по first_name, а last_name не учитывается
orWhereLikeFilter и whereFilter - это обычный where с like. Написан Trait.
PHP задачи с собеседований
Как отфильтровать правильно данные в Laravel?
Хочу отфильтровать данные так:
{{base_url}}/models?source=0&search=Олег Киселев
чтобы фильтровалось сначала по source , а потом уже по search
То есть, как и last_name (Киселев) так и first_name (Олег) так и вместе.
Попытки к этому есть: Но этот запрос не работает так как надо, находит только по first_name, а last_name не учитывается
public function index(Request $request): AnonymousResourceCollection
{
return IndexResource::collection(
Model::query()
->whereSource(SourceEnum::LARAVEL)
->whereFilter('source', $request->get('source'))
->orwhereLikeFilter('first_name', $request->get('search'))
->orwhereLikeFilter('last_name', $request->get('search'))
->paginate(25)
);
}
orWhereLikeFilter и whereFilter - это обычный where с like. Написан Trait.
PHP задачи с собеседований
❓Вопрос от пользователя
sqlsrv выдаёт ошибку 102
у меня есть бд в которую нужно вносить данные введённые пользователем из формы. К бд я подключаюсь, а данные не вставляются. Вот код php:
Сама проблема я думаю в запросе, но не понимаю где именно.
PHP задачи с собеседований
sqlsrv выдаёт ошибку 102
у меня есть бд в которую нужно вносить данные введённые пользователем из формы. К бд я подключаюсь, а данные не вставляются. Вот код php:
<?php
require_once('connect.php');
$startDay = $_POST['startDay'];
$endDay = $_POST['endDay'];
$targetType = $_POST['taget-type'];
$divisionType = $_POST['division-type'];
$fio = $_POST['fio'];
$firstName = $_POST['firstName'];;
$secondName = $_POST['secondName'];
$thirdName = $_POST['thirdName'];
$phoneNumber = $_POST['phoneNumber'];
$email = $_POST['email'];
$organization = $_POST['organization'];
$comment = $_POST['comment'];
$birthday = $_POST['birthday'];
$seriaPassport = $_POST['seriaPassport'];
$numberPassport = $_POST['numberPassport'];
$photo = $_POST['uploadImage'];
$uploadDocument = $_POST['uploadDocument'];
//print_r($_POST);
$sqlInsert = "INSERT INTO SoloVisitTable (stardDay, endDay, targetType, divisionType, fio, secondName, firstName, thirdName, phoneNumber, email, organization, comment, birthday, seriaPassport, numberPassport, photo, uploadDocument) VALUES ($startDay, $endDay, $targetType, $divisionType, $fio, $firstName, $secondName, $thirdName, $phoneNumber, $email, $organization, $comment, $birthday, $seriaPassport, $numberPassport, $photo, $uploadDocument)"; //sql запрос
$stmtInsert = sqlsrv_query($conn, $sqlInsert);
if($stmtInsert){
echo 'Инфа вставилась';
}
else{
if( ($errors = sqlsrv_errors() ) != null) {
foreach( $errors as $error ) {
echo "SQLSTATE: ".$error[ 'SQLSTATE']."<br />";
echo "Код: ".$error[ 'code']."<br />";
echo "Сообщение: ".$error[ 'message']."<br />";
}
}
}
?>
Сама проблема я думаю в запросе, но не понимаю где именно.
PHP задачи с собеседований
Товарищи, подскажите
Есть объект такого класса
есть кастомный сериалайзер:
Стандартный сериалайзер при вызове
выдает такое
а кастомный такое
Как заставить кастомный сериалайзер учитывать атрибуты Context для свойств?
symfony5.4
Есть объект такого класса
class Client
{
#[Context([DateTimeNormalizer::FORMAT_KEY => 'Y-m-d'])]
public \DateTimeImmutable $passportIssuedDate;
#[Context([DateTimeNormalizer::FORMAT_KEY => \DateTimeImmutable::ATOM])]
public \DateTimeImmutable $agreementDateTime;
}
есть кастомный сериалайзер:
$encoders = [new JsonEncoder()];
$extractor = new PropertyInfoExtractor([], [new PhpDocExtractor(), new ReflectionExtractor()]);
$normalizers = [
new DateTimeNormalizer(),
new ObjectNormalizer(propertyTypeExtractor: $extractor),
];
$serializer = new Serializer($normalizers, $encoders);
Стандартный сериалайзер при вызове
$this->serializer->serialize($client, 'json');
выдает такое
{"passportIssuedDate":"2024-04-05","agreementDateTime":"2024-04-05T11:59:32+00:00"}
а кастомный такое
{"passportIssuedDate":"2024-04-05T11:59:32+00:00","agreementDateTime":"2024-04-05T11:59:32+00:00"}
Как заставить кастомный сериалайзер учитывать атрибуты Context для свойств?
symfony5.4
❓Вопрос от пользователя
Как перезаписать определенную строку в определенном файле?
Возникла довольно трудная для моего опыта в php задача, с которой мне самостоятельно справиться увы не удается. Поэтому обращаюсь к вам за помощью. Задача следующая:
При регистрации каждого нового пользователя на сайте, в каталоге:
site ru/us/db/us/
создается файл, типа:
123456789
с его данными. Название файла - это id пользователя. Такой файл состоит из 10 строк.
us/db/list - это файл, в котором перечисляются все зарегистрированные пользователи. Каждая строка - это отдельный пользователь. Этот файл формируется так:
email*пароль*idпользователя
В админке (site ru/admin/) я создал файл school.php, в котором делаю вывод всех пользователей, в следующем виде:
Пользователь - Строка №5 (из файла данных пользователя) в input type=text...
Задача состоит в том, чтобы в админке я мог менять значение Строки №5 в файле с данными у каждого Пользователя в отдельности.
Пожалуйста, помогите справиться с поставленной задачей. Благодарю за помощь!
PHP задачи с собеседований
Как перезаписать определенную строку в определенном файле?
Возникла довольно трудная для моего опыта в php задача, с которой мне самостоятельно справиться увы не удается. Поэтому обращаюсь к вам за помощью. Задача следующая:
При регистрации каждого нового пользователя на сайте, в каталоге:
site ru/us/db/us/
создается файл, типа:
123456789
с его данными. Название файла - это id пользователя. Такой файл состоит из 10 строк.
us/db/list - это файл, в котором перечисляются все зарегистрированные пользователи. Каждая строка - это отдельный пользователь. Этот файл формируется так:
email*пароль*idпользователя
В админке (site ru/admin/) я создал файл school.php, в котором делаю вывод всех пользователей, в следующем виде:
Пользователь - Строка №5 (из файла данных пользователя) в input type=text...
Задача состоит в том, чтобы в админке я мог менять значение Строки №5 в файле с данными у каждого Пользователя в отдельности.
chdir("..");
$cat=array();
$d=opendir("us/db/us");
while(($e=readdir($d))!=false)
{
if($e =="." || $e ==".." || $e==".htaccess" || $e=="admin") continue;
$cat[]=$e;
}
closedir($d);
$data_e=array();
$file=file("us/db/list");
foreach($file as $line)
{
$expl=explode("*",$line);
$data_e[$expl[2]]=$expl[0];
}
if(isset($_GET['school']) && in_array($_GET['school'],$cat))
{
$file=file("us/db/us/$_GET[school]");
$f=fopen("us/db/us/$_GET[school]","w");
for($n=0;$n<count($file);$n++)
{
fwrite($f,$file[5]."\r\n");
}
fclose($f);
echo "<meta http-equiv=refresh content=0; url=school.php>";
exit();
}
$text=file("us/db/us/$cat[$x]");
$rec=file("admin/db/us/$cat[$x]");
echo"<p>Пользователь: $text[1]</p>
<form name='$cat[$x]' method='post'>
<input name=school type=text value='$text[5]'>
<button name=school type=submit value=Изменить>Изменить</button>
</form>";
Пожалуйста, помогите справиться с поставленной задачей. Благодарю за помощь!
PHP задачи с собеседований
❗️ Задача: создать файл на сетевом диске
Путь к папке на сетевом диске: //nk-web/folder/ (nk-web - имя сервера; тоже сетевой)
Функция is_dir с этим путём возвращает false (с любым написанием, \\nk-web\folder\, \\nk-web\folder, //nk-web/folder/, //nk-web/folder/). Но если вставить \nk-web\folder\ в проводник компьютера, то открывается нужная сетевая папка.
При создании файла с именем '123.txt':
Почему не получается создать файл в сетевой папке?
Почему файл создаётся в корне локального сервера?
Почему файл создаётся со странным названием, но корректным содержимым?
PHP задачи с собеседований
Путь к папке на сетевом диске: //nk-web/folder/ (nk-web - имя сервера; тоже сетевой)
Функция is_dir с этим путём возвращает false (с любым написанием, \\nk-web\folder\, \\nk-web\folder, //nk-web/folder/, //nk-web/folder/). Но если вставить \nk-web\folder\ в проводник компьютера, то открывается нужная сетевая папка.
При создании файла с именем '123.txt':
$f = fopen('//nk-web/folder/123.txt', 'a');
$text = 'test test';
fwrite($f, $test);
fclose($f);
Формируется файл в корне ЛОКАЛЬНОГО сервера с названием '_VL4NL~P.txt' и содержимым 'test test'.
Почему не получается создать файл в сетевой папке?
Почему файл создаётся в корне локального сервера?
Почему файл создаётся со странным названием, но корректным содержимым?
PHP задачи с собеседований
❓Вопрос от пользователя
Не правильно работают параметры wp_nav_menu()
Суть проблемы состоит в том что параметры функции wp_nav_menu() странно себя ведут, например:
При таких заданных параметрах почему-то контейнер не отключается, но если напишу допустим nav, то тег контейнера меняется, к тому же 'menu_class' => 'menu__list', меняет класс не у тега <ul> а у контейнера...
Вот так у меня регистрируется меню:
Не правильно работают параметры wp_nav_menu()
Суть проблемы состоит в том что параметры функции wp_nav_menu() странно себя ведут, например:
<?php
wp_nav_menu( [
'theme_location' => 'menu-header',
'container' => false,
'menu_class' => 'menu__list',
'menu_id' => false,
'echo' => true,
'items_wrap' => '<ul id="%1$s" class="%2$s">%3$s</ul>',
] );
?>
При таких заданных параметрах почему-то контейнер не отключается, но если напишу допустим nav, то тег контейнера меняется, к тому же 'menu_class' => 'menu__list', меняет класс не у тега <ul> а у контейнера...
Вот так у меня регистрируется меню:
function test_menus(){PHP задачи с собеседований
$locations = array(
'menu-header' => __('Header Menu', 'test'),
'footer' => __('Footer Menu', 'test')
);
register_nav_menus($locations);
}
add_action( 'init','test_menus');
❓Вопрос от пользователя
mysql_fetch_array() expects parameter 1 to be resource (or mysqli_result), boolean given
Я пытаюсь получить данные из таблицы MySQL, но вылезает одна из этих ошибок:
или
Вот мой код:
PHP задачи с собеседований
mysql_fetch_array() expects parameter 1 to be resource (or mysqli_result), boolean given
Я пытаюсь получить данные из таблицы MySQL, но вылезает одна из этих ошибок:
mysql_fetch_array() expects parameter 1 to be resource, boolean given
или
mysqli_fetch_array() expects parameter 1 to be mysqli_result, boolean given
Вот мой код:
$username = $_POST['username'];
$password = $_POST['password'];
$result = mysql_query("SELECT * FROM Users WHERE UserName LIKE $username");
while($row = mysql_fetch_array($result))
{
echo $row['FirstName'];
}
PHP задачи с собеседований
❓Вопрос от пользователя
Ошибка Target class [DatabaseSeeder] does not exist (Laravel 10)
Как и полагается, находится в App\database\seeders
в composer вроде тоже все нормально, composer dump-autoload запускал и все равно одна и та же проблема
PHP задачи с собеседований
Ошибка Target class [DatabaseSeeder] does not exist (Laravel 10)
<?php
namespace Database\Seeders;
namespace App\Models\User;
use Illuminate\Support\Facades\Hash;
// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Database\Eloquent\Model;
class DatabaseSeeder extends Seeder {
/**
* Seed the application's database.
*/
public function run(): void {
User::factory( 100 )->create();
}
}
Как и полагается, находится в App\database\seeders
"autoload": {
"psr-4": {
"App\\": "app/",
"Database\\Factories\\": "database/factories/",
"Database\\Seeders\\": "database/seeders/"
},
"files": [
"app/helpers.php"
]
},
в composer вроде тоже все нормально, composer dump-autoload запускал и все равно одна и та же проблема
PHP задачи с собеседований
❓Вопрос от пользователя
Обращение к ярлыку из php
В папке test лежит ярлык на другую папку, ярлык называется help-me. Если делаю scandir:
echo scandir('путь к test');
то на страницу выводится название ярлыка 'help-me.lnk' .
Как можно из кода сделать scandir этого ярлыка?
scandir('путь к test/help-me');
и
scandir('путь к test/help-me.lnk');
возвращают false
PHP задачи с собеседований
Обращение к ярлыку из php
В папке test лежит ярлык на другую папку, ярлык называется help-me. Если делаю scandir:
echo scandir('путь к test');
то на страницу выводится название ярлыка 'help-me.lnk' .
Как можно из кода сделать scandir этого ярлыка?
scandir('путь к test/help-me');
и
scandir('путь к test/help-me.lnk');
возвращают false
PHP задачи с собеседований
❓Вопрос от пользователя
Как с помощью php обратиться к папке под определенным пользователем?
Есть сетевая папка, для папки создана роль с доступом для чтения и записи. Как через код обратиться к этой папке под определенной ролью? Операционная система - Windows
PHP задачи с собеседований
Как с помощью php обратиться к папке под определенным пользователем?
Есть сетевая папка, для папки создана роль с доступом для чтения и записи. Как через код обратиться к этой папке под определенной ролью? Операционная система - Windows
PHP задачи с собеседований
❓Вопрос от пользователя
Psalm Cannot find referenced variable $articles in global scope в шаблоне подключенном через include
Работаю над добавлением Psalm в проект. В нем есть метод-функция для подключения php файла-шаблона:
public function include(string $template, array $args = array(), bool $echo = true)
{
include $this->templates_path . $template;
}
С ее помощью подключается шаблон arcticles.php:
Статический анализ в PHP Storm правильно связывает с $articles с типом Article, но psalm выдает ошибку Cannot find referenced variable $articles in global scope
Как можно доработать psalm, чтобы он воспринимал переменную с @var как переменную переданную в шаблон?
PHP задачи с собеседований
Psalm Cannot find referenced variable $articles in global scope в шаблоне подключенном через include
Работаю над добавлением Psalm в проект. В нем есть метод-функция для подключения php файла-шаблона:
public function include(string $template, array $args = array(), bool $echo = true)
{
include $this->templates_path . $template;
}
С ее помощью подключается шаблон arcticles.php:
<?php
declare(strict_types=1);
/**
* @var Article[] $articles
*/
foreach ($articles as $article) :
//...
endforeach;
Статический анализ в PHP Storm правильно связывает с $articles с типом Article, но psalm выдает ошибку Cannot find referenced variable $articles in global scope
Как можно доработать psalm, чтобы он воспринимал переменную с @var как переменную переданную в шаблон?
PHP задачи с собеседований
❓Вопрос от пользователя
Структура построения отображения картинок
Имеется код страницы
В нем в процессе загрузки создаются блоки с картинками, мне надо что-бы они были условно построечно, но не создавали пропусков, ни где не смог найти ответов, в том числе у ии, просьба помочь с реализацией задуманного.
Первый блок кода - код блока с картинкой
Второй блок кода - вся страница
1 картинка показывает что по факту имеется
2 картинка показывает что должно получится (сделал в photoshop)
Второй код
Структура построения отображения картинок
Имеется код страницы
В нем в процессе загрузки создаются блоки с картинками, мне надо что-бы они были условно построечно, но не создавали пропусков, ни где не смог найти ответов, в том числе у ии, просьба помочь с реализацией задуманного.
Первый блок кода - код блока с картинкой
Второй блок кода - вся страница
1 картинка показывает что по факту имеется
2 картинка показывает что должно получится (сделал в photoshop)
<?php foreach ($photos as $photo) { ?>
<div class="col draggable" data-id="<?=$photo['id']?>">
<div class="card">
<div class="card-body p-0 position-relative">
<img src="uploads/<?=$photo['file_name']?>" class="card-img-top img-fluid" alt="Фото <?=$photo['id']?>" onclick="openModal(this.src)">
<div class="photo-actions position-absolute w-100 d-flex justify-content-center">
<div class="opacity-75 p-2 rounded">
<a href="uploads/<?=$photo['file_name']?>" download class="btn btn-secondary">Скачать</a>
<button class="btn btn-primary print-request" data-id="<?=$photo['id']?>">Запрос на печать</button>
<button class="btn btn-danger delete-photo" data-id="<?=$photo['id']?>">Удалить</button>
</div>
</div>
</div>
</div>
</div>
<?php } ?>
Второй код
<?php
require("includes/header.php");
require("../src/db.php");
$stmt = $conn->prepare("SELECT * FROM bids WHERE user_id=?");
$stmt->execute([$_SESSION['user_id']]);
$bids = $stmt->fetchAll();
$photosStmt = $conn->prepare("SELECT * FROM photos WHERE user_id=?");
$photosStmt->execute([$_SESSION['user_id']]);
$photos = $photosStmt->fetchAll();
?>
<div class="container-fluid w-75 mb-3 mx-auto">
<h2 class="text-center p-3">Личный кабинет</h2>
<div class="container border mb-5">
<a href="bid_form.php" class="btn btn-success mb-2 mt-3">Новая заявка</a>
<h3>Ваши заявки:</h3>
<button class="btn btn-primary mb-3 mt-2" type="button" data-bs-toggle="collapse" data-bs-target="#bidsTable" aria-expanded="false" aria-controls="bidsTable">
Показать/Скрыть заявки
</button>
<div class="collapse" id="bidsTable">
<div class="row row-cols-1 row-cols-md-2 g-4">
<?php foreach ($bids as $bid) { ?>
<div class="col">
<div class="card">
<div class="card-body">
<h5 class="card-title">Заявка № <?=$bid["id"]?></h5>
<h5 class="card-title"><?=$bid["title"]?></h5>
<p class="card-text"><?=$bid["description"]?></p>
<p class="card-text"><?=$bid["status"]?></p>
</div>
</div>
</div>
<?php } ?>
</div>
</div>
</div>
<div class="container border">
<h3>Ваши фото:</h3>
<form action="api/upload_photo.php" method="post" enctype="multipart/form-data">
<input type="file" name="photo" id="photoInput" class="form-control mb-3" onchange="toggleUploadButton()">
<button type="submit" id="uploadButton" class="btn btn-primary" disabled>Загрузить фото</button>
</form>
<div id="photoGallery" class="row row-cols-1 row-cols-md-2 g-4 mt-3 mb-3">
<?php foreach ($photos as $photo) { ?>
<div class="col draggable" data-id="<?=$photo['id']?>">
<div class="card">
<div class="card-body p-0 position-relative">
<img src="uploads/<?=$photo['file_name']?>" class="card-img-top img-fluid" alt="Фото <?=$photo['id']?>" onclick="openModal(this.src)">
<div class="photo-actions position-absolute w-100 d-flex justify-content-center">
<div class="opacity-75 p-2 rounded">
<a href="uploads/<?=$photo['file_name']?>" download class="btn btn-secondary">Скачать</a>
<button class="btn btn-primary print-request" data-id="<?=$photo['id']?>">Запрос на печать</button>
<button class="btn btn-danger delete-photo" data-id="<?=$photo['id']?>">Удалить</button>
</div>
</div>
</div>
</div>
</div>
<?php } ?>
</div>
</div>
</div>
<!-- Modal for full-size image -->
<div id="imageModal" class="modal" tabindex="-1">
<span class="close" onclick="closeModal()">×</span>
<img class="modal-content" id="modalImage">
</div>
<script>
function toggleUploadButton() {
const photoInput = document.getElementById('photoInput');
const uploadButton = document.getElementById('uploadButton');
uploadButton.disabled = !photoInput.files.length;
}
document.addEventListener('DOMContentLoaded', function() {
const deleteButtons = document.querySelectorAll('.delete-photo');
deleteButtons.forEach(button => {
button.addEventListener('click', function() {
const photoId = this.getAttribute('data-id');
if (confirm('Вы уверены, что хотите удалить это фото?')) {
fetch('api/delete_photo.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
'photo_id': photoId
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
this.closest('.col').remove();
} else {
alert('Ошибка при удалении фото: ' + data.message);
}
})
.catch(error => {
console.error('Ошибка:', error);
alert('Произошла ошибка при удалении фото');
});
}
});
});
});
function openModal(src) {
const modal = document.getElementById("imageModal");
const modalImg = document.getElementById("modalImage");
modal.style.display = "block";
modalImg.src = src;
}
function closeModal() {
const modal = document.getElementById("imageModal");
modal.style.display = "none";
}
</script>
<style>
.card-body {
position: relative;
overflow: hidden;
}
.card-body .photo-actions {
display: flex;
align-items: center;
justify-content: center;
bottom: -100%;
left: 0;
right: 0;
background: linear-gradient(rgba(0, 0, 0, 0), rgba(255, 255, 255, 0.45));
transition: bottom 0.3s ease;
padding: 10px;
}
.card:hover .photo-actions {
bottom: 0;
}