Krzysztof Biernacki

Krzysztof Biernacki programista PHP

Temat: [SF 1.4, Doctrine] Problem z zapisaniem do bazy danych

Witajcie.
Siedze od pewnego czasu, drapie sie po glowie i nie moge znalezc rozwiazania na ponizszy problem. Otoz, napisalem pewien skrypt, ktorego zadaniem jest utworzenie dwoch miniaturek zdjec (thumb_xxxx oraz image_xxxx). Miniaturki sa poprawnie tworzone i zapisywane na dysku. Natomiast w klasie Article.class.php (w katalogu lib/model/doctrine) chce zapisac informacje do bazy danych (nazwy miniaturek). Tutaj zaczynaja sie schody. Co robie zle? Ktos pomoze?


public function setImage($value) {

$uploadImagePath = sfConfig::get('app_artPict_images_dir').'/';
$uploadThumbPath = sfConfig::get('app_artPict_thumbs_dir').'/';

$imagePrefix = 'image_';
$thumbPrefix = 'thumb_';

$artPictMaxWidth = sfConfig::get('app_artPict_maxWidth');
$artPictSliderMaxWidth = sfConfig::get('app_artPict_sliderMaxWidth');

$oldImage = $this->getImage();
$oldThumb = $this->getThumb();

if (!empty($oldImage) && is_file($uploadImagePath.$imagePrefix.$oldImage)) {
unlink($uploadImagePath.$imagePrefix.$oldImage);
}

if (!empty($oldThumb) && is_file($uploadThumbPath.$thumbPrefix.$oldThumb)) {
unlink($uploadThumbPath.$thumbPrefix.$oldThumb);
}

if (!empty($value) && is_file($uploadImagePath.$value)) {
$image = new sfThumbnail($artPictSliderMaxWidth, '', true, true, 100);
$image->loadFile($uploadImagePath.$value);
$image->save($uploadImagePath.$imagePrefix.$value);

$thumb = new sfThumbnail($artPictMaxWidth, '', true, false, 90);
$thumb->loadFile($uploadImagePath.$value);
$thumb->save($uploadThumbPath.$thumbPrefix.$value);

unlink($uploadImagePath.$value);
}

parent::setThumb($thumbPrefix.$value);
//parent::setImage($imagePrefix.$value); - w tym miejscu jest problem. Po odkomentowaniu tworzy sie petla, minaiturki zapisuja sie po kilkanascie razy, po czym nastepuje przerwanie skryptu ze wzgledu na timeout. W bazie danych nic sie nie zapisuje.
}
Piotr Głudkowski

Piotr Głudkowski Rzucam się na
wszystko to, co jest
ciekawe i wymaga
rusze...

Temat: [SF 1.4, Doctrine] Problem z zapisaniem do bazy danych

A dziedziczysz po BaseArticle? Bo jeśli zapomniałeś tego dopisać, to klasą bazową dla Article jest właśnie Article ;) i zawołanie parent::setImage() woła Ci de facto funkcję setImage() z klasy Article - i to się pętli.
Krzysztof Biernacki

Krzysztof Biernacki programista PHP

Temat: [SF 1.4, Doctrine] Problem z zapisaniem do bazy danych

Klasa Article dziedziczy po BaseArticle, a mimo to skrypt sie zapetla. Po prostu zglupialem. Ktos jeszcze rzuci okiem i podpowie w jaki sposob naprawic blad?

konto usunięte

Temat: [SF 1.4, Doctrine] Problem z zapisaniem do bazy danych

To czego doświadczasz to "efekt uboczny" stosowania przez Doctrine'a metod magicznych dla getterów i setterów. Aby pominąć ten mechanizm i w swoim przysłoniętym setterze wywołać standardowy setter Doctrine'a w miejsce:

parent::setImage($imagePrefix.$value)

użyj:

$this->_set('image', $imagePrefix.$value)
Sebastian Kremiec edytował(a) ten post dnia 23.10.11 o godzinie 11:22
Krzysztof Biernacki

Krzysztof Biernacki programista PHP

Temat: [SF 1.4, Doctrine] Problem z zapisaniem do bazy danych

Bog zaplac dobry czlowieku. Teraz skrypt dziala jak nalezy.
Swoja droga, co rusz lapie sie na tym, ze nie znajac dobrze Doctrine mozna na poprawianiu blahostki spedzic wiecznosc.

Pozostaje mi teraz uporanie sie z kluczami obcymi, podczas kasowania artykulu.
Przy probie skasowania wybranego artykulu, dostaje monit postaci:

Cannot delete or update a parent row: a foreign key constraint fails


Oczywiscie w modelu jest "stosowna wzmianka" nt. relacji pomiedzy artykulami i kategoriami. Do tego zapis: onDelete: CASCADE w tabeli laczacej.

Probowalem wymusic na Doctrine, aby nie sprawdzal kluczy obcych mniej wiecej w ten sposob:


$task = new sfDoctrineLoadDataTask($this->dispatcher, $this->formatter);
$task->setCommandApplication($this->commandApplication);

$databaseManager = new sfDatabaseManager($this->configuration);

$c = Doctrine_Manager::getInstance()->getCurrentConnection();
$c->exec('SET foreign_key_checks = 0');
$return_value = $task->run(array(), $taskOptions);
$c->exec('SET foreign_key_checks = 1');


Jednak powyzszy zabieg nie dziala. Jak to ugryzc?
Krzysztof N.

Krzysztof N. CEO. Aplikacje
internetowe i
mobilne. Symfony,
Zend.

Temat: [SF 1.4, Doctrine] Problem z zapisaniem do bazy danych

Krzysztof Biernacki:
Przy probie skasowania wybranego artykulu, dostaje monit postaci:
Cannot delete or update a parent row: a foreign key constraint fails


Oczywiscie w modelu jest "stosowna wzmianka" nt. relacji pomiedzy artykulami i kategoriami. Do tego zapis: onDelete: CASCADE w tabeli laczacej.
(...)
Jednak powyzszy zabieg nie dziala. Jak to ugryzc?
Masz relację kategoria -> artykuł, tj. klucz główny w tabeli z kategoriami jest kluczem obcym w tabeli z artykułami, tak?
Krzysztof Biernacki

Krzysztof Biernacki programista PHP

Temat: [SF 1.4, Doctrine] Problem z zapisaniem do bazy danych

Ponizej plik schema.yml, na podstawie ktorego zostal wygenerowany model (relacje artykulow z kategoriami):


Article:
actAs:
Timestampable: ~
columns:
id:
type: integer(4)
fixed: false
unsigned: false
primary: true
autoincrement: true
title:
type: string(255)
fixed: false
unsigned: false
primary: false
notnull: true
autoincrement: false
text:
type: string()
fixed: false
unsigned: false
primary: false
notnull: true
autoincrement: false
thumb:
type: string(100)
fixed: false
unsigned: false
primary: false
notnull: false
autoincrement: false
image:
type: string(100)
fixed: false
unsigned: false
primary: false
notnull: true
autoincrement: false
created_at:
type: timestamp(25)
fixed: false
unsigned: false
primary: false
notnull: true
autoincrement: false
updated_at:
type: timestamp(25)
fixed: false
unsigned: false
primary: false
notnull: true
autoincrement: false
is_active:
type: enum(5)
fixed: false
unsigned: false
values:
- 'true'
- 'false'
primary: false
default: 'false'
notnull: true
autoincrement: false
relations:
Categories:
class: Category
refClass: CategoryHasArticle
local: article_id
foreign: category_id
foreignAlias: Articles
CategoryHasArticle:
local: id
foreign: article_id
type: many

Category:
actAs:
Timestampable: ~
columns:
id:
type: integer(4)
fixed: false
unsigned: false
primary: true
autoincrement: true
category_id:
type: integer(4)
fixed: false
unsigned: false
primary: false
notnull: true
autoincrement: false
name:
type: string(150)
fixed: false
unsigned: false
primary: false
notnull: true
autoincrement: false
is_active:
type: enum(5)
fixed: false
unsigned: false
values:
- 'true'
- 'false'
primary: false
default: 'false'
notnull: true
autoincrement: false
ord:
type: integer(4)
fixed: false
unsigned: false
primary: false
notnull: false
autoincrement: false
relations:
Category:
local: id
foreign: category_id
type: many
Article:
class: Category
local: category_id
foreign: article_id
refClass: CategoryHasArticle
foreignAlias: Articles
CategoryHasArticle:
local: id
foreign: category_id
type: many

CategoryHasArticle:
connection: doctrine
tableName: category_has_article
columns:
category_id:
type: integer(4)
fixed: false
unsigned: false
primary: true
autoincrement: false
article_id:
type: integer(4)
fixed: false
unsigned: false
primary: true
autoincrement: false
relations:
Category:
local: category_id
onDelete: CASCADE
Article:
local: article_id
onDelete: CASCADE


Skonczyly mi sie pomysly, w jaki sposob uporac sie z kluczami obcymi i nieszczesnym kasowaniem artykulow. Bylbym wdzieczny za pomoc.
Krzysztof N.

Krzysztof N. CEO. Aplikacje
internetowe i
mobilne. Symfony,
Zend.

Temat: [SF 1.4, Doctrine] Problem z zapisaniem do bazy danych

Krzysztof Biernacki:
Ponizej plik schema.yml, na podstawie ktorego zostal wygenerowany model (relacje artykulow z kategoriami):
(...)
Skonczyly mi sie pomysly, w jaki sposob uporac sie z kluczami obcymi i nieszczesnym kasowaniem artykulow. Bylbym wdzieczny za pomoc.
Pierwsza możliwość:
Przed usunięciem artykułu usuwaj również wpis z tabeli wiążącej artykuł z kategorią(-ami).

Druga możliwość:
Skorzystaj z właściwości SoftDelete polegającej na tym, że zamiast usuwania wiersza z danej tabeli jest w nim ustawiana wartość bieżącej daty dla kolumny deleted_at i jest on traktowany jako usunięty.Krzysztof N. edytował(a) ten post dnia 23.10.11 o godzinie 18:31
Grzegorz Śliwiński

Grzegorz Śliwiński Programista python

Temat: [SF 1.4, Doctrine] Problem z zapisaniem do bazy danych

I sprawdź dokładnie jak klucze obce są zdefiniowane w bazie danych. Czy na pewno wszystkie tam mają ustawione ON DELETE CASCADE
Krzysztof Biernacki

Krzysztof Biernacki programista PHP

Temat: [SF 1.4, Doctrine] Problem z zapisaniem do bazy danych

Dzieki serdeczne za wszelkie sugestie i pomoc.
Sprawdzilem tabele laczaca 'category_has_article' z poziomu PHPMyAdmin i okazalo sie, ze nie bylo tam odpowiedniej adnotacji co do relacji i kluczy obcych. Nie wiedziec czemu, ale w widoku relacyjnym widnial zapis postaci 'ON DELETE: RESTRICT' zamiast 'ON DELETE: CASCADE'.
Nie wiem, gdzie robie blad przy tworzeniu modelu z pliku schema.yml, skoro pozniej relacje w bazie danych sa nieprawidlowe. Moze ktos mnie oswieci...

Pozdrawiam.
Krzysztof N.

Krzysztof N. CEO. Aplikacje
internetowe i
mobilne. Symfony,
Zend.

Temat: [SF 1.4, Doctrine] Problem z zapisaniem do bazy danych

Krzysztof Biernacki:
Nie wiedziec czemu, ale w widoku relacyjnym widnial zapis postaci 'ON DELETE: RESTRICT' zamiast 'ON DELETE: CASCADE'.
Nie wiem jak to zrobiłeś. Wygenerowałem tabele na podstawie podanego dzisiaj o 14:35 fragmentu schema.yml i uzyskałem ON DELETE: CASCADE, ON UPDATE: RESTRICT dla tabeli category_has_article.

konto usunięte

Temat: [SF 1.4, Doctrine] Problem z zapisaniem do bazy danych

być może zmiany w schemacie dokonywane były w trakcie generowania bazy danych i doctrine schemat bazy odczytal z cache. Czasem tak mam, ze zmiany dokonane w schemacie nie sa widziane przez doctrine dopoki nie usune cache. Czasem nawet musze usunac wszystkie pliki doctrine w katalogu /tmp (dokladniej pliki /tmp/doctrine_schema*).

Swoja droga nie musisz pisac w schemacie tego typu rzeczy
      fixed: false
unsigned: false
primary: false
autoincrement: false
sa one domyślne. Dopiero jezeli chcesz np utworzyc klucz glowny to to zmieniaj. Jezeli chcesz zobaczyc, jakie sa domyslne wartosci, zajrzyj na stonie http://www.symfonyreference.com/Michał Majewski edytował(a) ten post dnia 24.10.11 o godzinie 07:58

Następna dyskusja:

Generowanie schematu z bazy...




Wyślij zaproszenie do