Foros del Web » Programando para Internet » PHP » Symfony »

Claves primarias compuestas (composite primary key)

Estas en el tema de Claves primarias compuestas (composite primary key) en el foro de Symfony en Foros del Web. Buenas tardes, de nuevo vengo con un problemilla que llevo un buen rato dándole vuelta. Lo mejor creo es pegar el código y ahora explico ...
  #1 (permalink)  
Antiguo 22/11/2014, 15:07
Avatar de Dundee  
Fecha de Ingreso: junio-2002
Ubicación: El Médano
Mensajes: 1.310
Antigüedad: 21 años, 9 meses
Puntos: 8
Claves primarias compuestas (composite primary key)

Buenas tardes, de nuevo vengo con un problemilla que llevo un buen rato dándole vuelta. Lo mejor creo es pegar el código y ahora explico cual es mi problema.

Tengo una entidad Branch.php

Código PHP:
<?php

namespace BranchMainBundleEntity
;

use 
DoctrineORMMapping as ORM;
use 
SymfonyComponentValidatorConstraints as Assert;

/**
 * Book
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="Branch\MainBundle\Entity\BranchRepository")
 */
class Branch {

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

  
/**
   * @var intenger
   * 
   * @ORM\Column(name="book_id", type="integer", nullable=false)
   * @ORM\Id
   * @ORM\ManyToOne(targetEntity="Book", inversedBy="Branch")
   * @ORM\JoinColumn(name="book_id", referencedColumnName="id")
   */
  
private $book_id;

  public function 
__construct($id$book_id) {
    
$this->id $id// The branch id.
    
$this->book_id $book_id// The book id.
  
}

  
/**
   * @var integer

   * @ORM\OneToOne(targetEntity="Branch")
   * @ORM\Column(type="integer")
   * @ORM\JoinColumn(name="parent_branch", referencedColumnName="id")
   */
  
private $parentBranch;

  
/**
   * @var string
   * @Assert\NotBlank()
   * @Assert\Length(
   *      min = 10,
   *      max = 500,
   *      minMessage = "Your phrase must be at least {{ limit }} characters long",
   *      maxMessage = "Your phrase cannot be longer than {{ limit }} characters long"
   * ) 
   * @ORM\Column(name="phrase", type="string", length=255)
   */
  
private $phrase;

  
/**
   * @var integer
   * @Assert\NotBlank()
   * @ORM\Column(name="creator_uid", type="integer")
   */
  
private $creatorUid;

  
/**
   * Get book_id
   *
   * @return \Branch\MainBundle\Entity\Book 
   */
  
public function getBookId() {
    return 
$this->book_id;
  }

  
/**
   * Set phrase
   *
   * @param string $phrase
   * @return Book
   */
  
public function setPhrase($phrase) {
    
$this->phrase $phrase;

    return 
$this;
  }

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

  
/**
   * Set parentBranch
   *
   * @param integer $parentBranch
   * @return Branch
   */
  
public function setParentBranch($parentBranch) {
    
$this->parentBranch $parentBranch;

    return 
$this;
  }

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

  
/**
   * Set creatorUid
   *
   * @param integer $creatorUid
   * @return Branch
   */
  
public function setCreatorUid($creatorUid) {
    
$this->creatorUid $creatorUid;

    return 
$this;
  }

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

  
/**
   * Set book_id
   *
   * @param \Branch\MainBundle\Entity\Book $bookId
   * @return Branch
   */
  
public function setBookId(BranchMainBundleEntityBook $bookId null) {
    
$this->book_id $bookId;

    return 
$this;
  }

  public function 
__toString() {
    return 
$this->phrase;
  }
Y lo que quiero es conseguir una clave primaria compuesta; en la bd he establecido dos campos como claves primarias id, y book_id (esto sería la id de branch+ la id de book). Algo debo hacer mal, porque obtengo un error.

Pongo también el controlador por si acaso.

DefaultController.php

Código PHP:
<?php

namespace BranchMainBundleController
;

use 
SymfonyBundleFrameworkBundleControllerController;
use 
BranchMainBundleEntityBranch;
use 
BranchMainBundleEntityBook;
use 
SymfonyComponentHttpFoundationRequest;
use 
SymfonyComponentHttpFoundationResponse;
use 
BranchMainBundleFormPhraseNewPhrase;
use 
BranchMainBundleFormBookNewBook;

// Custom messages.
use BranchMainBundleMessagesMessages;

class 
DefaultController extends Controller {


  public function 
createBranchAction(Request $request$book_id$parent_branch_id) {

    
$em $this->getDoctrine()->getManager();

    
// Parent branch.
    
$parent_branch $em->getRepository('BranchMainBundle:Branch')->find($parent_branch_id$book_id);

    
// Presist parent branch
    
$em->persist($parent_branch);

    
// Actual book 
    
$actual_book $em->getRepository('BranchMainBundle:Book')->find($book_id);
  
    
// Presist book
    
$em->persist($actual_book);




    
// Create new child branch.
    
$branch = new Branch();
    
$branch->setPhrase('Write a blog post');
    
$branch->setParentBranch($parent_branch);
    
$branch->setBookId($actual_book);
    
// $book->setDueDate(new \DateTime('tomorrow'));
    
$branch->setCreatorUid(1);
    
$form $this->createForm(new NewPhrase(), $branch);
    
$form->handleRequest($request);

    if (
$form->isValid()) {
      
// Save new branch in db.

      
$em $this->getDoctrine()->getManager();
      
$em->persist($branch);
      
$em->flush();

      
//return $this->redirect($this->generateUrl('task_success'));
      
$Message = new Messages;
      return 
$Message->successAction();
    }
    
// Default view.
    
return $this->render('BranchMainBundle:Default:new_branch.html.twig', array(
          
'form' => $form->createView(),
    ));
  }

  function 
createBookAction(Request $request) {

    
$book = New Book();

    
$book->setTitle('Inserta un título');
    
$book->setDescription('');
    
$book->setPublic(1);
    
$book->setOwner(1);

    
$em $this->getDoctrine()->getManager();
    
$em->persist($book);

    
$form $this->createForm(new NewBook(), $book);
    
$form->handleRequest($request);

    if (
$form->isValid()) {
      
// Save new book in db.

      
$em $this->getDoctrine()->getManager();
      
$em->persist($book);
      
$em->flush();
      
      return 
$this->redirect($this->generateUrl('task_success'));
    }
    
// Default view.
    
return $this->render('BranchMainBundle:Default:new_book.html.twig', array(
          
'form' => $form->createView(),
    ));
  }


}
El routing.yml sería este:
Código PHP:
book_main_homepage:
    
path:     /books/{book}
    
defaults: { _controllerBranchMainBundle:Default:indexbook}
    
book_create_branch:
    
path:     /create-branch/{book_id}/{parent_branch_id}
    
defaults: { _controllerBranchMainBundle:Default:createBranchbook_id1parent_branch_id 1
    
book_create_book:
    
path:     /create-book
    defaults
: { _controllerBranchMainBundle:Default:createBook
    
task_success:
    
path: /success
    defaults
: { _controllerBranchMainBundle:Default:success 
__________________
Videotutoriales de Drupal
  #2 (permalink)  
Antiguo 23/11/2014, 06:23
Avatar de Dundee  
Fecha de Ingreso: junio-2002
Ubicación: El Médano
Mensajes: 1.310
Antigüedad: 21 años, 9 meses
Puntos: 8
Respuesta: Claves primarias compuestas (composite primary key)

Bueno parece que he conseguido lo que quería pero a medias, como decía mi clave primaria la forman la Id y el BookId; pero al aplicar el método find de este modo:

Código PHP:
    // Parent branch. // $parent_branch_id is really the branch id.
   
$parent_branch $em->getRepository('BranchMainBundle:Branch')->find(array(
     
'id' => $parent_branch_id
     
'book_id' => $book_id
       
)); 
Obtengo este error que no entiendo.
Código PHP:
WarningMissing argument 1 for BranchMainBundleEntityBranch::__construct(), called in /var/www/html/piramidal/src/Branch/MainBundle/Controller/DefaultController.php on line 79 and defined in /var/www/html/piramidal/src/Branch/MainBundle/Entity/Branch.php line 34 
El método en cuestión __contruct() es simplemente esto: (no pego el resto de código setter y getters porque ya lo he puesto antes).

Código PHP:
  /**
   * @var integer
   *
   * @ORM\Column(name="id", type="integer", nullable=false)
   * @ORM\Id
   * @ORM\Column(type="integer")
   */
  
private $id;

  
/**
   * @var intenger
   * 
   * @ORM\Column(name="book_id", type="integer", nullable=false)
   * @ORM\Id
   * @ORM\ManyToOne(targetEntity="Book", inversedBy="Branch")
   */
  
private $book_id;

  public function 
__construct($id$book_id) {
    
$this->id $id// The branch id.
    
$this->book_id $book_id// The book id.
  

Estoy revisando esto, pero no consigo que me funcione, y creo que lo tengo igual.
Esta clarísimo que el problema esta al llamar al __contruct, ya que si le meto datos por defecto a los parámetro , si funciona:
Código PHP:
  public function __construct($id 1$book_id 1) {
    
$this->id $id// The branch id.
    
$this->book_id $book_id// The book id.
  

¿El método find no crea a su vez el objeto?. He probado creando el objeto sin usar find, pero obtengo el mismo error de __construct().
Código:
Warning: Missing argument 1 for Branch\MainBundle\Entity\Branch::__construct(), called in /var/www/html/piramidal/src/Branch/MainBundle/Controller/DefaultController.php on line 69 and defined in /var/www/html/piramidal/src/Branch/MainBundle/Entity/Branch.php line 33
Código PHP:
$parent_branch = new Branch(1,1); 
Bueno sigo probando cositas como esto:
Código PHP:
$parent_branch = new Branch(array( 'id' => 1'book_id' => 1)); 
Pero el resultado es el mismo error del __construct()
¿Alguna idea?.
Gracias de antemano.
__________________
Videotutoriales de Drupal

Última edición por Dundee; 23/11/2014 a las 06:44
  #3 (permalink)  
Antiguo 23/11/2014, 06:51
Avatar de Dundee  
Fecha de Ingreso: junio-2002
Ubicación: El Médano
Mensajes: 1.310
Antigüedad: 21 años, 9 meses
Puntos: 8
Respuesta: Claves primarias compuestas (composite primary key)

He agregado
* @ORM\GeneratedValue(strategy="AUTO")
a la propiedad Id.
Código PHP:
  /**
   * @var integer
   *
   * @ORM\Column(name="id", type="integer", nullable=false)
   * @ORM\GeneratedValue(strategy="AUTO")
   * @ORM\Id
   */
  
private $id
Y ahora tengo otro error
Código:
Single id is not allowed on composite primary key in entity Branch\MainBundle\Entity\Branch
500 Internal Server Error - MappingException
__________________
Videotutoriales de Drupal
  #4 (permalink)  
Antiguo 23/11/2014, 15:21
Avatar de hhs
hhs
Colaborador
 
Fecha de Ingreso: junio-2013
Ubicación: México
Mensajes: 2.995
Antigüedad: 10 años, 9 meses
Puntos: 379
Respuesta: Claves primarias compuestas (composite primary key)

Lo errores del constructor son debido a que create una clave primaria compuesta asi que necesitas pasarle los valores correpondiente en el constructor:
Código PHP:
Ver original
  1. // Create new child branch.
  2.    $branch = new Branch();
No puedes hacer esto de arriba. Necesitas crear la logica necesaria para que tu constructor
Código PHP:
Ver original
  1. public function __construct($id = null, $book_id = null) {
  2.     $this->id = $id; // The branch id.
  3.     $this->book_id = $book_id; // The book id.
  4.   }
Me temo que el ultimo error es por que declaras la generación automatica y doctrine considera que estas creando un PK de una sola columna.
Supongo que todo esto es por que estas haciendo pruebas, si es asi, mejor realizar primero pruebas de unidad y luego pruebas funcionales.
__________________
Saludos
About me
Laraveles
A class should have only one reason to change.
  #5 (permalink)  
Antiguo 23/11/2014, 16:29
Avatar de Dundee  
Fecha de Ingreso: junio-2002
Ubicación: El Médano
Mensajes: 1.310
Antigüedad: 21 años, 9 meses
Puntos: 8
Respuesta: Claves primarias compuestas (composite primary key)

Cita:
Iniciado por hhs Ver Mensaje
Lo errores del constructor son debido a que create una clave primaria compuesta asi que necesitas pasarle los valores correpondiente en el constructor:
Código PHP:
Ver original
  1. // Create new child branch.
  2.    $branch = new Branch();
¿Entonces como hago cuando creo una nueva rama que no tiene Id (por que aun no existe) y tiene que generarla con autoincrement?.
Además cuando busco parent, también me da error, lo hago así, y según he visto en varios ejemplos se debe hacer así:
Ojo parent si tiene id y book_id, ya que es un rama existente, por eso le paso los dos valores, por lo que no se por qué peta.
Código PHP:
  $parent_branch $em->getRepository('BranchMainBundle:Branch')->find(array(
     
'id' => $parent_branch_id
     
'book_id' => $book_id
       
)); 
Pero siempre me tira un error como este:
Código PHP:
  Single id is not allowed on composite primary key in entity BranchMainBundleEntityBranch 
Cita:
Iniciado por hhs Ver Mensaje
No puedes hacer esto de arriba. Necesitas crear la logica necesaria para que tu constructor
Código PHP:
Ver original
  1. public function __construct($id = null, $book_id = null) {
  2.     $this->id = $id; // The branch id.
  3.     $this->book_id = $book_id; // The book id.
  4.   }


Me temo que el ultimo error es por que declaras la generación automatica y doctrine considera que estas creando un PK de una sola columna.
Supongo que todo esto es por que estas haciendo pruebas, si es asi, mejor realizar primero pruebas de unidad y luego pruebas funcionales.
No entiendo eso que dices, ¿no puedo hacer exactamente que?, si al crear el objeto envío dos argumentos, el contructor recibe dos argumentos, es lógica que le pase dos al crear el objeto no?. Lo de null ha sido para probar sismplemente , si lo quito obtengo también un error.

Ahora si que me siento un poco confundido con esto, hasta ahora toda había sido relativamente sencillo, pero ya me tocaba sufrir supongo jeje.

Gracias de antemano.
__________________
Videotutoriales de Drupal

Etiquetas: claves, key, primary
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 12:14.