Un modo migliore per manipolare oggetti grandi

4

Sto facendo un sacco di lavoro con SOAP Api in PHP e gli oggetti che vengono restituiti sono piuttosto grandi. Sto quindi aggiornando gli oggetti da modifiche db locali e spingendoli indietro.

Quindi molto spesso ho un grande oggetto restituito da una query db e un oggetto grande recuperato da una chiamata SOAP e devo aggiornare l'uno dall'altro.

Quindi finisco molto con questo:

$api_object->Organisation->Location[0]->AddressLine1 = $db_object->MainAddress->address_line_1;
$api_object->Organisation->Location[0]->AddressLine2 = $db_object->MainAddress->address_line_2;

$api_object->Organisation->Location[1]->AddressLine1 = $db_object->SecondaryAddress->address_line_1;
$api_object->Organisation->Location[1]->AddressLine2 = $db_object->SecondaryAddress->address_line_2;

E così via, e così via con molti più elementi! E come puoi vedere i nomi dei campi spesso non corrispondono a nomi o profondità.

Mi chiedevo solo se qualcuno avesse qualche suggerimento su come farlo meglio.

    
posta mattl 18.03.2015 - 17:12
fonte

3 risposte

1

Insieme al consiglio di Robert Harvey, piuttosto che "impostare" le proprietà di un oggetto API esistente da un'istanza di un oggetto DB direttamente dove è necessario che accada, perché non "creare" un oggetto API nuovo di zecca usando una fabbrica che utilizza il tuo oggetto DB come modello?

class ApiObjectFactory 
{
    public static function createFromDbObject($dbObject, ApiFactoryInterface $factory)
    {
        return $factory->createFromObject($dbObject);
    }
}

La fabbrica secondaria che passi a questa sarà la persona responsabile della creazione di singoli oggetti. Lo scopo di questo factory esterno è quello di incapsulare tutte queste fabbriche secondarie in un singolo punto (quindi in qualsiasi altro punto che deve creare un oggetto API da un oggetto DB chiamerà qui).

interface ApiFactoryInterface
{
    public function createFromObject($dbObject);
}

Questa interfaccia sta semplicemente configurando il contratto a cui le tue altre fabbriche di tipi aderiranno. Questo non è strettamente necessario, ma è utile per le prove future e per impostare le aspettative su esattamente ciò che questi oggetti faranno.

class  OrganizationApiFactory implements ApiFactoryInterface
{
    public function createFromObject($dbObject)
    {
        $organization = new StdClass;
        $organization->Location = [];
        $organization->Location[0] = $this->createAddress($dbObject->MainAddress);
        $organization->Location[1] = $this->createAddress($dbObject->SecondaryAddress);

        return $organization;
    }

    protected function createAddress(StdClass $address)
    {
        $returnAddress = new StdClass;
        $returnAddress->AddressLine1 = $address->address_line_1;
        $returnAddress->AddressLine2 = $address->address_line_2;

        return $returnAddress;
    }
}

Se sei in grado di sfruttare l'iniezione di dipendenza , tu potrebbe scaricare il riempimento degli indirizzi dell'organizzazione in un AddressApiFactory ed essere in grado di disaccoppiare completamente questo processo iniettando le fabbriche correlate nella fabbrica dell'organizzazione.

class  OrganizationApiFactory implements ApiFactoryInterface
{
    public function __construct(AddressApiFactory $addressFactory)
    {
        $this->addressFactory = $addressFactory;
    }

    public function createFromObject($dbObject)
    {
        $organization = new StdClass;
        $organization->Location = [];
        $organization->Location[0] = $this->addressFactory->createFromObject($dbObject->MainAddress);
        $organization->Location[1] = $this->addressFactory->createFromObject($dbObject->SecondaryAddress);

        return $organization;
    }
}

class AddressApiFactory implements ApiFactoryInterface
{
    public function createFromObject($dbObject)
    {
        $returnAddress = new StdClass;
        $returnAddress->AddressLine1 = $address->address_line_1;
        $returnAddress->AddressLine2 = $address->address_line_2;

        return $returnAddress;
    }
}

Questo approccio fa un paio di cose per te:

  1. Separa le preoccupazioni per tutti i diversi "tipi" di modelli API. Se stai scrivendo ripetutamente le stesse cose, questo è un odore di codice. Dovresti sforzarti di creare unità piccole e funzionali che facciano bene una sola cosa e una singola cosa. Una factory di organizzazione in questo contesto sa esattamente come prendere il tuo oggetto di database e convertirlo in qualsiasi formato necessario per inviarlo alla tua API. Ha assolutamente zero conoscenza di qualsiasi altra cosa.

  2. Se fatto correttamente, può aumentare notevolmente la leggibilità e la manutenibilità del tuo codice. Una volta completato, dovresti essere in grado di salvare qualsiasi oggetto nella tua API dato un oggetto esistente dal tuo database con solo poche righe di codice. Meno codice per eseguire il debug = debugging più veloce. Meno codice per eseguire il debug = meno debug, poiché meno codice ha la tendenza a rompere meno spesso.

Un esempio di come è possibile aggiornare un oggetto API utilizzando questo approccio:

// Simulating fetching an object from the api and loading your corresponding 
// object from the database
$myApiObject = getObjectFromApi();
$myDbObject = getObjectFromDb($myApiObject);

// Simulate updating your object locally
$myDbObject->address_line_1 = '111 Testing Dr';

// Now you need an API Object to save...
$factory = new ApiObjectFactory;
$apiObjectToSave = $factory->createFromDbObject($myDbObject, new OrganizationApiFactory);

// Save your updated data to your API
sendApiSaveRequest($apiObjectToSave);

// ... or even better ...
$apiObjectToSave->save();
    
risposta data 23.03.2015 - 17:23
fonte
6

Crea riferimenti alias per gli oggetti Posizione e Indirizzo per abbreviare i compiti.

$loc = $api_object->Organisation->Location;
$main = $db_object->MainAddress;

$loc[0]->AddressLine1 = $main->address_line_1;
$loc[0]->AddressLine2 = $main->address_line_2;
    
risposta data 18.03.2015 - 17:18
fonte
1

Questo sembra un "servizio" di classe o un'implementazione del modello di "unità di lavoro" sarebbe utile. Mi sto appoggiando all'Unità di lavoro qui.

È possibile definire più classi di "unità di lavoro" in una gerarchia per suddividere gli aggiornamenti. Inoltre, puoi definire classi aggiuntive per l'aggiornamento di $db_object con i valori di $api_object . Mentre questo aggiunge complessità, disaccoppia i due livelli dandoti espliciti punti di integrazione, e riflette la natura transazionale di ciò che stai cercando di realizzare. Ti dà una struttura ad albero di oggetti che fanno il lavoro per te in modo organizzato e isolato.

class UpdateApiUnitOfWork {
    private $update_organization;

    public function UpdateApiUnitOfWork() {
        $this->update_organization = new UpdateApiOrganizationUnitOfWork();
    }

    public function execute($api_object, $db_object) {
        $this->update_organization->execute($api_object->Organization, $db_object);
    }
}

class UpdateApiOrganizationUnitOfWork {
    private $update_location;

    public function UpdateApiOrganizationUnitOfWork() {
        $this->update_location = new UpdateApiLocationUnitOfWork();
    }

    public function execute($organization, $db_object) {
        $this->update_location->execute($organization->Location[0], $db_object->MainAddress);

        if (isset($organization->Location[1]))
            $this->update_location->execute($organization->Location[1], $db_object->SecondaryAddress);

        // ...
    }
}

class UpdateApiLocationUnitOfWork {
    public function execute($location, $address) {
        $location->AddressLine1 = $address->address_line_1;
        $location->AddressLine2 = $address->address_line_2;
        // ...
    }
}

L'uso di questo modello di "unità di lavoro" diventa molto semplice:

$api_object = // Get from the Web API
$db_object = // Get from the database

$updater = new UpdateApiUnitOfWork();
$updater->execute($api_object, $db_object);

Se non hai bisogno di aggiornare l'intera catena di oggetti, puoi scegliere quale unità di lavoro vuoi applicare:

$updater = new UpdateApiOrganizationUnitOfWork();
$updater->execute($api->Organzation, $db_object);

Dopodiché, devi solo chiamare l'API Web per aggiornare le informazioni o chiamare nel tuo livello di accesso ai dati per mantenere tali modifiche nel database.

    
risposta data 23.03.2015 - 18:19
fonte

Leggi altre domande sui tag