Kohana 3,添加 m2m 数据的“未定义索引”异常

Posted

技术标签:

【中文标题】Kohana 3,添加 m2m 数据的“未定义索引”异常【英文标题】:Kohana 3, "Undefined Index" exception with m2m data adding 【发布时间】:2010-05-06 21:12:21 【问题描述】:

我在官方论坛上发布了这个但没有结果。

我在尝试保存数据时收到Undefined index 注册错误。

我的支点模型:

class Model_Enrollment extends ORM  
               protected $_belongs_to = array('page' => array(), 'menugroup' => array());
          

模型页面

protected $_has_many = array('templates' => array(), 'menugroups' => array('through' => 'enrollment'));

模型_菜单组

  protected $_has_many = array('menuitems' => array(), 'pages' => array('through' => 'enrollment'));
//Overriden save() method in Model_Menugroup:
public function save() 
    if (empty($this->created)) 
         $this->created = time();
    
    parent::save();
    $this->reload();
    if (! $this->is_global) 
      if (! empty($this->groupOwnerPagesId) 
          $page = ORM::factory('page');
          foreach($this->groupOwnerPagesId as $id) 
            $this->add('enrollment', $page->find($id));
          
       
    

我做到了:

我通过将数据透视模型中的表名更改为单数来更正表名 我什至现在为数据透视表/模型 = 注册使用相同的名称。和教程中的一样。以防万一 所以数据透视表的名称为“enrollment”并有 2 列:page_id、menugroup_id 我尝试在数据透视表中添加 pk,但没有任何改变 我尝试添加/删除页面/菜单组和数据透视表 (InnoDB) 之间的数据库关系,但没有成功 我尝试将所有数据保存在控制器中,但结果相同:(

我仍然遇到同样的错误:

Undefined index: enrollment in ORM line: $columns = array($this->_has_many[$alias]['foreign_key'], $this->_has_many[$alias]['far_key']);

谁能告诉我,还有什么问题?我没有其他想法:(

亲切的问候

【问题讨论】:

【参考方案1】:

表注册

CREATE TABLE IF NOT EXISTS `enrollments` (
  `page_id` int(11) NOT NULL,
  `menugroup_id` int(11) NOT NULL,
  KEY `page_id` (`page_id`,`menugroup_id`),
  KEY `menugroup_id` (`menugroup_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

表格菜单组

CREATE TABLE IF NOT EXISTS `menugroups` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(100) NOT NULL,
  `location` tinyint(4) NOT NULL,
  `is_global` tinyint(4) NOT NULL DEFAULT '1',
  `order` tinyint(4) NOT NULL,
  `created` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 

表格页

CREATE TABLE IF NOT EXISTS `pages` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(100) NOT NULL,
  `link` varchar(100) NOT NULL,
  `keywords` tinytext,
  `description` tinytext,
  `template_id` int(11) unsigned DEFAULT NULL,
  `is_main` tinyint(4) NOT NULL DEFAULT '0',
  `header_on` tinyint(4) DEFAULT NULL,
  `footer_on` int(11) DEFAULT NULL,
  `sidebar_on` int(11) DEFAULT NULL,
  `content` longblob NOT NULL,
  `created` int(11) NOT NULL,
  `last_modified` int(11) DEFAULT NULL,
  `author` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `title` (`title`,`link`),
  UNIQUE KEY `link` (`link`),
  KEY `template_id` (`template_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8

Model_Enrollment

class Model_Enrollment extends ORM  
    protected $_belongs_to = array('page' => array(), 'menugroup' => array());

模型页面

类 Model_Page 扩展 Model_FlyOrm

protected $_filters = array(
                        'title' => array('trim' => NULL),
                        'content' => array('trim' => NULL),
                        'keywords' => array('trim' => NULL),
                        'description' => array('trim' => NULL)
                   );

protected $_has_many = array('templates' => array(), 'menugroups' => array('through' => 'enrollment', 'foreign_key' => 'page_id', 'far_key' => 'menugroup_id'));

protected $_rules = array(

           'title' => array(
               'not_empty' => array(),
               'min_length' => array(3),
               'max_length' => array(100),

           ),
           'keywords' => array(
               'max_length' => array(255),
           ),
           'description' => array(
               'max_length' => array(255),
           ),
           'template_id' => array(
               'digit' => array(),
           ),
           'header_on' => array(
               'digit' => array(),
           ),
           'footer_on' => array(
               'digit' => array(),
           ),
           'sidebar_on' => array(
               'digit' => array(),
           ),
           'is_main' => array(
               'digit' => array(),
           ),
           'content' => array(
               'not_empty' => array(),
               'min_length' => array(10),
           ),
           'created' => array(
               'digit' => array(),
           ),
           'last_modified' => array(
               'digit' => array(),
           ),
           'author' => array(
               'max_length' => array(50),
           )
);

protected $_callbacks = array(
    'title' => array('is_unique'),
    'link' => array('is_unique'),
);

private $result = array('msg' => '', 'is_success' => NULL);

public function __construct($id = null) 
    parent::__construct('pages', $id);


public function get_pages() 
    return $this->order_by('is_main', 'DESC')->find_all();


public function save() 
    $this->create_link();
    if (! $this->_loaded) 
        $this->created = time();
     else 
        $this->last_modified = time();
    
    if ($this->is_main) 
        $old_main = $this->get_main_page();
        if ($old_main->_loaded) 
            $old_main->is_main = 0;
            $old_main->save();
        
    
    return parent::save();


public function values($values) 
    foreach($values as $key => $val) 
        if ($val == self::NOT_SET)
            $values[$key] = NULL;
    
    return parent::values($values);


public function _delete($id) 
    $this->set_result($this->get_msg('pages.success.delete'));
    if (is_array($id)) 
            $pages = ORM::factory('page')->where('id', 'IN', $id)->find_all();
            foreach ($pages as $page) 
              if ($page->is_main) 
                    $this->set_result($this->get_msg('pages.fail.main_page'), FALSE);
               else 
                  $page->delete();
              
            
     else 
        $this->find($id);
        if ($this->_loaded) 
            if ($this->is_main) 
                $this->set_result($this->get_msg('pages.fail.main_page'), FALSE);
             else 
                $this->delete();
            
         else 
            $this->set_result($this->get_msg('pages.fail.delete'), FALSE);
        
    


public function get_result() 
    return $this->result;


public function __get($name) 
    $value = parent::__get($name);
    if ($name == 'created' || $name == 'last_modified')
        return date("Y-m-d H:i:s", $value);
    else return $value;


public function get_main_page() 
    return ORM::factory('page')->where('is_main', '=', 1)->find();


private function create_link() 
    $link = text::pl2en($this->title);
    $link = trim(preg_replace('/[^A-Za-z0-9\-\s]+/', '', $link));
    $link = preg_replace('/\s+/', '-', $link);
    $link = preg_replace('/^(-*)|(-*$)/', '', $link);
    $this->link = strtolower($link);


private function set_result($msg, $is_success = TRUE) 
    $this->result['msg'] = $msg;
    $this->result['is_success'] = $is_success;


private function get_msg($path) 
    return Kohana::message('messages', $path);


private function set_global_settings_if_required($global) 
    if (empty($this->template)) 
            $this->template = $global->template;
    
    if (is_null($this->header_on)) 
            $this->header_on = $global->header_on;
    
    if (is_null($this->sidebar_on)) 
            $this->sidebar_on = $global->sidebar_on;
    
    if (is_null($this->footer_on)) 
            $this->footer_on = $global->footer_on;
    
    if (empty($this->keywords)) 
            $this->keywords = $global->keywords;
    
    if (empty($this->description)) 
            $this->description = $global->description;
    
    if (empty($this->author)) 
            $this->author = $global->author;
    

CONST NOT_SET = -1;

模型_菜单组

class Model_MenuGroup extends Model_FlyOrm 

    protected $_has_many = array('menuitems' => array(), 'pages' => array('through' => 'enrollment', 'foreign_key' => 'menugroup_id', 'far_key' => 'page_id'));

    protected $_filters = array(
        'name' => array('trim' => NULL),
    );
    protected $_rules = array(
        'name' => array(
            'not_empty' => array(),
            'min_length' => array(2),
            'max_length' => array(100)
        ),
        'location' => array(
            'range' => array(0,2),
        ),
        'is_global' => array(
            'range' => array(0,1),
        ),
        'order' => array(
            'digit' => NULL,
        )
    );

    protected $_callbacks = array(
        'name' => array('is_unique'),
    );

    private $groupOwnerPagesId = array();

    public function __construct($id = NULL) 
        parent::__construct('menugroup', $id);
    

    public function save() 
        if (empty($this->created)) 
             $this->created = time();
        
        parent::save();
        $this->reload();
        if (! $this->is_global) 
            if (! empty($this->groupOwnerPagesId)) 
                $page = ORM::factory('page');
                foreach($this->groupOwnerPagesId as $id) 
                    $this->add('enrollment', $page->find($id));
                
            
        
    

    public function values($data) 
        parent::values($data);
        if (! isset($data['is_global'])) 
           if (isset($data['pages'])) 
               foreach( $data['pages'] as $key => $value) 
                   $this->groupOwnerPagesId[] = $key;
               
           
           $this->is_global = 0;
        

    

    public function check() 
        $result = parent::check();
        if (! $this->is_global) 
            if (empty($this->groupOwnerPagesId)) 
                $this->_validate->error('is_global', 'no_pages');
                return false;
            
        
        return $result;
    

    public function __get($name) 
        $value = parent::__get($name);
        if ($name == 'created')
            return date("Y-m-d H:i:s", $value);
        else return $value;
    

    public function get_by_location($id) 
        return $this->where('location', '=', $id)->order_by('order', 'ASC')->find_all();
    

    public function get_all_groups() 
        return $this->find_all();
    

    public function get_parent_pages_if_exists() 
        if (! $this->is_global) 
            return $this->pages->find_all();
         else 
            return FALSE;
        
    

    public function get_items($group_id) 
        return $this->find($group_id)->menuitems->find_all();
    

?>

我还注意到我有一个带有 mysql 保留字 'order' 的列名,我将其更改为 'ord' 但没有得到肯定的结果。

【讨论】:

如果你有额外的信息,你应该把它放在你的问题中,而不是发布一个(因为这篇文章没有回答你的问题)。【参考方案2】:

确保以这种方式命名表;

Model_Page = table pages
Model_Enrollment = table enrollments
Model_Menugroup = table menugroups

如果这不起作用,请尝试在 Model_MenugroupModel_Page 中定义 'model'、'foreign_key' 和 'far_key' '有很多'定义,尽管这是一条规则,“如果你必须手动定义表名、外键或远键,数据库设计中遗漏了一些东西(实际上,如果你必须定义任何应该自动定义的东西):)

如果您仍然不知道错误在哪里,请在此处发布所有 3 个表 CREATE 查询和模型。

编辑:

测试它,问题是您传递模型名称而不是“通过”的表名称。尝试使用“注册”而不是“注册”:)

【讨论】:

感谢您的回答。我尝试了您的建议,但仍然出现相同的错误结果。我将在下面粘贴我的表格和模型。【参考方案3】:

我的错!

代替:

            $this->add('pages', $page->find($id));

我尝试添加枢轴!

            $this->add('pages', $page->find($id));

我怎么这么瞎!

非常感谢 Kemo 的帮助,很抱歉因为我的大错而浪费了您的时间。

【讨论】:

(?) 你能纠正你的答案吗?您粘贴了两个相同的代码,如果它确实解决了您的问题,您也没有将您的答案标记为正确答案。

以上是关于Kohana 3,添加 m2m 数据的“未定义索引”异常的主要内容,如果未能解决你的问题,请参考以下文章

Kohana 2.3.4 ORM - 删除数据透视表关系

Kohana 添加函数返回省份名称

最喜欢的 Kohana 提示和功能? [关闭]

Kohana 3.1 ORM 数据库查询

Laravel 迁移未定义索引

Kohana 3.0.x ORM:读取数据透视表中的其他列