Помогите с проектировкой модуля

Здраствуйте уважаемое сообщество. Прошу вашей помощи с проектировкой модуля.

Данный модуль будет подключатся к сервису онлайн фильмов и выбирать отуда данные.

Сам модуль планирую разбить на 2 части (возможно их будет больше)

Первая часть будет осуществлять подключение к сервису.


class CMovieConnect {

    function connect($conn_str, $user, $pass){}

    function status(){}

}

Вторая будет отсылать/принимать информацию.


class CMovieCommand {

   function  searchMovie($str){}

   function  lastMovie(){}

}



Подскажите как мне правильно созать модуль?

что б потом я мог объявить этот модуль в конфиге как




'movie'=>array(

   'class'     => 'CMovie',

   'user'      => 'user',

   'pass'      => 'password',

)

а далее использовать по принципу Yii


$Movie = Yii::app()->movie;

$Movie->searchMovie('my movie');

Буду благодарен за помощь

Судя по вашему коду, вам нужен не модуль, а компонент приложения:




class EMovieComponent extends CApplicationComponent

{

    public $foo;


    public function init()

    {

        // инициализация компонента

    }


    public function searchMovie($value)

    {

        // ...

    }

}



Затем в конфиге в "components" подключаете компонент:




'components'=>array(

    'movie'=>array(

        'class'=>'path.to.EMovieComponent',

        'foo'=>'bar',

    ),

),



Готово, можно пользоваться.

P.S. Не используйте префикс "C" для своих классов.

to andy_s

Спасибо за стандартное написание, но я нехочу "Ложить все яйца в одну корзину", а именно класов для работы дожно быть несколько (в данном случае 2). первый будет работать с подключением, поскольку там есть несколько своих ньансов, второй работать с данными. Можно конечно все в один клас - но это будет неудобно.

Я так понимаю это что нужен "скелет" компонента приложения который будет расширятся другими класам. А вот как должен выглядеть этот "скелет" ?

Не очень понятно, какого результата вы хотите достичь. В первом посте я вижу два обычных класса, на модуль в понимании Yii совсем не тянет. Остается их использовать либо "как есть", либо создавать Application Component?

Конечная цель в удобстве работы с будущим компонентом.

  1. Я вношу в конфиг



'components'=>array(

    'movie'=>array(

        'class' => 'path.to.EMovieComponent',

        'user'  => 'user',

        'pass'  => 'password',


    ),

),



  1. Код в контролеере вызываю



$movie = Yii::app()->movie;

if ($movie->status == 'ok'){

    $movie->searchMovie('some movie');

}



  1. У меня есть папка с компонентом, где лежат 3 файла

EMovieComponent.php (<-- вопросный файл)

EMovieConnect.php

EMovieCommand.php

Как написать последних 2 я знаю, а вот что писать в EMovieComponent.php ?

Подключение, инициализация других классов, в общем всё, что потребуется для работы расширения (более верное название, чем "модуль"). Вся работа будет осуществляться через этот компонент.

Т.е., если хотим подключиться к сервису, то пишем:




Yii::app()->movie->connection->connect();

// теперь ищем movie

Yii::app()->movie->command->search('my movie');



movie->connection и movie->command - возвращают объекты соответствующих классов.

Вот тут и воникают проблемы

Я не хочу использовать дополнительные методы типа command и connection




Yii::app()->movie->connection->connect();

Yii::app()->movie->command->search('my movie');



Должно быть




Yii::app()->movie->connect();

Yii::app()->movie->search('my movie');



Получается, вы хотите работать с одним классом, но вызывать методы двух других. Тут вариантов не много:

  1. Поместить все методы в один класс.

  2. Delegation Pattern.

  3. Сделать из классов Connect и Command поведения (Behavior). Выглядит проще, чем второй вариант, но совсем не гарантирует, что в момент времени t у класса будет метод search(), т.к. поведение можно в любой момент отключить.

andy_s Спасибо за помощь, Из всех вариантов наиболее удачно подходит 2. Delegation Pattern

а именно interface

думаю это будет приблизительно будет так:

EMovieInterface.php


interface EMovieComponent{

 public function connect($str, $user, $pass);

}

EMovieConnect.php




abstract class EMovieConnect implements EMovieComponent{

    function connect($conn_str, $user, $pass){ ... }

    function status(){...}

}



Но как interface подключить в Yii?

Что такое интерфейсы, и зачем они нужны - вам лучше почитать отдельно и подробно. Я же говорю о том, что EMovieComponent должен содержать методы connect, search, lastMovie и т.д., но не реализовывать их, а вызывать методы соответствующих классов EMovieConnect и EMovieCommand. Хотя на самом деле интерфейсы здесь могут пригодится, если планируются различные типы подключений и команд, обладающих единым интерфейсом. Т.е., чтобы подключиться к ресурсу A, используются класс EMovieConnectA, а для подключения к B - класс EMovieConnectB. Оба реализуют интерфейс IMovieConnect.

Вот потому то я и прошу помощи. Дайте только скелет как дожно выглядеть. А дальше я разберусь

Примерно так (уж не знаю, то ли это, что вам нужно):




interface IMovieConnect

{

    public function openConnection();

    public function closeConnection();

}


interface IMovieCommand

{

    public function search($value);

}


class EMovieConnectA implements IMovieConnect

{

    // реализация интерфейса IMovieConnect

}


class EMovieConnectB implements IMovieConnect

{

    // другая реализация интерфейса IMovieConnect

}


class EMovie extends CApplicationComponent

{

    private $connect;

    private $command;


    public function init()

    {

        if ($this->connect === null)

            $this->setConnect('EMovieConnectA'); // коннект по умолчанию

        // ...

    }


    public function setConnect($className)

    {

        $reflection = new ReflectionClass($className);

        if ($reflection->implementsInterface('IMovieConnect'))

            $this->connect = new $className();

        else

            throw new Exception();

    }


    public function setCommand($className)

    {

        // см. setConnect

    }


    public function connect()

    {

        $this->connect->openConnection();

    }


    public function search($value)

    {

        $this->command->search($value);

    }

}


// конфиг

'components'=>array(

    'movie'=>array(

        'class'=>'path.to.EMovie',

        'connect'=>'EMovieConnectB',

    ),

),



Почти то, вот только напряг в том что будет намного больше функций чем connect и search, а переопределять каждую в класе EMovie - неохота. Нужно что б определил функцию в

EMovieConnectA




public function status(){

    // ...

    echo "status";

}



А в контролере вызвал




Yii::app()->movie->status();



Тогда помогут только Behavior’ы. Но я бы посоветовал не лениться и еще раз подумать. Получается, что сначала вы хотите полностью разделить компоненты, а потом опять смешиваете их в кучу. Оставьте в классе EMovie только инициализацию этих компонентов, а нужные методы вызывайте “прозрачно”:




$movie->command->search('value');



Ведь в самом фреймворке не перемешиваются компоненты приложения. Если нужен объект для связи с базой данных, то пишем Yii::app()->db->createCommand(), а не Yii::app()->createCommand(). Последний вариант как раз является аналогией тому, что вы хотите сейчас сделать, но он явно "не тру".

andy_s

Еще раз спасибо, похоже единственно нормальным решением будет объеденить это все в один класс. А там время покажет, нужно будет разделить - буду глядеть в сторону Behavior

Вот же ж бывает, на другои форуме посоветовали

ImageComponent

Вся суть сводится к следующуму


public function init()

{

Yii::setPathOfAlias('Imagine',__DIR__.'/Imagine');

$className="Imagine\\{$this->driver}\\Imagine";

$this->_imagine=new $className;

parent::init();

}


public function __call($name,$parameters)

{

if(method_exists($this->_imagine,$name))

return call_user_func_array(array($this->_imagine,$name),$parameters);


return parent::__call($name,$parameters);

}

Не понятно, как это решает проблему. Если в классе нет метода, то метод ищется в двух других классах? Это и есть суть Behavior’ов, только здесь зачем-то это вручную реализовано.