# df -T
Filesystem Type 1K-blocks Used Available Use% Mounted on
overlay overlay 61255652 2408348 55705972 5% /
tmpfs tmpfs 65536 0 65536 0% /dev
tmpfs tmpfs 1018508 0 1018508 0% /sys/fs/cgroup
grpcfuse fuse.grpcfuse 124372988 113400172 10972816 92% /www
/dev/sda1 ext4 61255652 2408348 55705972 5% /etc/hosts
shm tmpfs 65536 0 65536 0% /dev/shm
tmpfs tmpfs 1018508 0 1018508 0% /proc/acpi
tmpfs tmpfs 1018508 0 1018508 0% /sys/firmware
#
lslocks
, он не чего не показал.# Php application
app:
container_name: rapp.app
restart: on-failure
build:
context: .
dockerfile: ./docker/php/Dockerfile-dev
volumes:
- ./:/www/
- ./docker/php/log:/var/log
- ./docker/php/usr/local/etc/php/conf.d:/usr/local/etc/php/conf.d
- ./images:/www/images:rw
depends_on:
- db
links:
- db
expose:
- 9000
environment:
PHP_INI_SCAN_DIR: ":/usr/local/etc/php/conf.d"
TZ: "Europe/Moscow"
# ls -l
total 0
-rwxr-xr-x 1 root root 27384 Feb 10 03:10 9d38dd5b8c9e8707913fefe56c889304-5e409f7ccba8c.png
-rwxr-xr-x 1 root root 222764 Feb 10 04:25 ce0f1f370e9884e65e8cc911cb8b93a9-5e40b11173598.jpeg
-rwxr-xr-x 1 root root 222764 Jan 1 1970 ce0f1f370e9884e65e8cc911cb8b93a9-5e40c760c0e92.jpeg
#
#
# unlink ce0f1f370e9884e65e8cc911cb8b93a9-5e40c760c0e92.jpeg
unlink: cannot unlink 'ce0f1f370e9884e65e8cc911cb8b93a9-5e40c760c0e92.jpeg': Device or resource busy
# Nginx api admin server
nginx-images:
container_name: rapp.nginx-images
restart: on-failure
image: nginx:latest
volumes:
- ./docker/nginx/dev/nginx.conf:/etc/nginx/nginx.conf
- ./docker/nginx/dev/logs/nginx-images:/var/log/nginx
- ./docker/nginx/dev/sites-enabled/vhost-images.conf:/etc/nginx/sites-enabled/vhost-images.conf
- ./images:/www/images:ro
ports:
- 127.0.0.100:8013:80
depends_on:
- app
expose:
- 80
command: ["nginx", "-g", "daemon off;"]
# ls -l
total 0
-rwxr-xr-x 1 root root 27384 Feb 10 00:10 9d38dd5b8c9e8707913fefe56c889304-5e409f7ccba8c.png
-rwxr-xr-x 1 root root 222764 Feb 10 01:25 ce0f1f370e9884e65e8cc911cb8b93a9-5e40b11173598.jpeg
-rwxr-xr-x 1 root root 222764 Jan 1 1970 ce0f1f370e9884e65e8cc911cb8b93a9-5e40c760c0e92.jpeg
#
#
# unlink ce0f1f370e9884e65e8cc911cb8b93a9-5e40c760c0e92.jpeg
unlink: cannot unlink 'ce0f1f370e9884e65e8cc911cb8b93a9-5e40c760c0e92.jpeg': Read-only file system
"На последнем изображении" у вас красная линия. Мы как по ней должны догадаться в чём конкретно проблема?
<?php
namespace App\Service;
use App\Classes\Translatable\TranslationEntityInterface;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\PersistentCollection;
/**
* Class EntityTranslation
* @package App\Service
*/
class EntityTranslation
{
/**
* @param $entity
* @param string $lang
* @param array $properties
* @return ArrayCollection
*/
public function translate($entity, string $lang, $properties = [])
{
if (is_array($entity) or is_a($entity, PersistentCollection::class)) {
return $this->translateCollection($entity, $lang, $properties);
} elseif (is_a($entity, TranslationEntityInterface::class)) {
$this->translateOneObject($entity, $lang, $properties);
}
}
/**
* @param $items
* @param string $lang
* @param array $properties
* @return ArrayCollection
*/
public function translateCollection($items, string $lang, $properties = [])
{
foreach ($items as $item) {
foreach ($item->getTranslations($lang) as $translation) {
$item->setProperty($translation->getField(), $translation->getContent());
}
foreach ($properties as $property_name) {
if ($item->hasOwnProperty($property_name)) {
$this->translate($item->getProperty($property_name), $lang, []);
}
}
}
return $items;
}
/**
* @param TranslationEntityInterface $entity
* @param string $lang
* @param array $properties
* @return TranslationEntityInterface
*/
public function translateOneObject(TranslationEntityInterface $entity, string $lang, $properties = [])
{
foreach ($entity->getTranslations($lang) as $translation) {
$entity->setProperty($translation->getField(), $translation->getContent());
}
foreach ($properties as $property_name) {
if ($entity->hasOwnProperty($property_name)) {
$this->translate($entity->getProperty($property_name), $lang, []);
}
}
return $entity;
}
}
/**
* @Route(
* path="/products.getCategories",
* methods={"GET"}
* )
* @param Request $request
* @param EntityManagerInterface $manager
* @param NormalizerInterface $normalizer
* @param EntityTranslation $et
* @param Lang $lang
* @return JsonResponse
* @throws ExceptionInterface
*/
public function getCategories(
Request $request,
EntityManagerInterface $manager,
NormalizerInterface $normalizer,
EntityTranslation $et,
Lang $lang
)
{
/** @var CategoryProductRepository $categories_repository */
$categories_repository = $manager->getRepository("App:CategoryProduct");
$rs = new ResponseSchemaItems();
$rs->setCount($categories_repository->count(["restaurant" => $request->get("restaurant_id")]));
$categories = $categories_repository->getAll(
$request->get("restaurant_id", 0),
$request->get("q", ""),
$request->get("offset", 0),
$request->get("count", 100)
);
$et->translate($categories, $lang->get());
$rs->setItems($categories);
$response_object = $normalizer->normalize($rs, "json", [
"attributes" => [
"code",
"count",
"items" => [
"id",
"name",
"description"
]
]
]);
return $this->json($response_object);
}
$et->translate($categories, $lang->get(), []);
<?php
namespace App\Classes\Translatable;
use Doctrine\ORM\Mapping as ORM;
/**
* Class AbstractTranslation
* @package App\Entity
*/
abstract class AbstractTranslation
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
protected $id;
/**
* @ORM\Column(type="string", length=10)
*/
protected $lang;
/**
* @var string $field
* @ORM\Column(length=255)
*/
protected $field;
/**
* @var string $content
*
* @ORM\Column(type="text", nullable=true)
*/
protected $content;
/**
* Get id
*
* @return integer $id
*/
public function getId()
{
return $this->id;
}
/**
* @param string $locale
* @return static
*/
public function setLang(string $locale)
{
$this->lang = $locale;
return $this;
}
/**
* @return string|null
*/
public function getLang(): ?string
{
return $this->lang;
}
/**
* Set field
*
* @param string $field
*
* @return static
*/
public function setField(string $field)
{
$this->field = $field;
return $this;
}
/**
* Get field
*
* @return string
*/
public function getField()
{
return $this->field;
}
/**
* @param string $content
* @return static
*/
public function setContent($content)
{
$this->content = $content;
return $this;
}
/**
* Get content
*
* @return string
*/
public function getContent()
{
return $this->content;
}
}
<?php
namespace App\Classes\Translatable;
abstract class AbstractTranslationEntity
{
use PropertyManager;
}
<?php
namespace App\Classes\Translatable;
/**
* Trait PropertyManager
* @package App\Classes\Translatable
*/
trait PropertyManager
{
/**
* @param string $name
* @param $value
*/
public function setProperty(string $name, $value)
{
$this->{$name} = $value;
}
/**
* @param string $name
* @return
*/
public function getProperty(string $name)
{
return $this->{$name};
}
/**
* @param string $name
* @return bool
*/
public function hasOwnProperty(string $name)
{
return isset($this->{$name});
}
}
<?php
namespace App\Classes\Translatable;
/**
* Interface TranslationEntity
* @package App\Classes\Entity
*/
interface TranslationEntityInterface
{
/**
* @param $entity
* @return mixed
*/
public function addTranslation($entity);
/**
* @param string $lang
* @return mixed
*/
public function getTranslations(string $lang);
}
<?php
namespace App\Classes\Translatable;
/**
* Interface TranslationInterface
* @package App\Classes\Translatable
*/
interface TranslationInterface
{
/**
* @ORM\ManyToOne(targetEntity="Product", inversedBy="translations")
* @ORM\JoinColumn(name="owner_id", referencedColumnName="id", onDelete="CASCADE")
*/
/**
* ProductTranslation constructor.
* @param string $lang
* @param string $field
* @param $value
*/
public function __construct(string $lang, string $field, $value);
/**
* @param $owner
*/
public function setOwner($owner): void;
/**
* @return mixed
*/
public function getOwner();
}
<?php
namespace App\Entity;
use App\Classes\Translatable\AbstractTranslationEntity;
use App\Classes\Translatable\TranslationEntityInterface;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ORM\Entity(repositoryClass="App\Repository\CategoryProductRepository")
* @ORM\Table(name="categories_products")
*/
class CategoryProduct extends AbstractTranslationEntity implements TranslationEntityInterface
{
/**
* @ORM\Column(type="integer")
* @ORM\Id
* @ORM\GeneratedValue
*/
private $id;
protected $name;
protected $description;
/**
* @var Image|null
* @ORM\ManyToOne(targetEntity="App\Entity\Image", fetch="EXTRA_LAZY")
* @ORM\Column(nullable=true)
*/
private $image;
/**
* @var Restaurant
* @Assert\NotNull
* @ORM\ManyToOne(targetEntity="Restaurant", fetch="EXTRA_LAZY")
*/
private $restaurant;
/**
* @var ArrayCollection
* @ORM\OneToMany(
* targetEntity="CategoryProductTranslation",
* mappedBy="owner",
* cascade={"persist", "remove"},
* fetch="EXTRA_LAZY"
* )
*/
private $translations;
/**
* CategoryProduct constructor.
*/
public function __construct()
{
$this->translations = new ArrayCollection();
}
/**
* @return mixed
*/
public function getId()
{
return $this->id;
}
/**
* @return string|null
*/
public function getName(): ?string
{
return $this->name;
}
/**
* @return Image|null
*/
public function getImage(): ?Image
{
return $this->image;
}
/**
* @param Image|null $image
*/
public function setImage(?Image $image): void
{
$this->image = $image;
}
/**
* @return Restaurant|null
*/
public function getRestaurant(): ?Restaurant
{
return $this->restaurant;
}
/**
* @param Restaurant $restaurant
*/
public function setRestaurant(?Restaurant $restaurant): void
{
$this->restaurant = $restaurant;
}
/**
* @param $entity
* @return CategoryProduct
*/
public function addTranslation($entity)
{
if (!$this->translations->contains($entity)) {
$this->translations[] = $entity;
$entity->setOwner($this);
}
return $this;
}
/**
* @param string $lang
* @return ArrayCollection
*/
public function getTranslations(string $lang)
{
$translations = new ArrayCollection();
/** @var ProductTranslation $item */
foreach ($this->translations->toArray() as $item) {
if ($item->getLang() == $lang) {
$translations->add($item);
}
}
return $translations;
}
/**
* @return mixed
*/
public function getDescription(): ?string
{
return $this->description;
}
}
<?php
namespace App\Entity;
use App\Classes\Translatable\AbstractTranslation;
use App\Classes\Translatable\TranslationInterface;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="categories_products_translations")
*/
class CategoryProductTranslation extends AbstractTranslation implements TranslationInterface
{
/**
* ProductTranslation constructor.
* @param string $lang
* @param string $field
* @param $value
*/
public function __construct(string $lang, string $field, $value)
{
$this->setLang($lang);
$this->setField($field);
$this->setContent($value);
}
/**
* @ORM\ManyToOne(targetEntity="CategoryProduct", inversedBy="translations")
* @ORM\JoinColumn(name="owner_id", referencedColumnName="id", onDelete="CASCADE")
*/
protected $owner;
/**
* @param $owner
*/
public function setOwner($owner): void
{
$this->owner = $owner;
}
/**
* @return mixed
*/
public function getOwner()
{
return $this->owner;
}
}
В точку
open_file_cache max=100;
Параметр был включен в контексте http.
Выключил
open_file_cache off;
Теперь изображения не блокируются.