2
\$\begingroup\$

I want to know if it's more appropriate to use a separate class (such as a factory?) to construct an object. While the code works, I am concerned about bloating of the model and the tight coupling.

To construct the said object I need:

  1. environment variables like api tokens
  2. some of the user's attributes from the model
  3. classes from the library

Here's the relevant snippet within my user model that creates an AdWordsSession object for use in the third-party library:

class User extends Authenticatable {
...
 public function adWordsSession($customer_id = null){
 if(!$this->google_auth_token) {
 return null;
 }
 if( $this->adWordsSesssion &&
 (
 (isset($customer_id) && $this->adWordsSesssion->getClientCustomerId() == $customer_id) ||
 (!isset($customer_id) && $this->adWordsSesssion->getClientCustomerId() == $this->adwords_customer_id)
 )
 ){
 return $this->adWordsSesssion;
 }
 $oAuth2Credential = (new OAuth2TokenBuilder)
 ->withClientId(env('ADWORDS_CLIENT_ID'))
 ->withClientSecret(env('ADWORDS_CLIENT_SECRET'))
 ->withRefreshToken($this->google_auth_token)
 ->build();
 $session = (new AdWordsSessionBuilder())
 ->withDeveloperToken(env('ADWORDS_DEVELOPER_TOKEN'))
 ->withUserAgent(env('ADWORDS_USER_AGENT'))
 ->withClientCustomerId($customer_id ?: $this->adwords_customer_id)
 ->withOAuth2Credential($oAuth2Credential)
 ->build();
 $this->adWordsSesssion = $session;
 return $session;
 }
...
}

I am also interested to know if it applies to the reverse, using a class returned from the library (web service) to construct a model object. Should this be a static method of the model or a separate factory class. Code follows:

class AdWordsCampaign {
 public static function fromAdWordsClass(Campaign $campaign, AdWordsCampaign $adWordsCampaign = null): AdWordsCampaign {
 $self = $adWordsCampaign;
 if(is_null($adWordsCampaign)) {
 $self = new self;
 $self->criterions = $self->defaultCriterions();
 $self->extensions = $self->defaultExtensions();
 }
 if($campaign->getId()) {
 $self->fieldsHelper()->id = $campaign->getId();
 $self->setPublished();
 }
 $self->fieldsHelper()->name = $campaign->getName();
 $self->fieldsHelper()->status = $campaign->getStatus();
 $self->fieldsHelper()->advertisingChannelType = $campaign->getAdvertisingChannelType();
 $self->fieldsHelper()->advertisingChannelSubType = $campaign->getAdvertisingChannelSubType();
 $self->fieldsHelper()->budget = arrayify_object(
 $campaign->getBudget() ?
 $campaign->getBudget() :
 CampaignFields::defaultBudget()
 );
 return $self;
 }
}
asked Jan 8, 2017 at 19:19
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

I would implement this as a service in Laravel, and use IOC to resolve my dependencies.

I would make a service, called AdWordsCampaign. This would resolve its dependencies in constructor, namely OAuth2TokenBuilder and AdWordsSessionBuilder, although these two classes are good candidates for services themselves (a factory pattern is most of times is a sign you should abstract creation of class into a service provider).

Then I would implement a method in this service, adWordsSession which takes two parameters: a User instance and $customer_id. Then it has everything it needs to to its job.

I would also implement the reverse case using a service. Semantics are the same.

As for static method, I would avoid them. If you like them, use a Facade. They enable you to use a service anywhere you want.

I strongly suggest to read Laravel docs about services and providers and IOC and Facades. It will give you enough insight about how they work, and where to use them.

As a rule of thumb, whenever you see yourself using new * in your codes, it seems your could use a service/provider and inject it.

answered Jan 9, 2017 at 6:54
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.