1
\$\begingroup\$

I've a working implementation in Symfony2 with doctrine of the following model. enter image description here

  • A Parent can apply for one/more Training(s)
  • A Training is based on a specific Skill, but you can have multiple trainings at different dates for the same skill.
  • Once a Parent attends the training he can be marked as 'qualified' for the Skill related to the Training taken and becomes a Trainee.
  • A Parent can attend multiple Training on the same Skill but will only marked 'qualified' only once for the given Skill.
  • The Trainee can be 'qualified' on multiple Skills

The Inheritance and Association (one to one) between Parents and Trainee has been implemented using a single table inheritance as seen below:

    Parents\ParentsBundle\Entity\Parents:
type: entity
inheritanceType: SINGLE_TABLE
discriminatorColumn:
    name: type
    type: string
discriminatorMap:
     parents: Parents
     trainee: Parents\TraineeBundle\Entity\Trainee
table: Parents
repositoryClass: Parents\ParentsBundle\Repository\ParentsRepository
id:
    id:
        type: integer
        generator:
            strategy: AUTO
fields:
    firstname:
        type: string
        length: 250
    lastname:
        type: string
        length: 250
    dob:
        type: date
        nullable: true
lifecycleCallbacks:
    prePersist: [ setDateDeCreationValue ]
manyToMany:
    trainings:
        targetEntity: Training\TrainingBundle\Entity\Training
        mappedBy: parents
        orphanRemoval: true
        cascade: ["all"]
oneToOne:
    trainee:
        targetEntity: Parents\TraineeBundle\Entity\Trainee
        inversedBy: parents
        cascade:  ["all"]
        joinColumns:
            trainee_id:
                referencedColumnName: id
indexes:
    nom_prenoms_idx:
        columns: [ firstname, lastname ]


Parents\TraineeBundle\Entity\Trainee:
    type: entity
    extends: Parents\ParentsBundle\Entity\Parents
    repositoryClass: Parents\TraineeBundle\Repository\TraineeRepository
    manyToMany:
            skills:
                targetEntity: Training\SkillBundle\Entity\Skill
                mappedBy: trainees
    oneToOne:
            parents:
                targetEntity: Parents\ParentsBundle\Entity\Parents
                mappedBy: trainee

Trianing\SkillBundle\Entity\Skill:
    type: entity
    table: Skill
    repositoryClass: Training\SkillBundle\Repository\SkillRepository
    id:
        id:
            type: integer
            generator:
                strategy: auto
    fields:
        title:
            type: string
            length: 80
            unique: true
        description:
            type: string
            length: 250
            nullable: true
    manyToMany:
        trainees:
            targetEntity: Parents\TraineeBundle\Entity\Trainee
            inversedBy: skills
            cascade: ["all"]
            joinTable:
                name: trainess_skills
                joinColumns:
                    skill_id:
                        referencedColumnName: id
                        nullable: false
                        onDelete: CASCADE
                inverseJoinColumns:
                    trainee_id:
                        referencedColumnName: id
                        nullable: false
    uniqueConstraints:
        titre_UNIQUE:
            columns:
                - titre

Below is the form type and controller functions used to store and associate a Parent and a Trainee:

    public function buildForm(FormBuilderInterface $builder, array $options)
            {
                $builder
                    ->add('title', 'text', array('disabled' => 'true'))
                    ->add('parents', 'entity', array('label' => 'List attendees',
                                                    'expanded' => true, 'multiple' => true,
                                                    'mapped'=>false,'class' => 'ParentsBundle:Parents'
                                                    ,'query_builder' => function (EntityRepository $er) use ($options){
                            return $er->getParentsByTraining($options['training_id']);
                        }   ))
                ;

            }
public function qualifyAction(Request $request, $id)
        {
            $em = $this->getDoctrine()->getManager();
            $entity = $em->getRepository('TraiiningBundle:Training')->find($id);

            $qualifiyForm = $this->createQualificationForm($entity);
            $qualifiyForm->handleRequest($request);

            if ($qualifiyForm->isValid() && $qualifiyForm->isSubmitted()) {
                $parents = $qualifiyForm->get('parents')->getData();
                $skill = $entity->getSkill();
                foreach ($parents as $parent) {
                    if ($parent->getTrainee()) {
                        $trainee = $parent->getTrainee();
                        $skill->addTrainee($trainee);
                    } else {
                        $trainee = $this->getTrainee($parent);
                        $skill->addTrainee($trainee);
                        $parent->setTrainee($trainee);
                    }

                }
                $em->persist($skill);
                $em->flush();
                $this->get('session')->getFlashBag()->add('success', 'Changes recorded');
                return $this->redirect($this->generateUrl('/'));
            }
            return $this->render('TrainingBundle:Training:qualifyCandidates.html.twig',
                array(
                    'entity' => $entity,
                    'qualifiyForm' => $qualifiyForm->createView())
            );
        }
public function getTrainee(Parents $parent)
        {
            $trainee = new Trainee();
            $trainee->setFirstName($parent->getFirstName());
            $trainee->setLastName($parent->getLastName());
            $trainee->setEmail($parent->getEmail());
            $trainee->setDOB($parent->getDOB());
            return $trainee;
        }

I'll be glad to haave comments on improvement that can be made to this model

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.