Piotr Krajewski

Piotr Krajewski web application
programmer

Temat: Warning: spl_object_hash() i metoda persist w kontrolerze

Witam serdecznie,

ciąg dalszy walki w formularzami w symfony - tym razem problem przy zapisie.
mam sobie kontroler:


<?php

namespace Explore\UserBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;

use Explore\SiteBundle\Entity\Attraction;
use Explore\UserBundle\Form\AttractionType;

class AttractionsController extends Controller{
public function createAction(){
$attraction = new Attraction();
$form = $this->createForm(new AttractionType(), $attraction);
$request = $this->getRequest();

if ('POST' === $request->getMethod()){
$form->bindRequest($request);
if ($form->isValid()){
$entity = $this->getDoctrine()->getEntityManager();
$entity->persist($attraction);
$entity->flush();
return $this->redirect($this->generateUrl('ExploreUserBundle_createAttraction'));
}
}
return $this->render('ExploreUserBundle:Attractions:create.html.twig', array('form' => $form->createView()));
}
}


oraz mam plik AttractionType w ktorym buduje caly form.
Wygląda on tak:

<?php

namespace Explore\UserBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;


class AttractionType extends AbstractType{
public function buildForm(FormBuilder $builder, array $options){
$builder->add('category_id', 'entity', array('class' => 'ExploreSiteBundle:Category', 'property' => 'name', 'label' => 'Kategoria:'));
$builder->add('title', 'text');
$builder->add('city', 'text');
$builder->add('level', 'choice', array('choices' => \Explore\SiteBundle\Repository\AttractionRepository::$attractionLevels, 'label' => 'Poziom trudności:'));
$builder->add('attractive', 'choice', array('choices' => \Explore\SiteBundle\Repository\AttractionRepository::$attractionAttractive, 'label' => 'Atrakcyjność:'));
}

public function getDefaultOptions(array $options){
return array('data_class' => 'Explore\SiteBundle\Entity\Attraction');
}

public function getName(){
return 'attraction';
}
}


Prościej się nie da. Mój problem polega na tym iż podczas wysylania post'a z formularza dostaje 500 i taki błąd:


Warning: spl_object_hash() expects parameter 1 to be object, string given in /Users/pkrajewski/Sites/exploruj.to/vendor/doctrine/lib/Doctrine/ORM/UnitOfWork.php line 1095


wg dokumentacji symfony robię wszystko dobrze - http://symfony.com/doc/current/book/forms.html sekcja: "Forms and Doctrine"

Moje pytanko jak zmusić kontroler do zapisu danych?Piotr Krajewski edytował(a) ten post dnia 29.01.12 o godzinie 16:51
Daniel Żelazny

Daniel Żelazny Programista PHP,
Symfony

Temat: Warning: spl_object_hash() i metoda persist w kontrolerze

Z tego co widzę masz tu relację ManyToOne (category_id), spróbuj dodać przy definiowaniu jej (adnotacje, yaml bądź xml) opcję cascade: persist,

więcej :
http://www.doctrine-project.org/docs/orm/2.0/en/refere...
Piotr Krajewski

Piotr Krajewski web application
programmer

Temat: Warning: spl_object_hash() i metoda persist w kontrolerze

Faktycznie ot byl ten problem, nie mniej jednak mam ogromny problem z poprawną definicją Modelu, gdyż mając takie coś:


<?php

namespace Explore\SiteBundle\Entity;

use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\ORM\Mapping as ORM;

use Explore\SiteBundle\Repository\AttractionRepository as AttractionRepository;

use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Constraints\NotBlank;


/**
* Explore\SiteBundle\Entity\Attraction
*
* @ORM\Table(name="attractions")
* @ORM\Entity(repositoryClass="Explore\SiteBundle\Repository\AttractionRepository")
* @ORM\HasLifecycleCallbacks()
*/
class Attraction
{
/**
* @var integer $id
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;


/**
* @var integer $user_id
* Id uzytkownika posiadajacego atrakcje
*
* @ORM\Column(name="user_id", type="integer")
*/
private $user_id;


/**
* @var integer $region_id
* Id okreslajace id regionu
*
* @ORM\Column(name="region_id", type="integer")
*/
private $region_id;


/**
* @var integer $city_id
* Id okreslajace miasto przypisane do atrakcji
*
* @ORM\Column(name="city_id", type="integer")
*/
private $city_id;


/**
* @var integer $category_id
* Id okreslajace przynaleznosc atrakcji do kategorii
*
* @ORM\Column(name="category_id", type="integer")
*/
private $category_id;


/**
* @var string $title
* Tytul atrakcji
*
* @ORM\Column(name="title", type="string", length=255)
*/
private $title;


/**
* @var string title_slug
* Tytul atrakcji w postacji SLUG
*
* @Gedmo\Slug(fields={"title"})
* @ORM\Column(length=255, unique=true)
*/
private $title_slug;


/**
* @var text $description
* Opis atrakcji
*
* @ORM\Column(name="description", type="text")
*/
private $description;


/**
* @var text $important
* Wazne informacje odnosnie miejsca
*
* @ORM\Column(name="important", type="text")
*/
private $important;


/**
* @var smallint $rank
* Srednia ocena atrakcji - oceny sa dawane przez uzytkownikow
*
* @ORM\Column(name="rank", type="smallint", length=1)
*/
private $rank;


/**
* @var string $latitude
* Szerokosc geograficzna
*
* @ORM\Column(name="latitude", type="decimal", precision=16, scale=14)
*/
private $latitude;


/**
* @var string $longitude
* Dlugosc geograficzna
*
* @ORM\Column(name="longitude", type="decimal", precision=16, scale=14)
*/
private $longitude;


/**
* @var string $thumbnail
* Miniaturka / glowne zdjecie atrakcji
*
* @ORM\Column(name="thumbnail", type="string")
*/
private $thumbnail;


/**
* @var boolean $active
* Czy atrakcja / obiekt jest nadal dostepny (fizycznie w relanym swiecie)
*
* @ORM\Column(name="active", type="boolean")
*/
private $active;


/**
* @var integer $level
* Poziom trudnosci w explorowaniu miejsca
*
* @ORM\Column(name="level", type="integer")
*/
private $level;


/**
* @var integer $attractive
* Atrakcyjnosc miejsca
*
* @ORM\Column(name="attractive", type="smallint", length=1)
*/
private $attractive;


/**
* @var string $views
* Ilosc odwiedzin tego miejsca (na stronie wwww)
*
* @ORM\Column(name="views", type="integer")
*/
private $views;


/**
* @var string $status
* Status atrakcji:
* 0 - nieaktywny
* 1 - aktywny
* 2 - zawieszony
* 3 - usuniety
*
* @ORM\Column(name="status", type="smallint", length=1)
*/
private $status;


/**
* @var boolean $promoted
* Czy atrakcja / obiekt jest promowany (m.in na stronie glownej)
*
* @ORM\Column(name="promoted", type="boolean")
*/
private $promoted;


/**
* @var datetime $activated_at
* Data aktywacji atrakcji
*
* @ORM\Column(name="activated_at", type="datetime")
*/
private $activated_at;


/**
* @var datetime $created_at
* Data stworzenia atrakcji
*
* @Gedmo\Timestampable(on="create")
* @ORM\Column(type="date")
*/
private $created_at;


/**
* @var datetime $updated_at
* Data aktualizacji atrakcji
*
* @ORM\Column(type="datetime")
* @Gedmo\Timestampable(on="update")
*/
private $updated_at;



/*
*
* RELATIONS
*
*/


/**
* @ORM\ManyToOne(targetEntity="Explore\UserBundle\Entity\User", inversedBy="attractions", cascade={"persist"})
* @ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
private $user;


/**
* @ORM\ManyToOne(targetEntity="City", inversedBy="attractions", cascade={"persist"})
* @ORM\JoinColumn(name="city_id", referencedColumnName="id")
*/
private $city;


/**
* @ORM\ManyToOne(targetEntity="Region", inversedBy="attractions", cascade={"persist"})
* @ORM\JoinColumn(name="region_id", referencedColumnName="id")
*/
private $region;


/**
* @ORM\ManyToOne(targetEntity="Category", inversedBy="attractions", cascade={"persist"})
* @ORM\JoinColumn(name="category_id", referencedColumnName="id")
*/
private $category;


/**
* @ORM\ManyToMany(targetEntity="Explore\UserBundle\Entity\User", inversedBy="observe", cascade={"persist"})
* @ORM\JoinTable(name="observed_attraction",
* joinColumns={@ORM\JoinColumn(name="attraction_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")}
* )
*/
private $observed;


/**
* @ORM\ManyToMany(targetEntity="Tag", inversedBy="attraction", cascade={"persist"})
* @ORM\JoinTable(name="attraction_tags",
* joinColumns={@ORM\JoinColumn(name="attraction_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="tag_id", referencedColumnName="id")}
* )
*/
private $tags;


/**
* @ORM\OneToMany(targetEntity="Image", mappedBy="attraction")
*/
private $images;





public static function loadValidatorMetadata(ClassMetadata $metadata)
{
//$this->tags = new \Doctrine\Common\Collections\ArrayCollection();
// $this->user = new \Doctrine\Common\Collections\ArrayCollection();
// $this->city = new \Doctrine\Common\Collections\ArrayCollection();
// $this->region = new \Doctrine\Common\Collections\ArrayCollection();

//$this->tags = new ArrayCollection();

$metadata->addPropertyConstraint('title', new NotBlank());
$metadata->addPropertyConstraint('description', new NotBlank());
}

public function getId()
{
return $this->id;
}

public function setUserId($id)
{
$this->user_id = $id;
}

public function getUserId()
{
return $this->user_id;
}

public function getUser()
{
return $this->user;
}

public function setRegionId($id)
{
$this->region_id = $id;
}

public function getRegionId()
{
return $this->region_id;
}

public function getRegion()
{
return $this->region;
}

public function setCityId($id)
{
$this->city_id = $id;
}

public function getCityId()
{
return $this->city_id;
}

public function getCity()
{
return $this->city;
}

public function setCategoryId($id)
{
$this->category_id = $id;
}

public function getCategoryId()
{
return $this->category_id;
}

public function getCategory()
{
return $this->category;
}

public function setTitle($title)
{
$this->title = $title;
}

public function getTitle()
{
return $this->title;
}

public function getTitleSlug()
{
return $this->title_slug;
}

public function setDescription($description)
{
$this->description = $description;
}

public function getDescription()
{
return $this->description;
}

public function setImportant($important)
{
$this->important = $important;
}

public function getImportant()
{
return $this->important;
}

public function setRank($rank)
{
$this->rank = $rank;
}

public function getRank()
{
return $this->rank;
}

public function setAttractive($attractive)
{
$this->attractive = $attractive;
}

public function getAttractive()
{
return $this->attractive;
}

public function setLatitude($latitude)
{
$this->latitude = $latitude;
}

public function getLatitude()
{
return rtrim($this->latitude, '0');
}

public function setLongitude($longitude)
{
$this->longitude = $longitude;
}

public function getLongitude()
{
return rtrim($this->longitude, '0');
}

public function setViews($views)
{
$this->views = $views;
}

public function getViews()
{
return $this->views;
}

public function setStatus($status)
{
$this->status = $status;
}

public function getStatus()
{
return $this->status;
}

public function getNamedStatus()
{
return AttractionRepository::$statuses[$this->status];
}

public function getLabelStatus()
{
return AttractionRepository::$statusLabel[$this->status];
}

public function setPromoted($promoted)
{
$this->promoted = $promoted;
}

public function getPromoted()
{
return $this->promoted;
}

public function setActive($active)
{
$this->active = $active;
}

public function getActive()
{
return $this->active;
}

public function setLevel($level)
{
$this->level = $level;
}

public function getLevel()
{
return $this->level;
}

public function setThumbnail($thumbnail)
{
$this->thumbnail = $thumbnail;
}

public function getThumbnail()
{
return $this->thumbnail;
}

public function setActivatedAt()
{
$this->activated_at = new \DateTime();
}

public function getActivatedAt()
{
return $this->activated_at;
}

public function getCreatedAt()
{
return $this->created_at;
}

public function getUpdatedAt()
{
return $this->updated_at;
}


public function getTags()
{
return $this->tags;
}

public function setTags(ArrayCollection $tags)
{
//http://webspirited.com/tagit/
//http://symfony.com/doc/current/cookbook/form/form_collections.html
// $tags = explode(',', str_replace(', ', ',', $tags));

echo '<pre>';
print_r($tags);
echo '</pre>';
exit;
/*
$this->attraction_tags = $tags;

foreach ($tags as $tag){
$tag->setAttraction($this);
}*/
}

public function getImages()
{
return $this->images;
}
}


i w akcji kontrolera robię najprostszą rzecz:


$attraction = new Attraction();
$attraction->setUserId(2);
$attraction->setCategoryId(2);
$attraction->setCityId(2);
$attraction->setRegionId("1");
$attraction->setTitle('dupa');
$attraction->setDescription('kupa');
$attraction->setImportant('cipa');
$attraction->setRank(2);
$attraction->setLatitude(54.463004);
$attraction->setLongitude(21.639633);
$attraction->setThumbnail('ss.jpg');
$attraction->setAttractive(2);
$attraction->setActive(1);
$attraction->setLevel(8);
$attraction->setViews(1);
$attraction->setStatus(0);
$attraction->setPromoted(0);
$entity = $this->getDoctrine()->getEntityManager();
$entity->persist($attraction);
$entity->flush();
return new Response('Created product id '.$attraction->getId());


dostaje błędy na kluczach obcych pokroju tego:


SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'region_id' cannot be null


i tak dalej. Moje pytanie brzmi - co robie nie tak? bo jeden blad goni drugi a model przepisywalem chyba z 3 razy.

PS. sorry za długi post.
Daniel Żelazny

Daniel Żelazny Programista PHP,
Symfony

Temat: Warning: spl_object_hash() i metoda persist w kontrolerze

hmm, jeżeli deifniujesz ralację ManyToOne czy inne, daruj już sobie definiowanie kolumn z kluczami obcymi (region_id, user_id ) chyba że są Ci potrzebne do czegoś innego, to przynajmniej je inaczej nazwij.

Wywal zadeklarowanie prywatnych pól : user_id, region_id, category_id, city_id, pola są Ci niepotrzebne, oraz wszelkie gettery i settery dla tych atrybutów, przebuduj model, zaktualizuj bazę danych i zobaczymy czy będzie strzelać
Piotr Krajewski

Piotr Krajewski web application
programmer

Temat: Warning: spl_object_hash() i metoda persist w kontrolerze

oki to w takim razie jak pozniej mam ustawic dla user_id id uzytkownika skoro nie bede mial settera i gettera tego pola (podobnie dla pozostalych) ?
Daniel Żelazny

Daniel Żelazny Programista PHP,
Symfony

Temat: Warning: spl_object_hash() i metoda persist w kontrolerze

Podać do metody setUser() obiekt encji User :),

Natomiast w przypadku relacji ManyToOne żeby nie wyciągać po kolei z bazy danych dla danych obiektów, wystarczy użyć metody bindRequest(), podejrzyj jak to jest robione w możliwym do wygenerowania CRUD, zresztą także jest opisane w dziale Forms w dokumentacji.

Gdybyś chciał z palca posłużyć się przekazanym z formularza integerem, nie wiem jak należałoby to zrobić, dotychczas nie było mi to potrzebne.Daniel Żelazny edytował(a) ten post dnia 30.01.12 o godzinie 22:28
Piotr Krajewski

Piotr Krajewski web application
programmer

Temat: Warning: spl_object_hash() i metoda persist w kontrolerze

zaraz popatrze, ale wlasnie mi jest tak potrzebne ze czesc danych idzie z formularza a kilka np. user_id idzie z zmiennej ... hmmmm
Adam W.

Adam W. senior php
developer, Symfony

Temat: Warning: spl_object_hash() i metoda persist w kontrolerze

Daniel Żelazny:
hmm, jeżeli deifniujesz ralację ManyToOne czy inne, daruj już sobie definiowanie kolumn z kluczami obcymi (region_id, user_id ) chyba że są Ci potrzebne do czegoś innego, to przynajmniej je inaczej nazwij.

Wywal zadeklarowanie prywatnych pól : user_id, region_id, category_id, city_id, pola są Ci niepotrzebne, oraz wszelkie gettery i settery dla tych atrybutów, przebuduj model, zaktualizuj bazę danych i zobaczymy czy będzie strzelać

a jak pobrać ID połączonego obiektu, które to ID jest zapisane w tabeli?
w wygenerowanym crud nie mam w ogóle tych obiektów ManyToOne, nie za bardzo widzę jak pobrać to ID.
Antoni Orfin

Antoni Orfin Software Architect /
Symfony Consultant

Temat: Warning: spl_object_hash() i metoda persist w kontrolerze

Adam W.:

a jak pobrać ID połączonego obiektu, które to ID jest zapisane w tabeli?
w wygenerowanym crud nie mam w ogóle tych obiektów ManyToOne, nie za bardzo widzę jak pobrać to ID.
$obiekt->getPolaczonyObiekt()->getId();

na przykład tak. Pokaż kod modelu bo ciężko zgadnąć jak masz go napisanego...
Piotr Pasich

Piotr Pasich XSolve, Software
Developer

Temat: Warning: spl_object_hash() i metoda persist w kontrolerze

Najlepiej byłoby utworzyć encje dla wszystkich typów obiektów - user, kategoria, atrakcja itd. , a następnie skorzystać z app/console doctrine:generate:crud . Powinien wtedy utworzyć pełen crud dla danej encji.

Generator w osobnych plikach i klasach tworzy formularz dla encji, kontroler z pełnym crudem i widoki. Kod jest dość czytelny. Prawidłowo utworzona encja z odpowiednimi powiązaniami załatwia całą pracę w późniejszych etapach.

Następna dyskusja:

Krakow Hash House Harriers ...




Wyślij zaproszenie do