B
B
BuzzBz2018-05-15 06:39:09
PHP
BuzzBz, 2018-05-15 06:39:09

How to make a factory with parameters?

Good morning.
There is a need to make a class for exporting tabular data from the application: the type and data are given as input, and the finished file is output. In code I see it like this:

<?php 
  class DataExporter {
    public function Create( $type ) {
      $class = $type . 'Exporter';
      return new $class;
    }
  }

  class AbstractExporter {
    public function setData( $data ) { ... }
    public function getResult( ) { ... }
  }

  class CSVExporter extends AbstractExporter { ... }
  class XLSXExporter extends AbstractExporter { ... }

<?php 
  $data = db::query( 'select * from table' );
  $format = $request->get[ 'format' ];

  $exporter = DataExporter::Create( $format );
  $exporter->setData( $data );
  echo $exporter->getResult( );

The problem starts when you want to pass additional parameters to each exporter. For example, for xlsx, this is the style or width of the columns.
<?php 
  class XLSXExporter extends AbstractExporter {
    public function setColumnWidth( $column, $width ) { ... }
    public function setColumnStyle( $column, $style ) { ... }
  }

It is obviously wrong to write something like the code below in each controller.
<?php 
  $exporter = DataExporter::Create( $format );
  $exporter->setData( $data );

  if( $format == 'XLSX' ) {
    $exporter->setColumnWidth( 0, 100 );
    $exporter->setColumnWidth( 1, 30 );
    $exporter->setColumnWidth( 2, 60 );
  }

  echo $exporter->getResult( );

Actually, the question is: how to pass parameters from the controller to each created class in a beautiful way in a factory (or maybe a factory is not needed here?)

Answer the question

In order to leave comments, you need to log in

3 answer(s)
D
dmitriy, 2018-05-15
@BuzzBz

I think not much was not implemented well, so if:

$driver = new XLSXExporter();
$exporter = new DataExporter($driver);

echo $exporter->getResult();

class DataExporter{
protected $driver;
function __construct(DriverExporterInterface $driver){
$this->driver = $driver;
}
function getResult(){
return $this->driver->process();
}
}
interface DriverExporterInterface{
public function process();
}

it turns out:
if( $format == 'XLSX' ) {
    $driver = new XLSXExporter();
    $driver->setColumnWidth( 0, 100 );
    $driver->setColumnWidth( 1, 30 );
    $driver->setColumnWidth( 2, 60 );
  }
else{
$driver = new EmptyExporter();
}

$exporter = new DataExporter($driver);
$exporter->setData( $data );

echo $exporter->getResult();

M
Maxim Fedorov, 2018-05-15
@qonand

To solve this problem, it is worth using not a factory, but a DI container

K
KTF, 2018-05-15
@KTF

IMHO, the Strategy pattern fits perfectly on your task . The answer marked as a solution just shows an example implementation.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question