класс Foto

Baranov_Dron

Новичок
класс Foto

Пример приведённый тут слегка упрощён, от требуемой задачи, для наглядности.
Использую symfony + phpDoctrinePlugin.

Есть форма добавления статьи, в ней можно вписывать теги данной статьи, название, текст, дату и выбрать изображения для заливки.
Потом скрипт добавляет изображения в папку uploads, и записывает в БД 1 запись в таблицу articles и несколько записей в таблицу foto.
Ну при отображение есть статья и внизу блок с превью картинок. По нажатию будет полное изображение в новом окне, всё понятно...

Идём дальше, есть класс
abstract class BaseArticles extends sfDoctrineRecord
{}
в котором указываются свойства таблицы, и от него наследуется класс
class Articles extends BaseArticles
{}
Ну и тоже самое с классом foto.
Дальше в контролере мы создаём запись типа
PHP:
$art = new Articles;
$art->title = $request->getParameter('title');
$art->text = $request->getParameter('text') ;
     $this->foto[]->name = 'test';
     $this->foto[]->name = 'test';
$art->save();
Ну теперь самое интересное и сложное для меня, кто должен отвечать за заливку фото, а также добавление его в БД?
Я решил проблему следующим образом,
перегрузил метод save()
PHP:
class Foto extends BaseFoto
{
    public $file_object;

    public function setFileObject($file)
    {
        $this->file_object = $file;
    }

     public function save(Doctrine_Connection $conn = null)
    {
        $file = $this->file_object;

        $svimage = getimagesize($file->getTempName());

        $this->extension = $file->getExtension($file->getOriginalExtension());
		$this->filesize = $file->getSize();
		$this->height = $svimage[1];
		$this->width = $svimage[0];
		$this->date = date('Y-m-d H:i:s');

        parent::save($conn);

	    $file->save(sfConfig::get('sf_upload_dir').'/board/'.$this->id.$this->extension);
    }

    public function getRealName()
    {
        return $this->id.$this->extension;
    }
}
Теперь вызов выглядит наподобие
PHP:
$art = new Articles;
$art->title = $request->getParameter('title');
$art->text = $request->getParameter('text') ;
     $this->foto[]->name = 'test';
     $this->foto[]->setFileObject($this->getValue('foto1'));
     $this->foto[]->name = 'test';
     $this->foto[]->setFileObject($this->getValue('foto2'));
$art->save();
Тоесть перетаскиванием изображения с временного хранилища в нужную папку занимается класс Foto, но у меня есть большие сомнения в правильности решения, например в таблице фото имеется столбец булевого типа preview, тоесть есть ли превью, и если нету, чтоб дать демону, запускаемому кроном понять, что для этого изображения сделать preview и значение столбика из false сделать в TRUE.
Но тогда класс Foto отвечает:
1) за создание preview
2) за заливку изображений
3) за добавление информации о изображение в БД
4) за удаление(строки в таблице + самих файлов рисунков)
5) и т.д.

Но по сути правильно ли, что класс foto занимается такими задачами?!
Я вообще думал, что этот класс должен только работать с БД.
И вопрос к пользователям доктрины! Ничего страшного не случится при перегрузки метода save и delete, вроде не должно, но всё же?
 

AmdY

Пью пиво
Команда форума
ты верно сделал, только добавь ещё обработчик на удаление записи.
Я вообще думал, что этот класс должен только работать с БД.
в принципе, так оно и получается. если бы приходило вместо файла его содержимое, тебя же не мучала бы сомнения

-~{}~ 16.09.08 02:11:

вот только перегружать метод save не следует, тебе нужны
preInsert, postInsert для вставки
postDelete для удаления
preUpdate, postUpdate при апдейте
 

Baranov_Dron

Новичок
AmdY cпасибо за ответ.
Остаётся только два вопроса
1) Передача объекта с фотографией в класс Foto, правильно ли так передавать?
PHP:
class Foto extends BaseFoto 
{
    public $file_object;

    public function setFileObject($file)
    {
        $this->file_object = $file;
    } 
............................
}
2) кто должен делать preview?
Тоесть у меня preview делается cron`ом. Будет ли правильно если в кроне будет что-то наподобие
PHP:
<?php
$foto = new Foto;
for ($i =1; $i <= 10; $i++)
{
    if (!$foto->makeOnePreview())
        break;
}
?>
А метод makeOnePreview() класса Foto будет уже искать одну строчку в таблице foto и делать для одного фото preview, и если всё сделал, то возращает TRUE, а если нету строк для работы, то возратит FALSE...
Правильно ли будет сделать так?
 

AmdY

Пью пиво
Команда форума
это неверный подход, ведь не нужно забывать, что Foto extends BaseFoto в свою очередь унаследовано от Doctrine_Record, что подразумневает работу непосредственно с записью, а не всей таблицей.
$collection = Doctrine::getTable('Foto')->findByMake_preview(1);
foreach($collection AS $item) {
$item->makePreview();
}
 

Baranov_Dron

Новичок
время...
просто на генерацию превью уходит около 3-4 секунд(для пяти фото), что я считаю неприемлемым.
я тему создавал о этом
http://phpclub.ru/talk/showthread.php?s=&threadid=106551
 

Духовность™

Продвинутый новичок
Ну теперь самое интересное и сложное для меня, кто должен отвечать за заливку фото, а также добавление его в БД?
я так сделал:

в контроллере:

PHP:
    // проверка изображений на валидность
    private function checkImage()
    {
        global $_CONFIG;
        
        $this->uploads = array();
        
        if (isset($_FILES['article_image']))
        {
            foreach ($_FILES['article_image']['name'] as $id => $__)
            {
                // параметры изображения из FILES
                $fromFiles = array
                (
                    'name'     => &$_FILES['article_image']['name'][$id],
                    'type'     => &$_FILES['article_image']['type'][$id],
                    'tmp_name' => &$_FILES['article_image']['tmp_name'][$id],
                    'error'    => &$_FILES['article_image']['error'][$id],
                    'size'     => &$_FILES['article_image']['size'][$id],
                    'current'  => &$_POST['current'][$id]
                );
                
                // создаем новый объект изображения
                $img = new newArticleImage($fromFiles);
                $img->setTempDirectory($_CONFIG['dir']['temp']);
                $img->setImageName(translit::UrlTranslit($_POST['article_image_name'][$id]));
                $img->setUploadDir($_CONFIG['dir']['images']['articles']['normal']);
                $img->checkFile();
                
                // сохраняем объект в массиве uploads
                $this->uploads[$id] = $img;
            }
        }
    }
}
далее, в контроллере, методе сохранения статьи:

PHP:
// если есть инициализированные объекты изображений
if ($this->uploads)
{
    foreach ($this->uploads as $img)
    {
        // картинко сохранили 
        if ($img->saveFile($this->id_article))
        {
            // ресайзим 
            $img->setFileSize($_CONFIG['params']['normal_configs']);
            
            // записываем инфо в БД о картинко 
            $this->article->setImageInfo($img);
            
            // делаем 3 превью  картико (3 - потому, что так дизайнер сказало)
            foreach ($_CONFIG['dir']['images']['articles']['preview'] as $id => $dir)
            {
                $img->makePreview($dir, $_CONFIG['params']['preview_configs'][$id]);
            }
        }
    }
}
 
Сверху