Symfony 1.4/ Doctrine; n-m relation data cannot be

2019-07-23 17:19发布

I have a database with 3 tables. It's a simple n-m relationship. Student, Course and StudentHasCourse to handle n-m relationship. I post the schema.yml for reference, but it would not be really necessary.

Course:
  connection: doctrine
  tableName: course
  columns:
    id:
      type: integer(4)
      fixed: false
      unsigned: false
      primary: true
      autoincrement: false
    name:
      type: string(45)
      fixed: false
      unsigned: false
      primary: false
      notnull: false
      autoincrement: false
  relations:
    StudentHasCourse:
      local: id
      foreign: course_id
      type: many

Student:
  connection: doctrine
  tableName: student
  columns:
    id:
      type: integer(4)
      fixed: false
      unsigned: false
      primary: true
      autoincrement: false
    registration_details:
      type: string(45)
      fixed: false
      unsigned: false
      primary: false
      notnull: false
      autoincrement: false
    name:
      type: string(30)
      fixed: false
      unsigned: false
      primary: false
      notnull: false
      autoincrement: false
  relations:
    StudentHasCourse:
      local: id
      foreign: student_id
      type: many

StudentHasCourse:
  connection: doctrine
  tableName: student_has_course
  columns:
    student_id:
      type: integer(4)
      fixed: false
      unsigned: false
      primary: true
      autoincrement: false
    course_id:
      type: integer(4)
      fixed: false
      unsigned: false
      primary: true
      autoincrement: false
    result:
      type: string(1)
      fixed: true
      unsigned: false
      primary: false
      notnull: false
      autoincrement: false
  relations:
    Course:
      local: course_id
      foreign: id
      type: one
    Student:
      local: student_id
      foreign: id
      type: one

Then, I get data from tables in executeIndex() from the following query.

  $q_info = Doctrine_Query::create()
   ->select('s.*, shc.*, c.*')
   ->from('Student s')
   ->leftJoin('s.StudentHasCourse shc')
   ->leftJoin('shc.Course c')
   ->where('c.id = 1');
  $this->infos = $q_info->execute();

Then I access data by looping through in indexSuccess.php. But, in indexSuccess I can only access data from the table Student.

<?php foreach ($infos as $info): ?>
  <?php echo $info->getId(); ?>
  <?php echo $info->getName(); ?>
<?php endforeach; ?>

I expected, that I could access StudentHasCourse data and Course data like the following. But, it generates an error.

<?php echo $info->getStudentHasCourse()->getResult()?>
<?php echo $info->getStudentHasCourse()->getCourse()->getName()?>

The first statement gives a warning;

Warning: call_user_func_array() expects parameter 1 to be a valid callback, class 'Doctrine_Collection' does not have a method 'getCourse' in D:\wamp\bin\php\php5.3.5\PEAR\pear\symfony\escaper\sfOutputEscaperObjectDecorator.class.php on line 64

And the second statement gives the above warning and the following error;

Fatal error: Call to a member function getName() on a non-object in D:\wamp\www\sam\test_doc_1\apps\frontend\modules\registration\templates\indexSuccess.php on line 5

When I check the query from the Debug toolbar it appears as following and it gives all data I want.

SELECT s.id AS s__id, s.registration_details AS s__registration_details, s.name AS s__name, s2.student_id AS s2__student_id, s2.course_id AS s2__course_id, s2.result AS s2__result, c.id AS c__id, c.name AS c__name 
FROM student s LEFT JOIN student_has_course s2 ON s.id = s2.student_id LEFT JOIN course c ON s2.course_id = c.id 
WHERE (c.id = 1)

Though the question is short, as all the information mentioned it became so long. It's highly appreciated if someone can help me out to solve this. What I require is to access the data from StudentHasCourse and Course. If those data cannot be accessed by this design and this query, any other methodology is also appreciated.

1条回答
做个烂人
2楼-- · 2019-07-23 17:54

The problem lies in the fact that you didn't define an n-m relationship, but two 1-n relationships. This is quite equivalent from a database point of view, but from the application point of view, you are getting 4 methods that do not have much semantic value, when you could get two easy-to-use methods : Student::getCourses() and Course::getStudents()

Read this § of the doctrine1.2 documentation to learn how to achieve this. StudentHasCourse should be used as your refClass

UPDATE I just understood you were storing the result in StudentHasCourse To get what you want, try something like this in your controller:

$this->courses = CourseTable::getInstance()
  ->createQuery('c')
    ->innerJoin('c.StudentHasCourse shc')
        ->where('shc.student_id = ?', $student_id)
        ->execute();

This means you still need the StudentHasCourse relation in the Course class. Recover it if you deleted it.

Now you should be able to do something like this in your template

<ul>
<?php foreach($courses as $course): ?>
  <li><?php echo $course //implement __toString in Course ?> : <?php echo $course->getStudentHasCourse()->getFirst()->getResult(); ?></li>
<?php endforeach;?>
</ul>
查看更多
登录 后发表回答