There is a very subtle difference in the One Responsibility Principle that causes this kind of questioning.
Having Sole Responsibility is not restrict the object to do a single thing and yes prevent it from doing things hereafter of the closest context intended to begin coding.
In your case, you have the context of Contacts. A Controller Contacts should control everything about Contacts and only.
But controlling everything about Contacts includes everything you mentioned, from CRUD to search and import/export.
However, it will not be the Controller who will import/export the data, for example. It will only enter the user’s choice made in the GUI (View) and the final product through the Request made.
In that case, the Importer is a separate class yes, but is not a Controller, at least not in the conventional definition, as an Importer should be able to import not only contacts, but any kind of information.
I’m not sure if with methods you have actually referred to class methods or import forms, but assuming it has been as to import forms, this is not even the responsibility of the Importer itself.
The Importer in turn offer an interface (not visual, of course) to the Controller work, but the actual import routines, or better the strategies input analysis classes (CSV, TXT, XML...) are other more classes, all under a regulatory interface.
In code, we’d have something like this:
class ContactsController {
// GUIs
public function index() {}
public function create() {}
public function edit() {}
public function delete() {}
public function search() {}
public function import() {}
public function export() {}
// Actions
public function indexAction() {}
public function createAction() {}
public function editAction() {}
public function deleteAction() {}
public function searchAction() {}
public function importAction() {
$file = ( isset( $_POST['file'] ) ? $_POST['file'] : NULL );
$method = ( isset( $_POST['method'] ) ? $_POST['method'] : 'CSV' );
try {
$importer = new Importer( $file, $method );
$data = $importer -> import();
// Do something with $data
} catch( ImporterException $e ) {
die( $e -> getMessage() );
}
}
public function exportAction() {}
}
class Importer {
private $strategy;
public function __construct( $strategy, $file ) {
$strategyClass = sprintf( '%sStrategy.php', $strategy );
if( ! class_exists( $strategyClass ) {
throw new ImporterException(
sprintf( 'Importer Strategy %s does not exist', $strategy )
);
}
$this -> strategy = new $strategyClass( $file );
}
public function import() {
return $this -> strategy -> import();
}
}
class CSVStrategy implements ImporterInterface {
private $file;
public function __construct( $file ) {
$this -> file =& $file;
}
public function import() {
// Do something with $this -> file and return
}
}
interface ImporterInterface{
public function import();
}
The code fragment above is for educational purposes only and therefore has not been properly tested or even optimized, and may even present syntax errors
Relevant: http://qualityisspeed.blogspot.com.br/2014/08/why-i-dont-teach-solid.html
– Maniero