问题描述:
在“成绩龙虎榜”里面,下属于联赛盃的第一循环和第二循环的数据都是联赛盃的总成绩的数据,即是错误。
创建存储
所以,我们首先需要一个新表,来表示matchday与team之间的直接关系,就像season_teams一样:
我将称之为matchday_teams。通过输出season_teams表,得到一个SQL的参考,修改部分参数:
SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";# MySQL 傳回的查詢結果為空 (原因可能為:沒有找到符合條件的記錄)
CREATE TABLE IF NOT EXISTS `jos_bl_matchday_teams` (
`matchday_id` int(11) NOT NULL DEFAULT '0',
`team_id` int(11) NOT NULL DEFAULT '0',
`bonus_point` decimal(10,2) NOT NULL DEFAULT '0.00',
`results_remark` varchar(255) NOT NULL,
PRIMARY KEY (`matchday_id`,`team_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;# MySQL 傳回的查詢結果為空 (原因可能為:沒有找到符合條件的記錄)
现在需要做的是:
1.为现有数据创建相应的该表内记录,比如为每一个球队与联赛盃赛程的组合都插入一行记录;
2.找出所有操作到season_teams表的地方,因为那里同样需要操作matchday_teams,比如创建球队,创建赛季的操作;
3.修改“成绩龙虎榜”的视图,把新表格的数据考虑进去。
而我想从第二个开始,这可以使用easyEclipse的搜索功能:
幸好结果不算多,而其中我们需要理会的只有三个文件,但是components/com_joomsport/controllers/下的两个文件究竟在做什么,我已经忘记了,所以先看看admin.joomsport.php。
在其中,有下列方法操作到了season_teams表:
BL_SeasonEdit
BL_SeasonSave
BL_TeamEdit
BL_TeamSave
BL_MdayEdit
BL_GroupEdit
我们从后往前逐个逐个看:
group
在编辑分组时,系统会自动先获取这个赛季所包含的球队,因为分组是必然属于某个赛季的,所以参与该组的球队只能从参与是次赛季的球队中产生,出于这个原因,系统需要找到参与某个赛季的所有球队,因为需要season_teams表里的数据。
mDay
编辑赛程和编辑分组相似,都需要预先获得参与该赛季的所有球队。
team
编辑球队是需要修改season_teams表的地方,所以edit与save同时出现。这里是唯一需要对season_teams表中的remark和points字段修改的地方。
season
编辑赛季时,需要给这个赛季指定参与的球队,这将是给每一个需要的season/team对创建一个记录的地方。但并不修改remark与points字段。
结论是,我们不如在编辑赛季的地方,给season/team组合创建season_teams中记录时,就给matchday_teams也创建记录,当然这样不行,所以必须要把这个动作放在创建matchday的地方。
但严格来讲,在编辑season的时候,假如修改了参与该赛季的球队,那么这里也应该对这个赛季内的赛程进行更新。
而在编辑team时,修改matchday_teams的points与remark的数据。
现在。回头看看另外的引用到season_teams的php文件,moder.php其实是作为裁判员登陆后修改数据的控制器,我们无需理会,至于admin.php,在其中加入dumpMessage()方法,却并没有弹出任何窗口,在访问后台的时候,看起来它像是为了管理员在前端进行修改时的控制器。
可是,我们刚刚遗漏了一些搜索结果:
填补应有的数据
这是上面列出的任务列表的第一项。任务是安装现在的数据状况,为新建立的表matchday_teams加入它应该已经有的数据,每一行记录是一个联赛盃赛程与参与它的一个球队组合。
目前的状况是,联赛盃下有两个赛程:第一循环和第二循环,总共有55支球队全部参加了联赛盃,那么即是说这55个球队也悉数参加了第一循环和第二循环,针对每个“循环-球队”组,建立一个记录,一共应该产生2×55=110个记录。
至此,我们可以使用:
INSERT INTO table_2
SELECT * FROM table_1
来插入新数据,然后我现在还不想这样,我希望这个过程能够以更严谨的方式进行,因为实际上会被插入的记录所对应的球队与赛程是有关联的,这个球队必然要参与赛程所属 的赛季,即是说在season_teams表中可以寻找到的关联:
matchday JOIN season ON season_id JOIN season_teams ON season_id JOIN team ON team_id,
这个关系约束之上,还要加上只是联赛盃的限制:
matchday JOIN season ON season_id JOIN season_teams ON season_id JOIN team ON team_id JOIN tournament ON tournament_id (WHERE tournament.t_type = 双循环赛制)
当然这个关系可以简化很多,最终变成:
SELECT st.team_id AS tid, md.id AS mdid
FROM jos_bl_season_teams AS st, jos_bl_matchday AS md, jos_bl_seasons AS s, jos_bl_tournament AS tor
WHERE md.s_id = st.season_id
AND md.s_id = s.s_id
AND s.t_id = tor.id
AND tor.t_type = '1'
于是可以帮助我们完成插入数据的SQL应该是:
INSERT INTO jos_bl_matchday_teams( matchday_id, team_id )
SELECT md.id, st.team_id
FROM jos_bl_season_teams AS st, jos_bl_matchday AS md, jos_bl_seasons AS s, jos_bl_tournament AS tor
WHERE md.s_id = st.season_id
AND md.s_id = s.s_id
AND s.t_id = tor.id
AND tor.t_type = '1'
数据的生存周期--产生:在创建新matchDay时为matchday_teams插入应有的记录
现在来完成在创建matchday的时候,我们应该多做的一些事情,即在BL_MdaySave()方法里。
首先是判断当下赛程所属的赛季的比赛类型是否是双循环赛制,如果是,那么就要在matchday中建立新记录之后,再为这个记录和所有参与其中的球队建立在matchday_teams中的记录。
首先需要判断当下被保存的赛程是否是联赛盃:
$query = "SELECT t.t_type FROM #__bl_tournament AS t , #__bl_seasons as s WHERE s.t_id = t.id AND s.s_id = ".$row->s_id;
$db->setQuery($query);
$tour_type = $db->loadResult();
if($tour_type == "1")
{
}
关于$row,它在上面的声明为$row = new JTableMday($db);具体参见Joomla对于数据库访问的封装。JTableMday的定义在admin.class.php内,它继承自JTable。
总之现在我们遇到一个联赛盃的赛程时,需要再进行进一步的判断,就是它是否并没有被建立matchday_teams表中相应数据:
$query = "SELECT COUNT(*) FROM #__bl_matchday_teams as mdt WHERE mdt.matchday_id = ".$row->id;
$db->setQuery($query);
$result = $db->loadResult(); // string
if($result == "0")
{
}
这个时候,应该执行的是插入数据:
$query = "INSERT INTO #__bl_matchday_teams (matchday_id, team_id) " .
"SELECT ". $row->id . ", st.team_id FROM #__bl_season_teams AS st ".
"WHERE st.season_id = ".$row->s_id;
$db->setQuery($query);
$db->query();
数据的生存周期--更新:在编辑team时,更新bonus_points与remarks字段到matchDay_teams表
表matchday_teams的真正目的是存储关于每个球队在每个赛程之中的犯规记录,目前有两个字段,扣分和备注,现在需要实现让用户来填补这两个字段的逻辑。它们的界面应该被放在球队的编辑页面。
下面介绍的代码应该被放在BL_TeamEdit()方法里:
在做为了当下亟待解决的问题必要的修改之前,先修改个之前的问题,即是所查询的赛季应该是已发布的:
$query = "SELECT st.*,CONCAT(t.name,' ',s.s_name) as name FROM #__bl_seasons as s LEFT JOIN #__bl_tournament as t ON t.id = s.t_id, #__bl_season_teams as st WHERE s.s_id = st.season_id AND s.published = '1' AND st.team_id=".$row->id;
$db->setQuery($query);
$lists["bonuses"] = $db->loadObjectList();
下面是将要使用到的SQL查询,它将找出新表中与当下team相关的记录,同时也保证赛程是属于已发布的赛季的:
SELECT mdt . * , CONCAT( t.name, ' ', s.s_name, ' ', md.m_name ) AS name
FROM jos_bl_matchday AS md
LEFT JOIN jos_bl_seasons AS s ON md.s_id = s.s_id
LEFT JOIN jos_bl_tournament AS t ON t.id = s.t_id, jos_bl_matchday_teams AS mdt
WHERE mdt.matchday_id = md.id
AND s.published = '1'
AND mdt.team_id =2
最后,在这个方法中要加入的片段是:
// added by Vincent 2012-07-08
$query = "SELECT mdt.* , CONCAT( t.name, ' ', s.s_name, ' ', md.m_name ) AS name ".
"FROM #__bl_matchday AS md LEFT JOIN #__bl_seasons AS s ON md.s_id = s.s_id ".
"LEFT JOIN #__bl_tournament AS t ON t.id = s.t_id, #__bl_matchday_teams AS mdt ".
"WHERE mdt.matchday_id = md.id AND s.published = '1' AND mdt.team_id = ".$row->id;
$db->setQuery($query);
$lists["bonuses_md"] = $db->loadObjectList(); // could be null?
// end of addition
但这并不够,需要在输出HTML的admin.joomsport.html.php中,对方法bl_editTeam()添加代码:
if( isset($lists['bonuses_md']) && !empty( $lists['bonuses_md'] ) )
{
for($r=0;$r<count($lists['bonuses_md']);$r++)
{
$bonuses = $lists['bonuses_md'][$r];
echo '<tr><td><input type="hidden" name="mdids[]" value="'.$bonuses->matchday_id.'" />'.$bonuses->name.'</td>';
echo '<td><input style="width:300px" type="text" name="remarks_mdt[]" value="'.$bonuses->results_remark.'" />'.'</td>';
echo '<td><input type="text" name="bonuses_mdt[]" value="'.floatval($bonuses->bonus_point).'" />'.'</td></tr>';
}
}
注意每个input的name属性,我们需要在保存team的方法中使用它们。在BL_TeamSave()方法里,加入下面代码:
// added by Vincent 2012-07-08
if(isset($_POST['mdids']) && count($_POST['mdids']))
{
for($q=0;$q<count($_POST['mdids']);$q++)
{
$query = "UPDATE #__bl_matchday_teams SET bonus_point = " . ($_POST['bonuses_mdt'][$q])
.", results_remark = '" . ($_POST['remarks_mdt'][$q])
."' WHERE matchday_id = " . $_POST['mdids'][$q]." AND team_id = " . $row->id;
$db->setQuery($query);
$db->query();
}
}
// end of addition
处理team与season的关系的变更:
尚未完成,在賽季版面是可以編輯參與賽季的球隊的,所以這裡對season_teams的記錄進行了清洗并重新插入,對於matchday_teams也需要做同樣的事情。把下列代碼加入BL_SeasonSave()方法中:
// added by Vincent 2012-07-09
$query = "SELECT t.t_type FROM #__bl_tournament AS t , #__bl_seasons as s WHERE s.t_id = t.id AND s.s_id = ".$row->s_id;
$db->setQuery($query);
$tour_type = $db->loadResult(); // string
if($tour_type == '1') // 聯賽盃
{
$query = "SELECT id AS mday_id FROM #__bl_matchday WHERE s_id = ".$row->s_id;
$db->setQuery($query);
$mday_ids = $db->loadResultArray(); // array of string
if(!empty($mday_ids))
{
$mdid_str = implode("','", $mday_ids);
$query = "DELETE FROM #__bl_matchday_teams WHERE matchday_id IN('". $mdid_str . "')";
$db->setQuery($query);
$db->query();
if(count($teams_season))
{
foreach($mday_ids as $mdid)
{
foreach($teams_season as $teams)
{
$query = "INSERT INTO #__bl_matchday_teams(matchday_id, team_id) VALUES(".$mdid.",".$teams.")";
$db->setQuery($query);
$db->query();
}
}
}
}
}
// end of addition
数据的生存周期--使用:在前端的视图【成绩龙虎榜】中采用新数据
這個話題即是上面的“應該做清單”的最後一項。就是說,在“成績龍虎榜”的視圖里,當顯示的賽季是聯賽盃的賽程(第一循環或第二循環)時,將扣除紀律分與備註從matchday_teams里獲取,而不是season_teams表。
所以打開文件:components/com_joomsport/views/rankinglist/view.html.php
在循環賽程的代碼塊內,即if(1 == $ranktype){} 內,找到:
$query = "SELECT bonus_point, results_remark FROM #__bl_season_teams AS st, #__bl_matchday AS md "
. "WHERE st.season_id = md.s_id AND md.id = "
. $mday_id
. " AND st.team_id = "
. $team->id;
這即是從season_teams表里獲取扣分與備註的SQL查詢,將其更換成:
$query = "SELECT bonus_point, results_remark FROM #__bl_matchday_teams "
. "WHERE matchday_id = "
. $mday_id
. " AND team_id = "
. $team->id;
就這麼還沒完成,因為這個表有可能會有數據缺失,得到的返回結果並不可靠,所以在使用結果時,最好多一重驗證,所以將這段下面的代碼改為:
$db->setQuery($query);
$mday_team = $db->loadAssoc();
$team_record->remark = isset($mday_team['results_remark']) ? $mday_team['results_remark'] : '';
$team_record->bonus_deducted = isset($mday_team['bonus_point']) ? intval($mday_team['bonus_point']) : 0;