Помогите, afterSave не подходит, а события не осилил

Общие вопросы по использованию фреймворка. Если не знаете как что-то сделать и это про Yii, вам сюда.
Ответить
Ruganin
Сообщения: 14
Зарегистрирован: 2011.10.20, 15:25

Помогите, afterSave не подходит, а события не осилил

Сообщение Ruganin »

Приветствую вас люди добрые.
Помогите решить проблему.
PHP и Yii изучаю недавно, делаю первое приложение. Конечно многое можно почерпнуть из мануалов и форумов, но вот тут вообще встал в ступор и не могу решить задачу.
Есть модель Parsing.php и соответствующий контролер ParsingController.php, занимаются извлечением данных со страницы и переводом.
Основной метод контролера:

Код: Выделить всё

class ParsingController extends Controller {

// ...

public function actionParsingUrls() {
        $errors = array();
        $pars_page = '';
        $i_p = 0;
        if (isset($_POST['parsingurls'])) {
            $urls = Parsing::model()->getParsingUrls();
            Yii::import('application.vendors.*');
            require_once ("GoogleTranslater.php");
            foreach ($urls as $url) {
                // сразу создаем экземпляр переводчика
                //и экземпляр объекта
                $gt = new GoogleTranslater();
                $model = new Objects;
                // грузим страницу
                $page = file_get_contents($url);
                // забираем цену
                preg_match('/(?<=\<span class=\"detcena\"\>)([\d.]+)(?=\sKc\<\/span\>)/', $page, $price);
                $price = $price[1];
                $price = str_replace('.', '', $price);
                $model->price = $price;
                // забираем дату публикации
                preg_match('/(?<=Datum zadani:\s\<strong\>)([\d.]+)(?=\<\/strong\>)/', $page, $t_date);
                $t_date = $t_date[1];
                $date = explode('.',$t_date);
                $date_publication = $date[2].'-'.$date[1].'-'.$date[0];
                $model->date_publication = $date_publication;
                // вырезаем блок с данными квартиры
                $block_start = '<div class="tab" id="popis"';
                $block_stop = '<div class="tab" id="galerie"';
                $block_data = Parsing::model()->cutString($block_start, $block_stop, $page);
                // забираем количество комнат
                preg_match('/(?<=Velikost bytu:\<\/th\>\<td\>)([\d\w+]+)(?=\<\/td\>\<\/tr\>)/', $block_data, $rooms);
                $rooms = $rooms[1];
                $model->rooms = $rooms;
                // забираем общую площадь
                preg_match('/(?<=Uzitna plocha:\<\/th\>\<td\>)([\d]+)(?=\sm&sup2;\<\/td\>\<\/tr\>)/', $block_data, $total_area);
                $total_area = $total_area[1];
                $model->total_area = $total_area;
                // забираем жилую площадь
                preg_match('/(?<=Plocha bytu:\<\/th\>\<td\>)([\d]+)(?=\sm&sup2;\<\/td\>\<\/tr\>)/', $block_data, $living_area);
                $living_area = $living_area[1];
                $model->living_area = $living_area;
                // забираем этаж
                preg_match('/(?<=Cislo podlazi:\<\/th\>\<td\>)([\d]+)[\s\w.]*(?=\<\/td\>\<\/tr\>)/', $block_data, $floor);
                $floor = $floor[1];
                $model->floor = $floor;
                // забираем этажность
                preg_match('/(?<=Pocet NP:\<\/th\>\<td\>)([\d]+)(?=\<\/td\>\<\/tr\>)/', $block_data, $floors);
                $floors = $floors[1];
                $model->floors = $floors;

                // ...

                // пишем объект в базу
                if (!$model->save()) {
                    $errors[] = 'Не могу сохранить данные со страницы => ' . $url;
                } else {
                    Yii::app()->db->createCommand()->update('{{parsing}}', array('status_parsing'=>Parsing::PARSING_OK), 'url=:url', array(':url'=>$url));
                    $i_p++;
                }
            }
            $pars_page = 'Распарсил страниц => ' . $i_p;
        }
        $this->render('parsingurls', array('errors' => $errors, 'pars_page' => $pars_page));
    }
} 
Как видно из кода все данные обрабатывает модель Objects.php, в этой же модели далее в afterSave происходит обработка фотографий.

Код: Выделить всё

class Objects extends CActiveRecord
{

// ...

/**
     * Сохраняет фото после сохранения объекта
     *
     */
    public $medium_foto = '';
    public $small_foto = '';
    public $fotos = array();
    public $used_url = '';    
    public function afterSave() {
       // Получаем id записанного объекта
       $id_object = $this->id;
       $fotos = $this->fotos;
       $used_url = $this->used_url;
       // пишем id объекта для отработанного URL
       Yii::app()->db->createCommand()->update('{{parsing}}', array('id_object'=>$id_object), 'url=:url', array(':url'=>$used_url));
       // Создаем директории под фото
       // Основная директория объекта
       $dir = $_SERVER['DOCUMENT_ROOT'].'/images/'.$id_object;
       mkdir($dir);
       // Директория фото
       $dirscr = $_SERVER['DOCUMENT_ROOT'].'/images/'.$id_object.'/foto';
       mkdir($dirscr);
       // Директория превью
       $dirthumb = $_SERVER['DOCUMENT_ROOT'].'/images/'.$id_object.'/thumb';
       mkdir($dirthumb);
       // проверим пустой ли массив с URL
       if(count($fotos)!==0){       
       // Создаем рандомное фото для описания
       $rand_foto = array_rand($fotos);
       $descr_foto = $fotos[$rand_foto];       
       Yii::app()->ih->load($descr_foto)
       ->resize(300, 225)
       ->save($_SERVER['DOCUMENT_ROOT'] . '/images/' .$id_object. '/medium_foto.jpg')
       ->reload()->adaptiveThumb(150, 100)
       ->save($_SERVER['DOCUMENT_ROOT'].'/images/' .$id_object. '/small_foto.jpg');
       $url_medium = '/images/' .$id_object. '/medium_foto.jpg';
       $url_small = '/images/' .$id_object. '/small_foto.jpg';
       Yii::app()->db->createCommand()->update('{{objects}}', array('medium_foto'=>$url_medium), 'id=:id', array(':id'=>$id_object));
       Yii::app()->db->createCommand()->update('{{objects}}', array('small_foto'=>$url_small), 'id=:id', array(':id'=>$id_object));
       // Грузим фото объекта
       $i = 1;
       foreach ($fotos as $foto) {
            Yii::app()->ih->load($foto)
            ->resize(600, 450)
            ->save($_SERVER['DOCUMENT_ROOT'].'/images/'.$id_object.'/foto/'.$i.'.jpg')
            ->reload()
            ->adaptiveThumb(150, 100)
            ->save($_SERVER['DOCUMENT_ROOT'].'/images/'.$id_object.'/thumb/'.$i.'.jpg');
            Yii::app()->db->createCommand()
            ->insert('{{fotos_objects}}', array(
                                'id_object'=>$id_object,
                                'foto'=>'/images/'.$id_object.'/foto/'.$i.'.jpg',
                                'thumb' =>'/images/'.$id_object.'/thumb/'.$i.'.jpg',
                                ));
            $i++;
       }
    }
    }
}
 
Однако объект можно создать через контролер ObjectsController.php метод Create и естественно последующий afterSave в этом случае будет излишен.
Я так понимаю надо создавать событие для прасинга, но вот это я не осилил, и даже не знаю как подступиться.
Помогите создать сей тайное колдунство, буду признателен.
SpiLLeR
Сообщения: 350
Зарегистрирован: 2009.09.17, 16:47
Откуда: Санкт-Петербург
Контактная информация:

Re: Помогите, afterSave не подходит, а события не осилил

Сообщение SpiLLeR »

Можно пробовать разрулить через сценарий. $model->scenario = 'test'. И потом в afterSave() if($this->scenario == 'test') { blah-blah }
Предупрежден - значит вооружен.
devKP.ru
maschingan
Сообщения: 75
Зарегистрирован: 2011.01.20, 23:52

Re: Помогите, afterSave не подходит, а события не осилил

Сообщение maschingan »

Можно добавить метод model::savePhoto и где нужно аттачить этот метод к afterSave.

Код: Выделить всё

If (!empty($photo))
    $model->onAfterSave = array($model, 'savePhoto')
 
http://yiiframework.ru/doc/cookbook/ru/core.events
lnghost
Сообщения: 134
Зарегистрирован: 2011.07.26, 18:05
Откуда: Воронеж
Контактная информация:

Re: Помогите, afterSave не подходит, а события не осилил

Сообщение lnghost »

Можно проверять наличие $this->fotos. Если есть - обрабатывать, если нет - пропускать.
Конференция: yii@conference.jabber.ru Сайт: http://kamaran.ru
Ruganin
Сообщения: 14
Зарегистрирован: 2011.10.20, 15:25

Re: Помогите, afterSave не подходит, а события не осилил

Сообщение Ruganin »

lnghost писал(а):Можно проверять наличие $this->fotos. Если есть - обрабатывать, если нет - пропускать.
Это не подходит сразу, т.к.это сейчас, не зная как сделать, я в afterSave засунул только обработку фото, а так после записи объекта, будут модифицироваться дополнительные данные, которые следует модифицировать только если отработал ParsingUrls.
Ruganin
Сообщения: 14
Зарегистрирован: 2011.10.20, 15:25

Re: Помогите, afterSave не подходит, а события не осилил

Сообщение Ruganin »

SpiLLeR писал(а):Можно пробовать разрулить через сценарий. $model->scenario = 'test'. И потом в afterSave() if($this->scenario == 'test') { blah-blah }
Хм, вот это кажется то что нужно.
Я правильно понял?

Код: Выделить всё

 public function actionParsingUrls() {
            
                    $model = new Objects;
                     // СОЗДАЮ СЦЕНАРИЙ
                    $model->scenario = 'ParsingUrls';
                    $model->fotos = $fotos;
                    // пишем объект в базу
                    $model->save();
    } 
А в afterSave вот так:

Код: Выделить всё

public function afterSave() {
        if($this->scenario == 'ParsingUrls') { 
            $fotos = $this->fotos;
           foreach ($fotos as $foto) {
           //А ТУТ ТИПА ОБРАБАТЫВАЕМ ФОТКИ И ВСЕ ЧТО НУЖНО
           }
           }
 }     
 
И Еще сразу вопрос: $model = new Objects('ParsingUrls'); и $model->scenario = 'ParsingUrls'; это эквивалентные записи?
SpiLLeR
Сообщения: 350
Зарегистрирован: 2009.09.17, 16:47
Откуда: Санкт-Петербург
Контактная информация:

Re: Помогите, afterSave не подходит, а события не осилил

Сообщение SpiLLeR »

Да, все верно.
Эти записи эквивалентны.
Предупрежден - значит вооружен.
devKP.ru
Ruganin
Сообщения: 14
Зарегистрирован: 2011.10.20, 15:25

Re: Помогите, afterSave не подходит, а события не осилил

Сообщение Ruganin »

SpiLLeR спасибо за помощь, все работает как надо.
Ответить