thecodingmachine / database.tdbm Goto Github PK
View Code? Open in Web Editor NEWThe Database Machine is a PHP ORM that requires no configuration. The object model is deduced at runtime from the database model.
The Database Machine is a PHP ORM that requires no configuration. The object model is deduced at runtime from the database model.
when some columns are reserved keywords, update / insert queries may break :
$bean->setOrder(1);
$dao->save($bean);
will throw a SQL Syntax error
It would be great to be able to sort a column from the ResultSet. This requires pushing the logic of generating SQL in the ResultSet object (which should be possible).
The generated DAOFactory is referencing DAOs that do not exist (DAOs for join tables)
In a BaseBean file:
if (!$stopRecursion) {
$array['parent'] = $this->getParent()->jsonSerialize(true);
}
need to check if the Parent is null
in src / Mouf / Database / TDBM / TDBMObject
When whe have an empty arrayObject the function isset does not detect it.
I don't really know your code but
when must use ->count of arrayObject
i don't know if it's a php bug due to
https://bugs.php.net/bug.php?id=61347 and https://bugs.php.net/bug.php?id=62059
Should be, the behavior of the issetSet is strange on arrayObject, but it's pretty inappropriate not beeing able to do isset on an empty object
It would be very nice if JSON
columns return a stdClass
instead of a string
(a bit like datetime
SQL type already returns a DateTimeImmutable
PHP Type)
When a foreign key points towards a join table. (With no other attribut than id and foreigne key), it's doen't work. Since this join table is not related to a beans.
Ex: a User
Bean that has embedds a City
one (user.city_id). This will generate the following setters/getters :
* get/setCityId(int $cityId);
* get/setCity(CityBean $city);
* get/setCityByCityId(CityBean $city);
The last two setters are named according to the referenced table (city), which is nice, but confusing when there is more than 1 FK pointing to the same table. Ex : user.city_id and user.birth_city_id, and also generates very long method names.
Would it be possible, ini next version to make something like that :
* get/setCityId(int $cityId);
* get/setBirthCityId(int $birtjCityId);
* get/setCity(CityBean $city);
* get/setBirthCity(CityBean $city);
... by looking for id_... or ..._id patterns in foreign keys columns. If those patterns are not found, then the accessors could just be named by the column (camelcase) name.
When creating a new ChildBean
, the Dao::save()
function will not insert the line in child_table
.
This seems to be due to the fact that there is no dbRow
field pointing to the child_table
.
If you pass a DateTimeImmutable object to DBAL, it fails.
Getting the following error when using a method using TDBMService :
Call to a member function findObjects() on null
When I run composer require mouf/database.tdbm
it gives error:
Your requirements could not be resolved to an installable set of packages.
Problem 1
- Installation request for mouf/database.tdbm ^4.2 -> satisfiable by mouf/database.tdbm[v4.2.0].
- mouf/database.tdbm v4.2.0 requires mouf/database.doctrine-dbal-wrapper ~1.1 -> satisfiable by mouf/database.doctrine-dbal-wrapper[1.1.x-dev] but these conflict with your requirements or minimum-stability.
Installation failed, reverting ./composer.json to its original content.
Should it not install dependencies itself?
When casting a TDBMObjectArray
, the returned array is empty (same issue type as internal json encode I guess... #12)
The order by is not possible for a field which is not in the select tables clause (when we have a request containing multiple join clause). I have this error :
"SQLSTATE[HY000]: General error: 3065 Expression #1 of ORDER BY clause is not in SELECT list, references column '..' which is not in SELECT list; this is incompatible with DISTINCT"
ext/weakref has not been migrated to PHP 7.
There is this new lib: "php-weak-lib"
It could be a good idea to migrate the old "weakref" code to the new "php-weak-lib" code.
Let's assume this code:
public function getUsersByManagerId($managerId)
{
return $this->find('contacts.manager_id = :id!', ['id' => $managerId]);
}
If the table 'contacts' does not exists (maybe its 'contact' instead), we get this error message:
1) Mouf\Database\TDBM\TDBMDaoGeneratorTest::testQueryNullForeignKey
Fhaculty\Graph\Exception\OutOfBoundsException: Invalid vertex ID
We definitely need to improve the error message (and maybe even suggest the right table name).
Run on the test database
$personDao = Mouf::getPersonDao();
// Let's get the list of users
$personList = $personDao->findAll();
// Let's display the names
foreach ($personList as $person) {
/* @var $person PersonBean */
echo $person->getName()."\n";
}
In dependant doctrine library, a DECIMAL
column is now bound to php type string
. Therefore, retrieving such a column will return a string
, ie a number properly formatted. However, once the column has been set, a float
will be returned as long as the object is cached. Future queries will return a string
again.
// table `foo` containing column `bar`: DECIMAL(10,2)
$fooBean = $fooDao->getById(1);
echo $fooBean->getBar();
// "4.20"
$fooBean->setBar(4.1);
echo $fooBean->getBar();
// 4.1
$fooBean->setBar("4.10");
echo $fooBean->getBar();
// 4.1
The issues inferred are both an approximative precision and an unstable number format.
(cd doctrine/dbal: 9f51afa2)
Edit: typing error corrected
Sometimes, there seem to be a cache on data model while generating the DAOs.
After a cache clear, everything works fine...
When I apply an orderBy in the tdbm method findFromSql it doesn't work.
Comment done during :
It would be great to be able to get only the first result.
Note: idea: we could also alter the ResultSet class with a first
method that returns the first row only.
List of features that would be great for TDBM 4.0:
DateTime
$contact->getAddresses()
)Hi,
Was going through the documentation https://github.com/thecodingmachine/database.tdbm/blob/4.2/doc/quickstart.md#discarding-parameters-automatically-with-magic-parameters and noticed some code ( Just above paragraph of the link provided ) like
php // NEVER DO THIS! $list = $this->find("name LIKE '".$firstLetter.'%"' );
The code is actually written inside div. So I am not sure if that can be fixed or it is using a different approach to show on website.
Just thought of bringing it here for I wasn't able to fix it .
select * from 'table' where 'col' is null never return anything
It should be ignored somehow.
The generated DAOs and Beans are not fully PSR-2 compliant.
We should:
Note: by default, PHP-CS-Fixer ensures PSR-2 + an additional set of rules. We are only aiming for strict PSR-2 compliance (no additional rules)
Table:
1, Department (id, label)
2, Beneficiary (id, department_habitation_id)
3, Mobility_department_beneficiary (beneficiary_id, mobility_department_id)
Idea:
We need to get DepartmentBean from table Beneficiary via foreign key "department_habitation_id",
and we could also get BeneficiaryBean and DepartmentBean from table Mobility_department_beneficiary via his two foreign keys.
Problem:
In generated DepartmentBaseBean, we got two functions with a same name, getBeneficiary():
` /**
* Returns the list of BeneficiaryBean associated to this bean via the mobility_department_beneficiary pivot table.
*
* @return BeneficiaryBean[]
*/
public function getBeneficiary() {
return $this->_getRelationships('mobility_department_beneficiary');
}
/**
* Returns the list of BeneficiaryBean pointing to this bean via the department_id column.
*
* @return BeneficiaryBean[]|AlterableResultIterator
*/
public function getBeneficiary() : AlterableResultIterator
{
return $this->retrieveManyToOneRelationshipsStorage('beneficiary', 'fk_beneficiary_2', 'beneficiary', [ 'beneficiary.department_id' => $this->get('id', 'departments') ]);
}`
In the section "More about the filter bag" there are bad syntaxes or old syntaxes:
$france = $this->getCountryListByFilter("countries.country_name='France'"); for "->"
new TDBM_EqualFilter replaced by new EqualFilter
new TDBM_OrderByColumn replaced by new OrderByColumn
It could be interesting to add an example about auto JOINING.
In the Quick start guide documentation we speack about tdbm in Mouf, and we begin with an example using "Mouf::getUserDao()". To increase Mouf understanding, I think it could be interesting to always bind an instance of the dao or of the daoFactory in examples.
In order to improve drastically memory consumption (for scripts), we would need to add support for weakrefs so that TDBMObjects referenced in the TDBMService are automatically freed if noone is referencing them.
Due to lazy loading, we need to force the filling of the array in jsonSerialize.
Images are not up to date.
I think some functions are deprecated (or removed), for example getNew() replaced by create() in "The DAOs structure".
Generated columns are the result of an automated calculation or JSON extraction (in mysql, but they also see to exists in MsSql).
Problem is, they are loaded into the dbRow
and therefore will be added for update or insert statements, which will trigger an error.
Note : it would be nice to keep the possibility to get the value :)
If you make an error of syntax, example:
date_start <= :endDate AND date_end => :startDate
The date_end must be date_end >= startDate
The message is Call to a member function walk() on null in vendor\mouf\magic-query\src\SQLParser\Node\AbstractTwoOperandsOperator.php150
Not really expressive
Get 2 lazily loaded bean on the same object.
Check that the same instance is returned.
Ideally, default values should be initialized in the bean constructor directly on new
.
Beans with default values (even if they are not nullable) should not result in compulsory parameters in the constructor.
Is it possible to add a function to get the sql query send to the server.
TDBM version: v3.3.0
I did a script that use the cursor mode for the fetch mode of tdbm service.
if ($isFilterBag == true) {
// If a filter bag was passer in parameter, let's perform a getObjects.
$objects = $this->getObjects($table_name, $filters, null, null, null, $className);
if (count($objects) == 0) {
return null;
} elseif (count($objects) > 1) {
throw new DuplicateRowException("Error while querying an object for table '$table_name': ".count($objects)." rows have been returned, but we should have received at most one.");
}
// Return the first and only object.
return $objects[0]; // FATAL ERROR HERE
}
Here is the stacktrace:
PHP Fatal error: Cannot use object of type Generator as array in /home/guillaume/projects/abcsalles_admin/vendor/mouf/database.tdbm/src/Mouf/Database/TDBM/TDBMService.php on line 369
PHP Stack trace:
PHP 1. {main}() /home/guillaume/projects/abcsalles_admin/src/scripts/calculate-object-score.php:0
PHP 2. ABCSalles\Services\ScoringService->calculateGlobalScore() /home/guillaume/projects/abcsalles_admin/src/scripts/calculate-object-score.php:20
PHP 3. ABCSalles\Dao\SalleDao->getByObject() /home/guillaume/projects/abcsalles_admin/src/ABCSalles/Services/ScoringService.php:51
PHP 4. ABCSalles\Dao\SalleDaoBase->getByFilter() /home/guillaume/projects/abcsalles_admin/src/ABCSalles/Dao/SalleDao.php:1454
PHP 5. Mouf\Database\TDBM\TDBMService->getObject() /home/guillaume/projects/abcsalles_admin/src/ABCSalles/Dao/SalleDaoBase.php:130
I guess that "$objects[0]" fails because its type is Generator instead of array. And I guess that its type is Generator because "$objects = $this->getObjects($table_name, $filters, null, null, null, $className);" is called with cursor mode, so a Generator object is returned.
Due to changes in composer, the logger-essentials package seems to cause problems now.
Since it is only used for its filter, we should consider inlining this filter logger in TDBM.
Note: we could simply copy this class:
https://github.com/phlib/logger/blob/master/src/LevelFilter.php
Otherwise, tables are not detected.
Add mapping between tables and beans' names which allows users not to specify className in request like tdbmService->getObjectsFromSql()
Example :
$users = $this->getListByFilter(...);
var_dump($users);
--> gives an empty TDBM Array even if SQL returns rows
Seems to be caused by broken lazy loading because when trying to access $users[0], IDE inspector returns a UserBean
and var_dump
is the expected...
Hello,
after few attempts if found there was recusion on objects.
The Dao of the project i work on is not from me but supposing it is a nice programmed Dao i may use bad my objects?
In fact in my controller I do the following:
$this->something = $this->daoFactory->getSomething Dao()->getList();
and in my view when I print_r($this->something) php detect recursion.
Do I do Something wrong?
In 4.0, each bean class name ends with "Bean". For instance: UserBean
.
Since the beans can be used as pure objects, it could be great to have a class names User
only.
In order to not wreak havoc, the best idea would be to build a naming strategy class/interface for beans and daos.
The $orderBy parameter of findObjects
may offer a vector of attack from SQL injection. It may be obvious, but most people don't realize this. TDBM should definitely check that parameters passed to orderBy in findObjects and findObjectsFromSQL are only colrefs.
In order to input an expression, we should require users to tell they know what they are doing (for instance by using a "new DangerousOrderBy('RAND()')" method.
Nice to have, add the option to serialize in php the bean object.
(Very interesting for the right plugin ;-) )
Example : A points to B through a.b_id foreign key AND also has a pivot table : AB that joins A and B in a many2many relationship.
TDBM will generate the same method twice in B Class : getA(), that returns a list of A, first one through a.b_id FK, and second one through AB pivot table
In the case of a many-to-many relationship, it would be nice to have a set method which would take an array of beans as parameter and would compare with the array of already linked elements (remove beans not in the parameter array and add beans not already linked).
In a LessFilter, if you pass a table name that doesn't exists, the method getListByFilter leads to an infinite loop.
I think that you must test before if the table exists and thus, throw an exception if not.
When I get a TDBMObjectArray
, and then ad it into a object I want to json_encode I get the following error :
Modification of ArrayObject during sorting is prohibited in D:\projets\ABCSalles\work\abcsalles\vendor\mouf\database.tdbm\src\Mouf\Database\TDBM\TDBMObjectArray.php on line 175
Unit test has been added : TDBMServiceTest::testTDBMObjectArrayInnerJsonEncode
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.