-
Notifications
You must be signed in to change notification settings - Fork 21
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
Issues with 'with()' #19
Comments
Hi, A question before I further dig: did you modify the factories after baking them? If yes, please kindly share the code of all 3 factories. This will help me provide you a solution to your two issues. |
InvoicesFactory was not modified, I only added some default data to CustomersFactory using faker such as username, password etc. I will add the exact code later this day |
The saving of belongsTo associations is covered by the package, so I do not see for the moment where the issue comes from. The package's tests cover a similar case here: https://github.com/pakacuda/cakephp-fixture-factories/blob/master/tests/Factory/AddressFactory.php Where the AddressesTable belongs to a City. Tests pass when calling For example in this test:
|
Here are my three factories: InvoiceFactory.php class InvoiceFactory extends CakephpBaseFactory
{
protected function getRootTableRegistryName(): string
{
return 'Invoices';
}
protected function setDefaultTemplate(): void
{
$this->setDefaultData(function(Generator $faker) {
return [];
});
}
public function withCustomers(array $parameter = null): InvoiceFactory
{
return $this->with(
'Customers',
\App\Test\Factory\CustomerFactory::make($parameter)
);
}
public function withDeliveryAddresses(array $parameter = null): InvoiceFactory
{
return $this->with(
'DeliveryAddresses',
\App\Test\Factory\DeliveryAddressFactory::make($parameter)
);
}
} CustomerFactory.php class CustomerFactory extends CakephpBaseFactory
{
protected function getRootTableRegistryName(): string
{
return 'Customers';
}
protected function setDefaultTemplate(): void
{
$this->setDefaultData(function(Generator $faker) {
return [
'name' => $faker->name,
'login' => $faker->userName,
'password' => $faker->password
];
});
}
public function withInvoices(array $parameter = null, int $n = 1): CustomerFactory
{
return $this->with(
'Invoices',
\App\Test\Factory\InvoiceFactory::make($parameter, $n)->without('Customers')
);
}
} DeliveryAddressFactory.php class DeliveryAddressFactory extends CakephpBaseFactory
{
protected function getRootTableRegistryName(): string
{
return 'DeliveryAddresses';
}
protected function setDefaultTemplate(): void
{
$this->setDefaultData(function(Generator $faker) {
return [
'address' => $faker->address
];
});
}
public function withInvoices(array $parameter = null): DeliveryAddressFactory
{
return $this->with(
'Invoices',
\App\Test\Factory\InvoiceFactory::make($parameter)
);
}
} Here are requested outputs: InvoiceFactory::make()->withCustomers()->getEntity()->toArray(); results in an empty array [] The line below CustomerFactory::make()->with('Invoices.DeliveryAddresses')->getEntity()->toArray(); results in [
"name" => "John Doe",
"login" => "bernhard.gilda",
"password" => "$2y$10$5snFBm8XALfTU6AKCQxy4eZ6KXD0NqLGdCEnNwQpOesfKZTG3PmH2",
"invoices" => [
[],
],
] My invoices table for now only has the following fields: id, customer_id, delivery_address_id, created, modified. Only the first two are required. I do not really understand your third point. CakePHP conventions are clear that association names are plural and so are their table names. If i singularize my association from Customers to Customer, Cake will look for the table called customer instead of customers which produces errors. |
Regarding the third point, you simply have to set the key |
All right i managed to resolve the first issue with renaming the association as you pointed out. Now it gets correctly saved. CustomerFactory::make()->with('Invoices.DeliveryAddresses')->persist(); |
I found out that when using DeliveryAddressFactory::make()->with('Invoices.Customer')->persist(); All three entities are correctly saved. I have no idea why it does not work the other way. |
How about if you singularize the association There might be an issue in the package, the saving should work regardless of the name of the association. But if this worked, you could at least keep on working for the moment. I'll be able to search for a bug only by next week. |
Tried that, no effect |
I found out that association saving really does depend heavily on association name. Especially whether it's plural or singular. After setting all properties in my entities to accessible with protected $_accessible = [
'*'=> true
] i noticed that sometimes the association ends as an array istead of an entity instance with incorrect property name. I would seem that FixtureFactory does not extract the correct property name from association, especially hasOne/belongsTo. |
I have found that the native singularization/pluralization of 'Address/Addresses' is un predictable. I've had to add this rule:
and make sure it gets run in both my app and the testing bootstrap |
@rtrochim Do you have a concrete example illustrating that? I agree with dreamingmind. |
I have fixed the issue of non saved plural toOne association. As described in the documentation here: https://book.cakephp.org/3/en/orm/saving-data.html#saving-belongsto-associations the associated data should be singular, which the package did not consider. This is now fixed, you may update the package with its latest version. I personally prefer naming my toOne associations singular, but if you don't, feel free rename your associations plural, and please let me know if it worked for you. I will close this issue in three days, if this alright for you. |
Everything now works correctly. |
I have models: Customers, Invoices and DeliveryAddresses
CustomersTable.php:
InvoicesTable.php:
DeliveryAddressesTable.php
I baked my factories as in the docs
In one of my test cases, when i do:
I get both models saved correctly
However if i do:
I get the following error:
CakephpFixtureFactories\Error\PersistenceException : Error in Factory App\Test\Factory\InvoiceFactory.
Message: SQLSTATE[HY000]: General error: 1364 Field 'customer_id' doesn't have a default value
What am i doing wrong?
Another issue is when i try to make a deeper association.
As in the tutorial
The Customer and Invoice are correctly saved. However delivery_address_id can be NULL, so the DeliveryAddress record is not created, and delivery_address_id in Invoice is NULL. When i force it to NOT NULL in database, i get the following error:
CakephpFixtureFactories\Error\PersistenceException : Error in Factory App\Test\Factory\CustomerFactory.
Message: SQLSTATE[HY000]: General error: 1364 Field 'delivery_address_id' doesn't have a default value
How do i make this work?
Thanks in advance!
The text was updated successfully, but these errors were encountered: