How to store priority in a Many-to-Many relationship with Doctrine 2.0 - orm

My problem is simple:
I have Users and Stories in a many to many relationship, I would like to store a couple of attribute in the UserStory relationship:
Priority (In order to set the ordering of the display for a given user)
Main (flags which one is the main story)
How can I do that ?
Let say we have the following :
<?php
/** #Entity */
class User
{
// ...
/**
* #ManyToMany(targetEntity="Story", inversedBy="users")
* #JoinTable(name="users_stories")
*/
private $stories;
public function __construct() {
$this->stories = new \Doctrine\Common\Collections\ArrayCollection();
}
// ...
}
/** #Entity */
class Story
{
// ...
/**
* #ManyToMany(targetEntity="User", mappedBy="stories")
*/
private $users;
public function __construct() {
$this->users = new \Doctrine\Common\Collections\ArrayCollection();
}
// ...
}
?>

As Crozin suggested, this question is a duplicate of:
Doctrine2: Best way to handle many-to-many with extra columns in reference table
In my specific case the solution is simple. The Many-To-Many relationship needs to be build by hand, and extra fields need to be added manually. So two OneToMany relationship need to be build.
So here are my 3 objects and the associated meta information for each attribute:
<?php
/**
* #Entity
* #Table(name="users")
*/
class User{
/**
* #Id
* #Column(type="integer", name="id")
* #GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #OneToMany(targetEntity="UserStory", mappedBy="user")
*/
private $user_stories;
// ...
}
/**
* #Entity
* #Table(name="user_stories")
*/
class UserStory{
/**
* #Id
* #Column(type="integer", name="id")
* #GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #ManyToOne(targetEntity="User", inversedBy="user_stories")
*/
private $user;
/**
* #ManyToOne(targetEntity="Story", inversedBy="user_stories")
*/
private $stories;
/**
* #Column(type="integer")
*/
private $priority;
/**
* #Column(type="integer")
*/
private $priority_tmp;
/**
* #Column(type="integer")
*/
private $main;
// ...
}
/**
* #Entity
* #Table(name="stories")
*/
class Story
{
/**
* #Id
* #Column(type="integer", name="id")
* #GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #OneToMany(targetEntity="UserStory", mappedBy="stories")
*/
private $user_stories;
// ...
}
?>

Related

Doctrine Abstract - Concrete class ORM

I'm working with doctrine for the mapping of some objects to database tables.
This is what I have now:
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="account")
*/
abstract class Account{
/**
* #ORM\Id
* #ORM\Column(type="string")
*/
private $username;
/**
* #ORM\Id
* #ORM\Column(type="string")
*/
private $password;
/*Getters and setters*/
}
/**
* #ORM\Entity
* #ORM\Table(name="player")
*/
abstract class Player extends Account{
/**
* #ORM\Id
* #ORM\Column(type="integer")
*/
private $number;
/*Getters and setters*/
}
/**
* #ORM\Entity
* #ORM\Table(name="coach")
*/
abstract class Coach extends Account{
/**
* #ORM\Id
* #ORM\Column(type="integer")
*/
private $experience;
/*Getters and setters*/
}
This way, all concrete classes will have the username and the password column, what if I would need to store only the username in order to be able to join them later and get the oconcrete object back? Thanks in advance.
What you want is then possibly Class Table Inheritance as described in http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/inheritance-mapping.html#class-table-inheritance
namespace MyProject\Model;
/**
* #Entity
* #InheritanceType("JOINED")
* #DiscriminatorColumn(name="discr", type="string")
* #DiscriminatorMap({"player" = "Player", "coach" = "Coach"})
*/
abstract class Account
{
// ...
}
/** #Entity */
class Player extends Account
{
// ...
}
/** #Entity */
class Coach extends Account
{
// ...
}
This should create 3 tables Account, Player and Coach, though Account alone cannot be persisted, rather it will have a discriminator column + ID to link to. So, e.g. 'coach' '3' will join to Coach object with id 3.
First Answer:
If I understood you correctly and the password doesn't need to be provided directly, you can add to the $password annotation
* #ORM\Column(type="string", nullable=true)
Is this what you had in mind?

Doctrine 2 get items from related entities

I have an entity with ManyToOne, OneToOne relations. I have another entity, which is linked to the first one and what I want to do is to get information about the first entity as well as all other entities, which are related to it.
For some reason when I make the call, it returns NULL in the related entity.
Code:
<?php
namespace App\Model\Entities;
use Doctrine\ORM\Mapping as ORM,
Doctrine\Common\Collections\ArrayCollection;
use Kdyby\Doctrine\Entities\BaseEntity;
/**
* Doctrine entity for resorts in destinations
* #package App\Model\Entities
* #ORM\Entity
*/
class Resort extends BaseEntity
{
/**
* autoincremented resort id
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue
*/
protected $id;
/**
* resort name
* #ORM\Column(type="string")
*/
protected $title;
/**
* #ORM\OneToOne(targetEntity="ResortProperties", mappedBy="resort", cascade={"persist"})
*/
private $properties;
public function __construct()
{
$this->properties = new ArrayCollection();
}
/**
* HERE I WANT TO GET DATA FROM ANOTHER ENTITY
* #return type
*/
public function getProperties()
{
return $this->properties;
}
}
And the related entity is this:
<?php
namespace App\Model\Entities;
use Doctrine\ORM\Mapping as ORM,
Doctrine\Common\Collections\ArrayCollection;
use Kdyby\Doctrine\Entities\BaseEntity;
/**
* Doctrine entity for resort properties
* #package App\Model\Entities
* #ORM\Entity
*/
class ResortProperties extends BaseEntity
{
/**
* autoincremented id
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue
*/
protected $id;
/**
* resort id
* #ORM\OneToOne(targetEntity="Resort", inversedBy="Resort", cascade={"persist", "remove"})
* #ORM\JoinColumn(onDelete="CASCADE")
*/
protected $resort;
/**
* parameter1
* #ORM\Column(type="string")
*/
protected $parameter1;
}
I expected, that when I call $repository->findAll(); I would get all Resort entities and in Resort->properties would be joined ResortProperty entity, but it is NULL.
I don't know what I did wrong, can someone point out my mistake? Thanks
I assume the problem is the JoinColumn-Annotation.
The Entity with the Foreign-key (ResortProperties) needs to know, how to join the two tables.
The "inversedBy"-Statement on the Resort-Entity then uses this rule.
It should look something like the following in your ResortProperties-Entity:
/**
* resort id
* #ORM\OneToOne(targetEntity="Resort", inversedBy="Resort", cascade={"persist", "remove"})
* #ORM\JoinColumn(name="resort_id", referencedColumnName="id")
*/
protected $resort;
"resort_id" is the name of your foreign-key-column.
Hope this helps.
In ResortProperties entity I had to make this change:
class ResortProperties extends BaseEntity
{
/**
* resort id
* #ORM\OneToOne(targetEntity="Resort", inversedBy="properties", cascade={"persist", "remove"})
* #ORM\JoinColumn(name="resort_id", referencedColumnName="id", onDelete="CASCADE")
*/
protected $resort;
}
And in Resort entity I had to change it like this:
class Resort extends BaseEntity
{
/**
* #ORM\OneToOne(targetEntity="ResortProperties", mappedBy="resort", cascade={"persist"})
*/
private $properties;
public function __construct()
{
parent::__construct();
$this->properties = new ArrayCollection();
}
}
Now it's working properly, hope this will help others

Laravel "auth controller not found" exception

I am making admin panel in LARAVEL4.2.*. I make the controller in "admin" folder and also a view in views "admin" folder. My controller code is
namespace admin;
class AuthController extends \BaseController {
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index()
{
//
}
/**
* Show the form for creating a new resource.
*
* #return Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* #return Response
*/
public function store()
{
//
}
/**
* Display the specified resource.
*
* #param int $id
* #return Response
*/
public function show($id)
{
//
}
/**
* Show the form for editing the specified resource.
*
* #param int $id
* #return Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* #param int $id
* #return Response
*/
public function update($id)
{
//
}
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return Response
*/
public function destroy($id)
{
//
}
}
and my routes coding is:
Route::get('admin/login', array('as' => 'admin.login', 'uses' => 'App\Controllers\Admin\AuthController#getLogin'));
I have also tried "composer update" and "composer dump-autoload" above 50 times. My url is localhost/laraveltest/public/admin/login.
You defined your namespace as admin, therefore you have to use this also in your routes:
Route::get('admin/login', array('uses' => '\admin\AuthController#getLogin'));

DQL query in Symfony for ManyToOne unidirectional relationship

class MenuItem
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\ManyToOne(targetEntity="MenuCategory")
* #ORM\JoinColumn(name="menu_id", referencedColumnName="id")
*/
protected $catagory;
}
Category class
class MenuCategory
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="string")
*/
protected $name;
/**
* #ORM\Column(type="integer")
*/
protectted $ordering;
}
I want to query all of the items ordered by the ordering property in the category. Here is my query that I tried. I am new to SQL/DQL and am not sure how to access the ordering property in the query. This query is the the MenuItemRepository.php file.
class MenuItemRepository extends EntityRepository
{
public function getOrderedMenu()
{
return $this->createQueryBuilder('i')
->select('i')
->orderBy('i.catagory.ordering', 'ASC') //????
->getQuery()
->getResult()
}
}
Is there a way to get all the items orderedBy ordering?
You have cat a gory in your orderBy clause instead of cat e gory!
Further protectted instead of protected in front of your $ordering property.
The following should work:
return $this->createQueryBuilder('i')
->leftJoin('i.category', 'c')
->orderBy('c.ordering', 'ASC')
->getQuery()
->getResult();

doctrine entity with foreign key to this entity

I have a simple table for recursive categories:
id
name
parent_id - is a link to id, NULL - for root categories
I need to create a table with foreign key. My class doesn't create this key. How can I change this class to create table with foreign key using "doctrine:schema:create"? What I have tried:
<?php
namespace Test\BackEndBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="category")
*/
class Category
{
/**
* #ORM\Id
* #ORM\Column(type="bigint", length=20)
* #ORM\GeneratedValue(strategy="AUTO")
* #var int
*/
protected $id;
/**
* #ORM\Column(type="string", length="255")
* #var string
*/
protected $name;
/**
* #ORM\Column(name="parent_id", type="bigint", length=20, nullable="true")
* #ORM\OneToMany(targetEntity="Category")
* #ORM\JoinColumn(name="id", onDelete="CASCADE", onUpdate="CASCADE")
* #var int
*/
protected $parentId;
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
*/
public function setName($name)
{
$this->name = $name;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
}
You reversed OneToMany with ManyToOne !
See here: http://docs.doctrine-project.org/en/2.0.x/reference/association-mapping.html#one-to-many-self-referencing
In fact, you want that plural subcategories can have one parent cat !
What you need:
/**
* #OneToMany(targetEntity="Category", mappedBy="parent")
*/
private $children;
/**
* #ManyToOne(targetEntity="Category", inversedBy="children")
* #JoinColumn(name="parent_id", referencedColumnName="id")
*/
private $parent;
// ...
public function __construct() {
$this->children = new \Doctrine\Common\Collections\ArrayCollection();
}
You can replace $parent for $parentId (and mappedBy="parent" for mappedBy="parentId"), but this is not a good coding convention ^^