PHP - Symfony2 - related entity

0

Witam,

Właśnie korzystam z tego frameworka doctrine i muszę powiedzieć, że nie jest dla mnie zbyt sugestywny bądź czegoś nie rozumiem. Mam pytanie jak w łatwy sposób powiązać dwa obiekty, czytałem właśnie, że należy edytować klasy i dopisać tam odpowiednie elementy jak funkcje przypisania oraz pola, które mają być przypisane. Jeśli możecie mi podrzucić jakiś łatwiejszy tutorial byłbym wdzięczny ewentualnie jakoś mi to opisać. W innych językacj jest to zdecydowanie prostsze tutaj , trzeba się trochę namęczyć. Jak zwykle brak mi czasu, bo walczę z kilkoma rzeczami na raz.
Będę wam bardzo wdzięczy za pomoc.

Pozdrawiam

Może jeszcze dopiszę fragment bo może się ciężko wysłowiłem
mam takie zapytanie

 
$query = $this->getDoctrine()->getManager()
        ->createQuery(
            'SELECT a.title as title, a.name as name,
            a.content as content, m.name as menuname 
            FROM ZzwpBundle:articles a JOIN ZzwpBundle:menus m
            WHERE a.id = :id'
        )->setParameter('id', $id);

i wiem żeby to zadziałało trzeba wpisać parę powiązań w klasach. Czy ktoś mógłby mi to jakoś opisać ?

tzn wiem o co chodzi ale chodzi mi o wyjaśnienie jak to wprowadzić w tych klasach entity ?

0

Dokumentacja twoim przyjacielem! - masz tam opisane wszystkie typy relacji.
http://doctrine-orm.readthedocs.org/en/latest/reference/association-mapping.html

0

Przesyłam Ci przykład dwóch powiązanych ze sobą encji.
Zwróć uwagę na katalog (widzisz go w namespace). Oczywiście możesz go umieścić w Twoim bundle ale musi być w Entity. Zwróć też uwagę na adnotacje - masz tam powiązanie z kolumnami w bazie.

<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Article
 *
 * @ORM\Table()
 * @ORM\Entity
 */
class Article
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

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

    /**
     * @var string
     *
     * @ORM\Column(name="content", type="text")
     */
    private $content;

    /**
     * @ORM\ManyToOne(targetEntity="Category", inversedBy="articles")
     * @ORM\JoinColumn(name="category_id", referencedColumnName="id")
     */
    protected $category;


    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set title
     *
     * @param string $title
     * @return Article
     */
    public function setTitle($title)
    {
        $this->title = $title;

        return $this;
    }

    /**
     * Get title
     *
     * @return string 
     */
    public function getTitle()
    {
        return $this->title;
    }

    /**
     * Set content
     *
     * @param string $content
     * @return Article
     */
    public function setContent($content)
    {
        $this->content = $content;

        return $this;
    }

    /**
     * Get content
     *
     * @return string 
     */
    public function getContent()
    {
        return $this->content;
    }

    /**
     * Set category
     *
     * @param \AppBundle\Entity\Category $category
     * @return Article
     */
    public function setCategory(\AppBundle\Entity\Category $category = null)
    {
        $this->category = $category;

        return $this;
    }

    /**
     * Get category
     *
     * @return \AppBundle\Entity\Category 
     */
    public function getCategory()
    {
        return $this->category;
    }
}
<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Category
 *
 * @ORM\Table()
 * @ORM\Entity
 */
class Category
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

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

    /**
     * @ORM\OneToMany(targetEntity="Article", mappedBy="category")
     */
    protected $articles;

    public function __construct()
    {
        $this->articles = new ArrayCollection();
    }


    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set name
     *
     * @param string $name
     * @return Category
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

    /**
     * Get name
     *
     * @return string 
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Add articles
     *
     * @param \AppBundle\Entity\Article $articles
     * @return Category
     */
    public function addArticle(\AppBundle\Entity\Article $articles)
    {
        $this->articles[] = $articles;

        return $this;
    }

    /**
     * Remove articles
     *
     * @param \AppBundle\Entity\Article $articles
     */
    public function removeArticle(\AppBundle\Entity\Article $articles)
    {
        $this->articles->removeElement($articles);
    }

    /**
     * Get articles
     *
     * @return \Doctrine\Common\Collections\Collection 
     */
    public function getArticles()
    {
        return $this->articles;
    }
}

Oraz przykład wykorzystania powyższych encji w kontrolerze:

$id = 1;

$article = $this->getDoctrine()
    ->getRepository('AppBundle:Article')
    ->find($id);

$categoryName = $article->getCategory()->getName();

więcej szczegółów po linkiem: http://symfony.com/doc/current/book/doctrine.html#relationship-mapping-metadata

[Adrian]

0

No właśnie trochę się zgubiłem, ponieważ tak

mamy pierwszy byt/jednostkę/klasę(enitity) o nazwie Article
które ma atrybuty takie jak

     /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;
 
    /**
     * @var string
     *
     * @ORM\Column(name="title", type="string", length=255)
     */
    private $title;
 
    /**
     * @var string
     *
     * @ORM\Column(name="content", type="text")
     */
    private $content; 

teraz tak wskazanie połączenia naszych jednostek ( myśląc jak o bycie tabeli ) czy klas, patrząc jak na język obiektowy
jest to

 /**
     * @ORM\ManyToOne(targetEntity="Category", inversedBy="articles")
     * @ORM\JoinColumn(name="category_id", referencedColumnName="id")
     */
    protected $category;

Dlatego mam pytanie czym jest to $category, czy jest to jednocześnie polem tabeli czy tylko abstrakcyjną reprezentacją połączeń dwóch relacji relacji
jak wskazuje komentarz, nie ma tam przecież wskazanego typu pola jak w poprzednich jest tylko wskanie na relację wiele do jednego i wskazane klasy/byty
i wskazanie na atrybut klasy łączonej czyli articles. Dalej jest łączenie kolumny i tego właśnie nie rozumiem dlaczego jest tam napisane category_id skoro w Category jest już tylko id
a w Article nie ma takiego atrybuty jak category_id ( w sumie powinno coś takiego być oczywiście ), natomiast reference column to jasne że id.

Teraz Article

    /**
     * @ORM\OneToMany(targetEntity="Article", mappedBy="category")
     */
    protected $articles;

Tu jest jasne wszystko po prostu wskazanie referencji dla odwrotnego działania choć nie rozumiem dlaczego nie ma wskazania konkretnego atrybutu, rozumiem, że może działać tutaj
silnik ale dlaczego w tamtym przypadku było inaczej ?
Kolejne pytanie co to jest

  /**
     * Add articles
     *
     * @param \AppBundle\Entity\Article $articles
     * @return Category
     */
    public function addArticle(\AppBundle\Entity\Article $articles)
    {
        $this->articles[] = $articles;
 
        return $this;
    }

Hmm, myślę sobie, że jest to jakieś przeładowanie innej metody gdzieś w silniku doctrine ale nie jestem pewien. Drugie pytanie co to jest articles[] i gdzie jest deklaracja
tej tablicy w klasie ? Jest tam w opisie dla dctrine opisane, że zwracane jest Category, ale przyznam, że jakoś nie rozumiem.

Czy może mi ktoś to jakoś opisać ? Przyznam, że staram się to zrozumieć ale być może ten framework jest dla mnie zbyt zawiły, przyznaje, że uczyłem się na innych językach
przyznam zdecydowanie prostszych frameworkach, a chciałbym cholera to zrozumieć i umieć odnieść się do elementów w mojej pamięc na zasadzie zrozumienia danego problemu.
Z góry dziękuje Wam za pomoc, zdaje sobie sprawę, że są tu już jacyś wyjadacze tylko nie wiem czy chętnie podzielą się wiedzą, a ja muszę powiedzieć, że niestety nie mam tyle
czasu aby zjeść na tym swoje zęby.
Panowie prośbą o jakieś wyjaśnienie sensowne. Chętnie się zrewanżuje ! Akurat mam takki projekt i chciałbym szybko jakąś wiedzę zyskać.

Dzięki i Pozdrawiam
P.

0
PiotroSan napisał(a):

Dlatego mam pytanie czym jest to $category, czy jest to jednocześnie polem tabeli czy tylko abstrakcyjną reprezentacją połączeń dwóch relacji relacji
jak wskazuje komentarz, nie ma tam przecież wskazanego typu pola jak w poprzednich jest tylko wskanie na relację wiele do jednego i wskazane klasy/byty
i wskazanie na atrybut klasy łączonej czyli articles. Dalej jest łączenie kolumny i tego właśnie nie rozumiem dlaczego jest tam napisane category_id skoro w Category jest już tylko id
a w Article nie ma takiego atrybuty jak category_id ( w sumie powinno coś takiego być oczywiście ), natomiast reference column to jasne że id.

$category to jest encja czyli odwzorowanie pola tabeli w obiekcie Doctrine. Używając Doctrine w pewnym sensie zapominasz o tabeli i działasz wyłącznie na jej obiektowym odwzorowaniu.
W ENCJI article masz ENCJE category i mozesz na tym zrobić wszystko co potrzeba w kodzie. A z komentarza można odczytać, że w tabeli article istnieje kolumna category_id która jest kluczem obcym odpowiadającym kolumnie id z tabeli category.

PiotroSan napisał(a):
  /**
     * @ORM\OneToMany(targetEntity="Article", mappedBy="category")
     */
    protected $articles;

Tu jest jasne wszystko po prostu wskazanie referencji dla odwrotnego działania choć nie rozumiem dlaczego nie ma wskazania konkretnego atrybutu, rozumiem, że może działać tutaj
silnik ale dlaczego w tamtym przypadku było inaczej ?

Wystarczy, że informacja jest w tamtym miejscu. Silnik to ogarnia. W encji Article jest już Category - jak sam napisałeś wcześniej to zostało zakodowane.

PiotroSan napisał(a):

Kolejne pytanie co to jest

  /**
     * Add articles
     *
     * @param \AppBundle\Entity\Article $articles
     * @return Category
     */
    public function addArticle(\AppBundle\Entity\Article $articles)
    {
        $this->articles[] = $articles;
 
        return $this;
    }

Hmm, myślę sobie, że jest to jakieś przeładowanie innej metody gdzieś w silniku doctrine ale nie jestem pewien. Drugie pytanie co to jest articles[] i gdzie jest deklaracja
tej tablicy w klasie ? Jest tam w opisie dla dctrine opisane, że zwracane jest Category, ale przyznam, że jakoś nie rozumiem.

/**
     * @ORM\OneToMany(targetEntity="Article", mappedBy="category")
     */
    protected $articles;

Tu jest deklaracja – jest to po prostu tablica artykułów w kategorii. Zwraca Category i w tym momencie możesz dodawać artykuły do kategorii pisząc:

$category->addArticle($article1)	
	->addArticle($article2)
	…..
	->addArticle($articleN);

Można to stosować w setterach i temu podobnych metodach. Więcej informacji – google: fluent interface.

Wiele rzeczy wyjdzie po prostu w praniu. Jak nie masz czasu to zrób na przykładzie i potem kombinuj jak Ci czegoś będzie brakować.

1 użytkowników online, w tym zalogowanych: 0, gości: 1