Last active
January 18, 2020 09:04
-
-
Save webdevilopers/160409917c942e0ba83ba948250aec18 to your computer and use it in GitHub Desktop.
Uploading Files with Metadata using MongoDB GridFS in a PHP Domain-Driven Design application
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class DefaultGridFSRepository extends DocumentRepository implements GridFSRepository | |
{ | |
public function uploadFromStream(string $filename, $source, ?UploadOptions $uploadOptions = null) | |
{ | |
$options = $this->prepareOptions($uploadOptions); | |
$databaseIdentifier = $this->getDocumentBucket()->uploadFromStream($filename, $source, $options); | |
$documentIdentifier = $this->class->getPHPIdentifierValue($databaseIdentifier); | |
return $this->dm->getReference($this->getClassName(), $documentIdentifier); | |
} | |
public function uploadFromFile(string $source, ?string $filename = null, ?UploadOptions $uploadOptions = null) | |
{ | |
$resource = fopen($source, 'r'); | |
if ($resource === false) { | |
throw MongoDBException::cannotReadGridFSSourceFile($source); | |
} | |
if ($filename === null) { | |
$filename = pathinfo($source, PATHINFO_BASENAME); | |
} | |
try { | |
return $this->uploadFromStream($filename, $resource, $uploadOptions); | |
} finally { | |
fclose($resource); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<doctrine-mongo-mapping xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
xmlns="http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping" | |
xsi:schemaLocation="http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping | |
http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping.xsd"> | |
<gridfs-file name="InvoiceDocument" | |
repository-class="MongoInvoiceDocumentRepository" | |
bucket-name="invoice_documents"> | |
<id field-name="surrogateId" /> | |
<length /> | |
<chunk-size /> | |
<upload-date /> | |
<filename field-name="filename" /> | |
<metadata target-document="InvoiceDocumentMetadata" field-name="metadata" /> | |
</gridfs-file> | |
</doctrine-mongo-mapping> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class InvoiceDocument extends SurrogateIdEntity | |
{ | |
/** @var string */ | |
protected $filename; | |
/** @var \DateTimeInterface */ | |
protected $uploadDate; | |
/** @var int */ | |
protected $length; | |
/** @var int */ | |
protected $chunkSize; | |
/** @var InvoiceDocumentMetadata */ | |
protected $metadata; | |
public function __construct() | |
{ | |
$this->id = Uuid::uuid4()->toString(); | |
} | |
public function id(): string | |
{ | |
return $this->metadata->id(); | |
} | |
public function filename(): string | |
{ | |
return $this->filename; | |
} | |
public function contentType(): string | |
{ | |
return $this->metadata->contentType(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
final class InvoiceDocumentFactory | |
{ | |
/** @var InvoiceDocumentRepository */ | |
private $repository; | |
public function __construct(InvoiceDocumentRepository $repository) | |
{ | |
$this->repository = $repository; | |
} | |
public function build( | |
int $invoiceId, Uuid $documentId, $source, $filename, $contentType | |
): InvoiceDocument | |
{ | |
$metadata = new InvoiceDocumentMetadata($documentId, $contentType, $invoiceId); | |
return $this->repository->save($source, $filename, $metadata); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<doctrine-mongo-mapping xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
xmlns="http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping" | |
xsi:schemaLocation="http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping | |
http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping.xsd"> | |
<embedded-document name="InvoiceDocumentMetadata"> | |
<field field-name="id" type="string" /> | |
<field field-name="contentType" type="string" /> | |
<field field-name="invoiceId" type="int" /> | |
</embedded-document> | |
</doctrine-mongo-mapping> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
final class InvoiceDocumentMetadata | |
{ | |
/** @var string */ | |
private $id; | |
/** @var string */ | |
private $contentType; | |
/** @var int */ | |
protected $invoiceId; | |
public function __construct(string $id, string $contentType, int $invoiceId) | |
{ | |
$this->id = $id; | |
$this->contentType = $contentType; | |
$this->invoiceId = $invoiceId; | |
} | |
public function id(): string | |
{ | |
return $this->id; | |
} | |
public function contentType(): string | |
{ | |
return $this->contentType; | |
} | |
public function invoiceId(): int | |
{ | |
return $this->invoiceId; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
interface InvoiceDocumentRepository | |
{ | |
public function save(string $source, string $filename, InvoiceDocumentMetadata $metadata): InvoiceDocument; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
final class MongoInvoiceDocumentRepository extends DefaultGridFSRepository implements InvoiceDocumentRepository | |
{ | |
public function save(string $source, string $filename, InvoiceDocumentMetadata $metadata): InvoiceDocument | |
{ | |
$uploadOptions = new UploadOptions(); | |
$uploadOptions->metadata = $metadata; | |
return $this->uploadFromFile($source, $filename, $uploadOptions); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class SurrogateIdEntity extends Entity implements SurrogateIdInterface | |
{ | |
/** | |
* @var string | |
* Surrogate id used internally by ORM or ODM only. | |
*/ | |
protected $surrogateId; | |
public function surrogateId(): string | |
{ | |
return $this->surrogateId; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
final class UploadInvoiceDocumentHandler | |
{ | |
/** @var InvoiceDocumentFactory */ | |
protected $invoiceDocumentFactory; | |
public function __construct(InvoiceDocumentFactory invoiceDocumentFactory) | |
{ | |
$this->invoiceDocumentFactory = $invoiceDocumentFactory; | |
} | |
public function __invoke(UploadInvoiceDocument $command): void | |
{ | |
/** @var UploadedFile $file */ | |
$file = $command->file(); | |
/** @var InvoiceDocument $document */ | |
$document = $this->invoiceDocumentFactory->build( | |
$command->invoiceId(), | |
Uuid::uuid4(), | |
$file->getPathname(), | |
$file->getClientOriginalName(), | |
$file->getClientMimeType() | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Feel free to join the discussion: