Using Doctrine 3.1 - In my entity I have this column:
#[ORM\Column(type: 'blob')]
private $dataJpg;
If I make it string
, PHP complains that resource is used and it cannot assign it during hydration. The problem is that I dont want to use resources at all, I want the binary data in its string
form.
It is easy to work with resource when doing getter:
public function getDataJpg(): ?string
{
$jpgData = $this->dataJpg;
/** @var resource|null $jpgData*/
if ($jpgData !== null) {
return stream_get_contents($jpgData);
}
return null;
}
But for setter I do not know how to approach it. I get string
variable which I want to persist, but I cannot assign it to a resource. A workaround would be to fopen('php://memory')
but I dont like that.
I need a way to tell doctrine to hydrate blob data as strings, so that I can get and set strings only and not care about resources.
For those interested, as suggested by @BERKUT in the comment, here is the custom type I made:
<?php
declare(strict_types=1);
namespace App\DBAL\Types;
use Doctrine\DBAL\ParameterType;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\ConversionException;
use Doctrine\DBAL\Types\Type;
class BlobStringType extends Type
{
/**
* {@inheritDoc}
*/
public function getSQLDeclaration(array $column, AbstractPlatform $platform): string
{
return $platform->getBlobTypeDeclarationSQL($column);
}
public function getName(): string
{
return 'blob_string';
}
/**
* {@inheritDoc}
*/
public function getBindingType(): int
{
return ParameterType::LARGE_OBJECT;
}
/**
* {@inheritDoc}
**/
public function convertToPHPValue($value, AbstractPlatform $platform): mixed
{
if ($value === null) {
return null;
}
if (is_string($value)) {
return $value;
}
if (! is_resource($value)) {
throw ConversionException::conversionFailed($value, Types::BLOB);
}
$result = stream_get_contents($value);
if ($result === false) {
throw ConversionException::conversionFailed($value, Types::BLOB);
}
return $result;
}
/**
* {@inheritDoc}
*/
public function convertToDatabaseValue($value, AbstractPlatform $platform): mixed
{
if (is_null($value)) {
return null;
}
if (is_string($value)) {
$value = $this->convertStringToResource($value);
}
return $value;
}
/**
* @return resource
*/
public function convertStringToResource(string $value)
{
$fp = fopen('php://temp', 'rb+');
assert(is_resource($fp));
fwrite($fp, $value);
fseek($fp, 0);
return $fp;
}
}