2

我一直在研究ATK的学生注册示例/教程,并且一直坚持通过链接表使用 ref()。

系统的基本 ER 如下:

[Student] ||---|< [class_has_student] >|---|| [class]  >|----|| [subject]

主题存储主题名称、主题代码、可以运行的学期以及描述的位置。课程是在给定时期内针对给定主题提供给学生的讲座/教程。学生可以注册一个班级,并且关系存储在 class_has_student 表中。

对于基本示例,我希望显示特定学生的详细信息并显示他们注册的课程(带有学科名称)。我正在使用视图模板来显示学生详细信息(姓名等)和任何课程(带有学科名称) 他们使用 Lister 类注册。主要问题是在尝试列出特定学生注册的科目时使用:

$student_detail= $student->ref('ClassHasStudent2')->ref('class_idclass')

它不是检索学生注册的所有科目,而是从数据库中检索所有科目。

请参阅下面的页面、模型和此示例的模板代码,以及修改后的 Table.php 类以使其工作(对不起,长度)。

谢谢你的帮助。

楷模

“类”表

+-------------------+---------+------+-----+---------+----------------+
| Field             | Type    | Null | Key | Default | Extra          |
+-------------------+---------+------+-----+---------+----------------+
| idclass           | int(11) | NO   | PRI | NULL    | auto_increment |
| subject_idsubject | int(11) | NO   | MUL | NULL    |                |
| date_start        | date    | YES  |     | NULL    |                |
| date_end          | date    | YES  |     | NULL    |                |
| max_students      | int(11) | YES  |     | NULL    |                |
+-------------------+---------+------+-----+---------+----------------+

select * from class;
+---------+-------------------+------------+------------+--------------+
| idclass | subject_idsubject | date_start | date_end   | max_students |
+---------+-------------------+------------+------------+--------------+
|       1 |                 2 | 2012-09-10 | 2012-09-30 |           10 |
|       2 |                 1 | 2012-09-08 | 2012-09-30 |           30 |
|       3 |                 3 | 2012-10-01 | 2012-10-31 |           35 |
|       4 |                 2 | 2012-09-19 | 2012-09-29 |           10 |
+---------+-------------------+------------+------------+--------------+

类.php

<?php

class Model_Class extends Model_Table {
    public $table='class';
    public $entity_code='class';
public $id_field='idclass';

    function init(){
        parent::init();
    $this->hasOne('Subject','subject_idsubject','name', 'subject_name');
    $this->addField('date_start')->type('date')->caption('Start');
    $this->addField('date_end')->type('date')->caption('End');
    $this->addField('max_students')->type('int');

    $this->hasMany('ClassHasStudent','class_idclass', 'idclass');
    }
}

“学生”表

+------------+-------------+------+-----+---------+----------------+
| Field      | Type        | Null | Key | Default | Extra          |
+------------+-------------+------+-----+---------+----------------+
| idstudent  | int(11)     | NO   | PRI | NULL    | auto_increment |
| student_id | varchar(45) | NO   |     | NULL    |                |
| name       | varchar(45) | NO   |     | NULL    |                |
+------------+-------------+------+-----+---------+----------------+

select * from student;
+-----------+------------+--------+
| idstudent | student_id | name   |
+-----------+------------+--------+
|         1 | T123       | Tom    |
|         2 | L222       | Lizley |
|         3 | B123       | Betty  |
|         4 | H33        | Homer  |
|         5 | N42        | Nick   |
+-----------+------------+--------+

学生.php

  <?php
  class Model_Student extends Model_Table {
      public $table='student';
      public $entity_code='student';
      public $id_field='idstudent';
      public $title_field='name';

      function init(){
          parent::init();

          $this->addField('student_id')->caption('Student ID');
          $this->addField('name')->caption('Name');
          $this->hasMany('ClassHasStudent', 'student_idstudent', 'idstudent');
      }
  }

Mysql“class_has_student”表

  +---------------------+-------------+------+-----+---------+----------------+
  | Field               | Type        | Null | Key | Default | Extra          |
  +---------------------+-------------+------+-----+---------+----------------+
  | idclass_has_student | int(11)     | NO   | PRI | NULL    | auto_increment |
  | class_idclass       | int(11)     | NO   | MUL | NULL    |                |
  | student_idstudent   | int(11)     | NO   | MUL | NULL    |                |
  | date_enrolled       | varchar(45) | YES  |     | NULL    |                |
  | grade               | double      | YES  |     | NULL    |                |
  +---------------------+-------------+------+-----+---------+----------------+

  select * from class_has_student;
  +---------------------+---------------+-------------------+---------------+-------+
  | idclass_has_student | class_idclass | student_idstudent | date_enrolled | grade |
  +---------------------+---------------+-------------------+---------------+-------+
  |                   1 |             1 |                 1 | 2012-09-04    |     0 |
  |                   2 |             1 |                 2 | 2012-09-11    |     0 |
  |                   3 |             2 |                 1 | 2012-09-14    |     0 |
  +---------------------+---------------+-------------------+---------------+-------+

classhasstudent.php

  <?php
  class Model_ClassHasStudent extends Model_Table {
      public $table='class_has_student';
      public $entity_code='class_has_student';
      public $id_field='idclass_has_student';

      function init(){
          parent::init();

      $this->hasOne('Class','class_idclass','idclass', 'class_name');
          $this->hasOne('Student', 'student_idstudent', 'name', 'student_name');
      $this->addField('date_enrolled')->type('date');
      $this->addField('grade');

      }

  }

mysql“主题”表

  +--------------+-------------+------+-----+---------+----------------+
  | Field        | Type        | Null | Key | Default | Extra          |
  +--------------+-------------+------+-----+---------+----------------+
  | idsubject    | int(11)     | NO   | PRI | NULL    | auto_increment |
  | name         | varchar(45) | YES  |     | NULL    |                |
  | subject_code | varchar(45) | YES  |     | NULL    |                |
  | semester     | varchar(45) | YES  |     | NULL    |                |
  | description  | blob        | YES  |     | NULL    |                |
  +--------------+-------------+------+-----+---------+----------------+

  select * from subject;
  +-----------+-----------+--------------+----------+--------------------------+
  | idsubject | name      | subject_code | semester | description              |
  +-----------+-----------+--------------+----------+--------------------------+
  |         1 | Maths     | mat101       | 1        | Mathematics and numbers. |
  |         2 | English   | enh101       | 1        | English and languages.   |
  |         3 | Chemistry | chm101       | 2        | Inorganic chemistry.     |
  +-----------+-----------+--------------+----------+--------------------------+

主题.php

  <?php

  class Model_Subject extends Model_Table {
      public $entity_code='subject';
  public $id_field='idsubject';


      function init(){
          parent::init();

      $this->addField('name');
      $this->addField('subject_code');
      $this->addField('semester');
      $this->addField('description');

      }

  }

李斯特

  <?php
  // Lister class for displaying classes that a student attends.
  class StudentClasses extends Lister {

      function init(){
          parent::init();
      }

      // Override defaultTemplate function.
      function defaultTemplate(){
          return array('view/class_info');
      }
  }

模板

/templates/default/view/student_details.html

  <div id="<?$_name?>" class="projectinfo">

      <table class="student">
      <tr><td id="property">Student Name</td><td id="value"> <?$name?> </td></tr>
      <tr><td id="property">Student ID</td> <td id="value"><?$student_id?></td></tr>
      </table>


  </div>

  <h2>Enrolled classes</h2>
  <?ClassList?>
  <?/?>

/templates/default/view/class_info.html

  <dl id="<?$_name?>" class="<?$class?>">
<dt><?$subject_name?></dt>
<dd><?$date_start?></dd><dd><?$date_start?></dd>
  </dl>

页面

<?php

class page_TestClasses extends Page {
    function init() {
        parent::init();

        $this->api->auth->check();
        $this->api->stickyGET('id');

    }

    // Called only once.
    function initMainPage(){


        $view=$this->add('View',null,null,array('view/student_details'));

//      $student = $this->add('Model_Student')->loadAny();


        $student = $this->add('Model_Student')->loadAny();

//      $student_detail= $student->ref('ClassHasStudent')->debug();
//      select `idclass_has_student`,`class_idclass`,(select `idclass` from `class` where `class_has_student`.`class_idclass` = `class`.`idclass` ) `class_idclass_2`,`student_idstudent`,(select `name` from `student` where `class_has_student`.`student_idstudent` = `student`.`idstudent` ) `student_name`,`date_enrolled`,`grade` from `class_has_student` where `class_has_student`.`student_idstudent` = "1"
+---------------------+---------------+-----------------+-------------------+--------------+---------------+-------+
| idclass_has_student | class_idclass | class_idclass_2 | student_idstudent | student_name | date_enrolled | grade |
+---------------------+---------------+-----------------+-------------------+--------------+---------------+-------+
|                   1 |             1 |               1 |                 1 | Tom          | 2012-09-04    |     0 |
|                   3 |             2 |               2 |                 1 | Tom          | 2012-09-14    |     0 |
+---------------------+---------------+-----------------+-------------------+--------------+---------------+-------+

        // USING $this->hasOne('Class','class_idclass','idclass', 'class_name'); in ClassHasStudent
//      select `idclass_has_student`,`class_idclass`,(select `idclass` from `class` where `class_has_student`.`class_idclass` = `class`.`idclass` ) `class_name`,`student_idstudent`,(select `name` from `student` where `class_has_student`.`student_idstudent` = `student`.`idstudent` ) `student_name`,`date_enrolled`,`grade` from `class_has_student` where `class_has_student`.`student_idstudent` = "1";
+---------------------+---------------+------------+-------------------+--------------+---------------+-------+
| idclass_has_student | class_idclass | class_name | student_idstudent | student_name | date_enrolled | grade |
+---------------------+---------------+------------+-------------------+--------------+---------------+-------+
|                   1 |             1 |          1 |                 1 | Tom          | 2012-09-04    |     0 |
|                   3 |             2 |          2 |                 1 | Tom          | 2012-09-14    |     0 |
+---------------------+---------------+------------+-------------------+--------------+---------------+-------+

        $student_detail= $student->ref('ClassHasStudent')->ref('class_idclass')->debug();
//      select `idclass`,`subject_idsubject`,(select `name` from `subject` where `class`.`subject_idsubject` = `subject`.`idsubject` ) `subject_idsubject_2`,`date_start`,`date_end`,`max_students` from `class`
+---------+-------------------+---------------------+------------+------------+--------------+
| idclass | subject_idsubject | subject_idsubject_2 | date_start | date_end   | max_students |
+---------+-------------------+---------------------+------------+------------+--------------+
|       1 |                 2 | English             | 2012-09-10 | 2012-09-30 |           10 |
|       2 |                 1 | Maths               | 2012-09-08 | 2012-09-30 |           30 |
|       3 |                 3 | Chemistry           | 2012-10-01 | 2012-10-31 |           35 |
|       4 |                 2 | English             | 2012-09-19 | 2012-09-29 |           10 |
+---------+-------------------+---------------------+------------+------------+--------------+


        // Add Lister object to view, using LibraryList template spot.
        $ClassList = $view->add('StudentClasses', null, 'ClassList');

        $view->setModel( $student );
        $ClassList->setModel( $student_detail );

    }
}

我也修改Table::hasOne()为以下,哪里hasOne可以设置dereferenced_field变量。/atk4/lib/Model/Table.php

/** Defines one to many association */
function hasOne($model,$our_field=null,$display_field=null,$deref_field_name=null){
    if(!$our_field){
        if(!is_object($model)){
            $tmp=preg_replace('|^(.*/)?(.*)$|','\1Model_\2',$model);
            $tmp=new $tmp; // avoid recursion
        }else $tmp=$model;
        $our_field=($tmp->table).'_id';
    }
    $r=$this->add('Field_Reference',$our_field);
    $r->dereferenced_field=$deref_field_name;
    $r->setModel($model,$display_field);
    return $r;
}

更新 1

将上述示例更改为视频中指定的设计会生成以下代码:

学生.php

  <?php
  class Model_Student extends Model_Table {
      public $table='student';
      public $entity_code='student';
      public $id_field='idstudent';
      public $title_field='name';

      function init(){
          parent::init();

          $this->addField('student_id')->caption('Student ID');
          $this->addField('name')->caption('Name');
          $this->hasMany('ClassJoinClassHasStudent');
      }
  }

ClassJoinClassHasStudent.php

class Model_ClassJoinClassHasStudent extends Model_Class {

    function init(){
        parent::init();

        $chs = $this->join('class_has_student.class_idclass','idclass');
        // Import fields from ClassHasStudent
        $chs->addField('date_enrolled');
        $chs->addField('grade');

        $chs->hasOne('Class'); // use id_class from CHS table.
    }
}

但是,我收到以下与在 ClassJoinClassHasStudent 中设置主字段相关的错误。我试过调用 hasMany('ClassJoinClassHasStudent', 'student_idstudent', 'idstudent'),但错误是一样的,只是它抱怨的是 student_idstudent 而不是 student_id。

BaseException

Child element not found

Additional information:

    Raised by object: Object Model_ClassJoinClassHasStudent(studentenrol_testclasses_model_student_ClassJoinClassHasStudent_model_classjoinclasshasstudent)
    element: student_id

Possible Actions:

    Debug this Model

/home/user1/public_html/studentenrol/atk4/lib/BaseException.php:38
Stack trace:
/home/user1/public_html/studentenrol/atk4/lib/BaseException.php :38     BaseException   BaseException->collectBasicData(Null, 1, 0)
/home/user1/public_html/studentenrol/atk4/lib/AbstractObject.php    :292    BaseException   BaseException->__construct("Child element not found")
/   :   studentenrol_testclasses_model_student_ClassJoinClassHasStudent_model_classjoinclasshasstudent  Model_ClassJoinClassHasStudent->exception("Child element not found")
/home/user1/public_html/studentenrol/atk4/lib/Model/Table.php   :87         Loggercall_user_func_array(Array(2), Array(1))
/home/user1/public_html/studentenrol/atk4/lib/AbstractObject.php    :202    studentenrol_testclasses_model_student_ClassJoinClassHasStudent_model_classjoinclasshasstudent  Model_ClassJoinClassHasStudent->exception("Child element not found")
/home/user1/public_html/studentenrol/atk4/lib/Model/Table.php   :259    studentenrol_testclasses_model_student_ClassJoinClassHasStudent_model_classjoinclasshasstudent  Model_ClassJoinClassHasStudent->getElement("student_id")
/home/user1/public_html/studentenrol/atk4/lib/Model/Table.php   :321    studentenrol_testclasses_model_student_ClassJoinClassHasStudent_model_classjoinclasshasstudent  Model_ClassJoinClassHasStudent->addCondition("student_id", "1")
/home/user1/public_html/studentenrol/atk4/lib/SQL/Many.php  :48     studentenrol_testclasses_model_student_ClassJoinClassHasStudent_model_classjoinclasshasstudent  Model_ClassJoinClassHasStudent->setMasterField("student_id", "1")
/home/user1/public_html/studentenrol/atk4/lib/Model/Table.php   :243    studentenrol_testclasses_model_student_ClassJoinClassHasStudent SQL_Many->ref(Null)
/home/user1/public_html/studentenrol/page/testclasses.php   :93     studentenrol_testclasses_model_student  Model_Student->ref("ClassJoinClassHasStudent")
/home/user1/public_html/studentenrol/atk4/lib/ApiFrontend.php   :93     studentenrol_testclasses    page_TestClasses->initMainPage()
/home/user1/public_html/studentenrol/atk4/lib/ApiWeb.php    :332    studentenrol    Frontend->layout_Content()
/home/user1/public_html/studentenrol/atk4/lib/ApiFrontend.php   :33     studentenrol    Frontend->addLayout("Content")
/home/user1/public_html/studentenrol/atk4/lib/ApiWeb.php    :208    studentenrol    Frontend->initLayout()
/home/user1/public_html/studentenrol/index.php  :24     studentenrol    Frontend->main()
4

2 回答 2

1

我重新创建了您的示例并更改了如下代码:

$student = $this->add('Model_Student')->loadAny();
$student_detail= $this->add('Model_Class');
$student_detail->join('class_has_student.class_idclass','idclass')->addField('student_idstudent');
$student_detail->addCondition('student_idstudent',$student->id);
$ClassList = $view->add('StudentClasses', null, 'ClassList');

$view->setModel( $student );
$ClassList->setModel( $student_detail->debug() );

基本上你必须从你愿意展示的模型开始。因为要列出类,所以应该选择 Model_Class。然后将模型与多对多表连接起来,并从另一端 (student_idstudent) 定义字段。接下来,您可以在条件下使用它。

在此处输入图像描述

我还必须修补 Model_Table 以允许 hasOne() 的第四个参数定义取消引用的字段,所以请更新到最新的 ATK4。

https://github.com/atk4/atk4-testsuite/commit/ccaef2c5e5841bb265001f00d832c3583a4cf722

于 2012-10-12T01:06:00.010 回答
0

我认为这个视频解释了如何处理你的问题:

http://www.youtube.com/watch?v=yghw7MZABPk&feature=plcp

以最有效的方式。

于 2012-09-18T19:30:20.323 回答