atlasphp / atlas.mapper Goto Github PK
View Code? Open in Web Editor NEWA data mapper implementation for the persistence model.
License: MIT License
A data mapper implementation for the persistence model.
License: MIT License
This code will crash with TokenRow::$account_id is immutable after Row is deleted
$account = $mapper->fetchRecord(1, ['tokens']);
$token = $account->tokens->getOneBy(['type' => 'test']);
if (isValid($token)) {
$atlas->delete($token);
}
$account->modified = date('c');
$atlas->update($account);
Is this the intended behavior?
Ps.
I found out will writing this issue that I can use detachOneBy
instead of getOneBy
but that's not always what you want.
Ps 2.
Also found the detachDeleted
method.
We should probably update the documentation with a not about this behavior
Hello,
I'm trying to remove some repetitive, boilerplate code in our app models and one of the areas we see a lot of repeated code is in handling the creation of new records with related fields. When you create a new record none of the related fields will be setup - they are all null - so when we come to set values on them we first need to create the appropriate Record or RecordSet class. While I don't intend to blanket-create these empty classes on record creation I would like to create a simple function that will handle it.
At the moment there is no way to retrieve the foreign mapper class name so any util code would still need to accept the class of the foreign mapper as a parameter. If either the MapperRelationships::getForeignMapper() function was public or there was a public MapperRelationships::getForeignMapperClass() method similar to the Record::getMapperClass() method then I could remove a lot of hard-coded class names and simplify our code by being able to look up the mapper class based on the related field name.
The only way to achieve something similar at the moment is via the stitchIntoRecords() method but this makes unneeded db calls.
Would anyone object to such as change?
Hi all,
I'm testing pushing real-world levels of data through a microservice I've written using Atlas and I've noticed some significant inefficiencies in the various stitchIntoRecord methods.
For instance, the OneToOne class method in combination with RegularRelationship's stitchIntoMethods() method basically loops through every nativeRecord in turn and then loops through every foreignRecord to match them up. However, it neither exits early when a match is found nor removed matched foreignRecords. So with 1000 nativeRecords and their associated 1000 foreignRecords you end up with 1,000,000 calls to recordsMatch().
I'd like to suggest that:
I don't think there are further optimisations available for the other relationship types.
In the case of OneToOne the result is a change from O(n^2) to O(2n). In testing with 3000 records in my app this changed execution time from over 2 mins to 5 seconds.
Do these changes sound correct and reasonable or have I missed something? If there's no reason against the changes I'm happy to put together a PR.
One point with these changes will be that in the case of duplicate records the behaviour will change. If there are duplicates foreignRecord entries, where currently the last record that matches in the foreignRecords array will always be assigned with my changes the first will be assigned instead for OneToOne and ManyToOne. If there are duplicate nativeRecord entries, where currently all duplicates will receive the same foreignRecord they will now receive different ones and possibly no match will be found for duplicates in the case of OneToOne and OneToMany as the foreignRecord entries are removed as they are consumed.
Thoughts from anyone?
Hello :)
I have a few oneToOne table relationships where I always want the related data. Rather than having to remember to 'with' the related table each time, it would be nice to be able to specify when defining the relationship that the related table data is always fetched.
Alternatively, is there a recommended way to catch and modify the underlying calls to inject an additional 'with' in a custom subclass somewhere?
I'm not sure if here or the Orm repo is the best place for this issue / question / feature request but I figured I'd try here first :)
Thanks!
Hi all,
There's a performance issue with large many-to-many relationships due to very large numbers of calls to recordsMatch
. I've submitted PR #17 with a suggested approach to optimising the code that in my testing significantly reduced execution time. Comments and thoughts welcome :D
I am using the new Symfony Flex bundle. I have a long running process. I am creating a new row in a table, then waiting for a semaphore, and reading the row again as it has changed in the meantime.
Similarly, I want to be able to create a new row and then re-read it as MySQL executes a trigger that amends values. I am not able to retrieve the updated row values.
It seems the row is stored in Mapper::identityMap so I am getting back the original array passed through; not the updated row from the database.
I cannot see a way to force a refresh so the row is actually read from the database.
Thoughts?
When M:1 variant has missing variant, report the native mapper, the related name, and the missing variant name.
Hi,
How we can order the relationship ?
Example, if a have a "project" and associates "tasks", and each "task" has priority value.
I give tasks to project with 'with()' method, but I am unable to order the tasks by a column name.In Realtionship objects, i am able to filter with where with method '\Atlas\Mapper\Relationship\Relationship::where' but not ordering.
Thanks.
How can I create, from a MapperSelect, another MapperSelect to use in a join on the main query?
Right now I'm creating the 2 MapperSelects separated, then turning the second into a string and passing the bindvalues by hand.
The problem is that the bindings values colide, from the use of bindinline on both.
Something like:
/* @var $atlas \Atlas\Orm\Atlas */
$select = $atlas->select('table1')->(...);
$select2 = $atlas->select('table2')->(...);
$select2String = $select2->getStatement();
$select->join('INNER' , '('.$select2String.') as t2', 'table2.id = table.table2_id');
$bindValues = [];
foreach ($select2->getBindValues() as $bindKey => $bindValue) {
$bindValues[$bindKey] = $bindValue[0];
}
$select->bindValues($bindValues);
Results in:
select
*
from
table1
inner join (
select *
from table2
where
table2.id = :__1__
) t2 on t2.id = table1.table2_id
where
table1.id = :__1__
Table1 has a relationship to table2, but instead of using a simple join, I want to use a subselect to keep separated scopes. This is useful especially because I'm reusing the 2nd select.
Thank you for the help.
This may not be the repo to fix this in (it may be an issue building the query, not sure), so if I need to repost this issue somewhere else I'll be happy to do so. Just let me know.
Noted that when calling Mapper->fetchRecords(), that if all of the records are in the identity map, then a malformed sql string is built and an error is thrown.
Here's a minimal recreation:
$primaryKey = 'A_LEGIT_PRIMARY_KEY';
$mapper->fetchRecord($primaryKey); // primes the identity cache for illustration purposes.
$mapper->fetchRecords([$primaryKey]); // throws
The issue is that in Mapper.php:104 we're querying for all of the non-identity-map cached rows in the set ($this->table->selectRows($this->select(), $missing)
).$missing
is an empty array if we've already cached all of the records belonging to the primary keys we're interested in. The resulting sequel ends in a clause that looks like this: WHERE id IN ()
, which isn't supported, at least in MySQL 8 or 5.7.
My gut says that the preferable way to solve this is to allow for querying an empty set like this. I've seen suggested elsewhere that you drop-in replace WHERE {col} IN ()
with any clause that evaluates to false... so WHERE NULL IS NOT NULL
or something. You can do the inverse for NOT IN empty sets (WHERE NULL IS NULL
). I don't know where this code lives, though.
The other thought I had is to just hold back on the selectRows call when $missing
is empty. It's less preferable in my mind, but I think this largely depends on how uncomfortable you are with making the query builder smarter.
Let me know your thoughts.
Atlas.Mapper/src/MapperRelationships.php
Line 130 in e4e6234
Is this a mistake? Found this merely by accident :)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.