Hi @all,
I am working on a ManyToMany relationship with models, controllers, forms and form elements. So what I want to archive is the following:
- Configure a ManyToMany relationship => DONE (I guess, see example below)
- CRUD model operations for ManyToMany relationships including validation => PROGRESS (Need help on this)
- Form handling for ManyToMany relationships with creating a form element which handles the relationship in a visual way including displaying error messages => PROGRESS (Need help on this)
I guess I've done the first step already. Here is the code I've written so far:
MySQL Tables
Competitions
CREATE TABLE `competitions` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`title` varchar(255) COLLATE utf8_bin NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
Teams
CREATE TABLE `teams` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`title` varchar(255) COLLATE utf8_bin NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
CompetitionsTeams
CREATE TABLE `competitions_teams` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`competition_id` int(11) unsigned NOT NULL,
`team_id` int(11) unsigned NOT NULL,
`weight` int(11) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `competition_id` (`competition_id`),
KEY `team_id` (`team_id`),
CONSTRAINT `competitions_teams_fk_1` FOREIGN KEY (`competition_id`) REFERENCES `competitions` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `competitions_teams_fk_2` FOREIGN KEY (`team_id`) REFERENCES `teams` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
Phalcon Models
Competition
namespace test\Models;
use Phalcon\Mvc\Model\Validator\PresenceOf,
Phalcon\Mvc\Model\Validator\StringLength;
class Competition extends Model {
public function getSource() {
return "competitions";
}
public function initialize() {
$this->hasManyToMany(
"id",
"test\\Models\\CompetitionTeam",
"competition_id",
"team_id",
"test\\Models\\Team",
"id",
array('alias' => 'CompetitionTeam')
);
}
public function validation() {
$this->validate(new PresenceOf(array(
"field" => "title",
'message' => 'The title is required.'
)));
$this->validate(new StringLength(array(
"field" => "title",
'min' => 2,
'messageMinimum' => 'The title is too short.'
)));
return !$this->validationHasFailed();
}
}
Team
namespace test\Models;
use Phalcon\Mvc\Model\Validator\PresenceOf,
Phalcon\Mvc\Model\Validator\StringLength;
class Team extends Model {
public function getSource() {
return "teams";
}
public function initialize() {
$this->hasManyToMany(
"id",
"test\\Models\\CompetitionTeam",
"team_id",
"competition_id",
"test\\Models\\Competition",
"id",
array('alias' => 'CompetitionTeam')
);
}
public function validation() {
$this->validate(new PresenceOf(array(
"field" => "title",
'message' => 'The title is required.'
)));
$this->validate(new StringLength(array(
"field" => "title",
'min' => 2,
'messageMinimum' => 'The title is too short.'
)));
return !$this->validationHasFailed();
}
}
CompetitionTeam
namespace test\Models;
class CompetitionTeam extends Model {
public function getSource() {
return "competitions_teams";
}
public function initialize() {
$this->belongsTo("competition_id", "test\\Models\\Competition", "id", array('alias' => 'Competition'));
$this->belongsTo("team_id", "test\\Models\\Team", "id", array('alias' => 'Team'));
}
public function validation() {
$this->validate(new PresenceOf(array(
"field" => "competition_id",
'message' => 'The competition is required.'
)));
$this->validate(new PresenceOf(array(
"field" => "team_id",
'message' => 'The team is required.'
)));
$this->validate(new PresenceOf(array(
"field" => "weight",
'message' => 'The weight is required.'
)));
return !$this->validationHasFailed();
}
}
Competition Controller
namespace test\Controller;
use test\Models\Competition as Competition,
test\Models\CompetitionTeam as CompetitionTeam;
class CompetitionsController extends Controller {
public function testAction() {
$testCompetition = new Competition();
$testCompetition->title = 'HAS MANY TO MANY TEST';
$CompetitionTeams = array();
$testCompetitionTeam1 = new CompetitionTeam();
$testCompetitionTeam1->team_id = 1; // There is already a team with the id 1 in the database
$CompetitionTeams[] = $testCompetitionTeam1;
$testCompetition->CompetitionTeam = $CompetitionTeams;
if(!$testCompetition->save()) {
foreach($testCompetition->getMessages() as $message) {
$this->log($message->getMessage());
}
}
}
The CompetitionController is currently just for testing and does not have included the CRUD actions. In the database is currently only one team added which has the id 1. No relationships and competitions are sored.
Current Test Result
-
Currently the competitions and competition teams relationship is not stored cause I got the following error: "competition_id is required". This is right cause the competition is not created right now. But this should be handled by phalcon itself, correct? If not what is the best way to integrate this behavior?
- Secondly the validation function of the relationship is not running. Cause I need to store extra fields in this relationship a validation should be done as well. How to handle this?
If you have further questions please feel free to ask.
Thanks for your help!
Michael