Symfony2/Doctrine: Building objects from multiple

2019-08-23 06:04发布

问题:

I'm working on an eCommerce Symfony2 application, and I'm trying to work out how to organize my Model to best suit what we're doing.

My issue is that this application must interface with the inventory system of the physical store location to retrieve stock and pricing information, but store web-related data within Doctrine.

So I have a product object:

class Product
{
    protected $id;
    protected $title;
    protected $description;
    protected $variants;
}

And a ProductVariant object (for things like hardcover/softcover books, different sized stickers, etc. Products will have a "default" variant if they don't have any options):

class ProductVariant
{
    protected $id;
    protected $name; // "Hard Cover", IS persisted
    protected $otherData; // Placeholder for other persisted data for a variant.

    protected $price; // Not persisted in Doctrine
    protected $quantity; // Not persisted in Doctrine

    protected $backendID // The ID/SKU of this exact item in our backend database to look up prices
}

Most of this data will be stored in a Doctrine Entity (basic Symfony stuff), but I'm wondering how to pull in the other data as I retrieve these objects.

My ideal goal is to be able to call any of the standard Doctrine EM functions (find, findAll, findBy) and get back full entities with the prices and quantities available.

So right now I'm thinking that I need to create a ProductFactory which does something like this (note that I'm eagerloading prices because we'll need them basically every time we want to look at a product):

$backendService = (A backend service from the Symfony DI container)
$em = (doctrine Product repo EM);

$product = $em->find($id);
foreach($product->getVariants() as $variant)
{
    $backendData = $backendService->getData($variant->getBackendID());
    // Possible caching of $backendData here? (currently it only updates once a day due to legacy constraints)

    $variant->setPrice($backendData->getPrice());
    $variant->setQuantity($backendData->getQuantity());
}

This backend data source will be changing over the next year, and it is unknown how we will retrieve data from the new system, so building this as a service seems to make sense since I can just later change it so that it creates a consistent BakendData object from whatever new data we have.1

But now I have two big questions:

  1. Where do I place this logic? Like I said, since most of the data is coming from Doctrine, I'd like to be able to keep using all the Doctrine EM functions to build these entities, but this additional step of adding in the extra data needs to happen somewhere. Is this something that belongs in the Product Entity Repository, or in a separate Model class that doctrine somehow calls before it returns its objects?

and

  1. How would this affect large requests? When someone's looking at a page with 100 products, without this external data, doctrine can just select 100 items from PDO and they come back as basically pre-built objects that are ready to go. With this processing step, it looks like I'm going to need 100+ additional queries and processing steps to pull in data for each variant. (Some of this data can be cached, and I can write the backendService to be able to request many ID's at once, but these ID's still need to be discovered from doctrine)

Of course, I will be trying to cache as much information as I can from the backend service, but the processing steps are still there.

Thanks for any advice that you guys can give me.

Footnotes

  1. Our current backend data is imported into a MySQL database by a nightly script, and I have mapped it to Doctrine Entities in a separate bundle that I can retrieve as needed. In the future, I might be looking at a REST API, ODBC connections, flat CSV dumps of the data, etc. (Management is currently in the process of choosing a system for the physical store to run on, which will define what sort of data I can get out of it.)