-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Problem with Many to Many #24
Comments
I forgot to point out I was using SqliteAdapter... Maybe that's the problem. I will try to check with Mysql. |
I've tried with mysql and I've got different errors:
The movie table is not created but actor and cast tables are correctly saved. Adding above lines, actor and movie tables are correctly saved but cast table is partially saved as I've got this PDO error:
cast table looks like:
For both SQLite and MySQL, it works correctly with the 2 added lines and without editmode. For testing, I use this php file based on README example: <?php
include('tests/autoload.php');
// Add a slash to comment out next line and use SQLite
/* For SQLITE
$pdo = new PDO('sqlite:test.db');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->query('DROP TABLE IF EXISTS actor');
$pdo->query('DROP TABLE IF EXISTS movie');
$pdo->query('DROP TABLE IF EXISTS cast');
$pdo->query('CREATE TABLE "actor" (id INTEGER NOT NULL, `name` VARCHAR(255), PRIMARY KEY(id));');
$pdo->query('CREATE TABLE "movie" (id INTEGER, `title` VARCHAR(255), PRIMARY KEY(id));');
$pdo->query('CREATE TABLE "cast" (movieId VARCHAR(255) NOT NULL, actorId INTEGER NOT NULL, PRIMARY KEY(movieId, actorId));');
// */
// Add a slash to comment out next line and use MySQL
/* For MySQL
$pdo = new PDO('mysql:dbname=maphpertest;host=127.0.0.1', 'root', '');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->query('DROP TABLE IF EXISTS actor');
$pdo->query('DROP TABLE IF EXISTS movie');
$pdo->query('DROP TABLE IF EXISTS cast');
$pdo->query('CREATE TABLE `actor` (`id` int(11) NOT NULL, `name` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;');
$pdo->query('CREATE TABLE `movie` (`id` int(11) NOT NULL AUTO_INCREMENT, `title` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`), KEY `id` (`id`), KEY `title` (`title`)) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;');
$pdo->query('CREATE TABLE `cast` (`movieId` varchar(255) NOT NULL, `actorId` int(11) NOT NULL, PRIMARY KEY (`movieId`,`actorId`), KEY `actorid` (`actorId`), KEY `actorid_movieid` (`actorId`,`movieId`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;');
// */
//prevent any Date errors
date_default_timezone_set('Europe/London');
$actors = new \Maphper\Maphper(
new \Maphper\DataSource\Database(
$pdo, 'actor', 'id'
// ,['editmode' => true]
)
);
$movies = new \Maphper\Maphper(
new \Maphper\DataSource\Database(
$pdo, 'movie', 'id'
// , ['editmode' => true]
)
);
$cast = new \Maphper\Maphper(
new \Maphper\Datasource\Database(
$pdo, 'cast', ['movieId', 'actorId']
// , ['editmode' => true]
)
);
$actors->addRelation('movies', new \Maphper\Relation\ManyMany($cast, $movies, 'id', 'movieId'));
$movies->addRelation('actors', new \Maphper\Relation\ManyMany($cast, $actors, 'id', 'actorId'));
$actor = new \stdclass;
$actor->id = 123;
$actor->name = 'Samuel L. Jackson';
//save the actor
$actors[] = $actor;
//now add some movies to the actor
$movie1 = new \stdclass;
$movie1->title = 'Pulp Fiction';
// Without this line, it does not save $movie1 in movie table
$movies[] = $movie1;
$actor->movies[] = $movie1;
//now add some movies to the actor
$movie2 = new \stdclass;
$movie2->title = 'Snakes on a Plane';
// Without this line, it does not save $movie2 in movie table
$movies[] = $movie2;
$actor->movies[] = $movie2;
$actor = $actors[123];
echo $actor->name . ' was in the movies:' . "\n";
foreach ($actor->movies as $movie) {
echo $movie->title . "\n";
}
$actor = new \stdclass;
$actor->id = 124;
$actor->name = 'John Travolta';
$actors[] = $actor;
//Find the movie 'Pulp Fiction and add it to John Travolta
$movie = $movies->filter(['title' =>'Pulp Fiction'])->item(0);
$actor->movies[] = $movie;
echo 'The actors in ' . $movie->title . ' are :' . "\n";
foreach ($movie->actors as $actor) {
echo $actor->name . "\n";
} |
Thanks, I believe I've fixed this issue and another related one I had discovered previously and proved quite difficult to fix. Previously this would not work: $author = new stdclass;
$author->name = 'Tom';
$author->blogs = [];
$blog1 = new stdClass;
$blog1->title = 'Blog 1';
$author->blogs[] = $blog1;
$blog2 = new stdClass;
$blog2->title = 'Blog 2';
$author->blogs[] = $blog2;
$authors[] = $author; Previously this would not give the correct results and the blogs would not be saved unless you saved the author prior to assigning the blogs: $author = new stdclass;
$author->name = 'Tom';
$author->blogs = [];
$authors[] = $author;
$blog1 = new stdClass;
$blog1->title = 'Blog 1';
$author->blogs[] = $blog1;
$blog2 = new stdClass;
$blog2->title = 'Blog 2';
$author->blogs[] = $blog2; I've changed the implementation so that the order of saving doesn't matter. Take a look at the tests |
SQLite is now fixed. There is still an issue with ManyMany when using auto-traversal (skipping the intermediate table) |
I've tried with you're updated code but I've got this new error with sqliteadapter:
It seems to work correctly with mysqladapter I've got this error using very simple code:
The problem occurs when However all tests run correctly for sqliteadapter...
BTW, I guess the test files needs modifications as for now, mysql driver is required for sqlite tests as pdo is constructed in construct and sqlite tests inherit from mysql one. I guess it's better to initialize pdo in setup function without calling parent ?
edit:
|
I've found the problem
In the code, PDO errors are handle with exceptions. Thus, this line is needed in the example, in order to work correctly:
For now, I guess everything is OK ! |
Aha, well spotted! I'm going to re-open this as it's not desired behaviour. I fixed this for the MySQL wrapper but need to add the same for the SQLite version |
No problem. What about the problem I raise about tests and the solution I've proposed with setUp function ? |
I am still getting issues with ManyMany and I am using MySql |
I figured it out. ManyMany doesn't work unless you set up both sides of the relation. So in the test if you comment out $movies->addRelation('actors', new \Maphper\Relation\ManyMany($cast, $actors, 'aid', 'actorId')); but leave $actors->addRelation('movies', new \Maphper\Relation\ManyMany($cast, $movies, 'mid', 'movieId')); Then you get this error
|
Could it be made that if the relation is not already added, then the ManyMany object adds the other relation. |
I have some problems using your README example.
First, I guess it should be:
$movies = new \Maphper\Maphper(new \Maphper\Datasource\Database($pdo, 'movie', 'id'));
instead of:
$movies = new \Maphper\Maphper(new \Maphper\Datasource\Database($pdo, 'actor', 'id'));
Then, I have to add
before using
otherwise it does not add movie to actor.
I don't know if this is an error in README or an unexpected behaviour of Maphper.
Finally, if I add editmode and the table does not exists
It does not save the second movie and actor correctly (with the above correction adding manually the movies).
My final dumb is:
Snakes on a Plane is not present and John Travolta is missing too except on cast with the 124 that appears
The text was updated successfully, but these errors were encountered: