Laravel 8 custom foreign name with foreignId() - laravel-7

Laravel 7 introduced a shorter version of defining foreign keys with a function foreignId, but I can't find option to provide a custom name for that foreign ID.
In "old" way, we would wrote:
$table->unsignedBigInteger('user_id');
$table->foreign('user_id', 'custom_foreign_key_name')->references('id')->on('users');
New way:
$table->foreignId('user_id')->constrained();
But how to provide a "custom_foreign_key_name" in new way? Is it even possible?

example- You can add your table name inside constrained() :
public function up()
{
Schema::create('tutor_payouts', function (Blueprint $table) {
$table->id();
$table->foreignId('tutor_id')->constrained('users');
$table->foreignId('fee_id')->constrained();
$table->dateTime('payout_date');
$table->double('payout_amount', 8, 2);
$table->timestamps();
});
}
Reference: [https://laravel.com/docs/9.x/migrations#foreign-key-constraints][1]
If your table name does not match Laravel's conventions, you may specify the table name by passing it as an argument to the constrained method:
Schema::table('posts', function (Blueprint $table) {
$table->foreignId('user_id')->constrained('users');
});

Related

Shopware 6 Create a default entity in migration file

How can i store a default record using the migration file?
In symfony/doctrine there are a method like postUp() which is missing in shopware.
So how can i do this? The shopware doc provides a tutorial Creating data with a given ID, but i cannot initialize the needed repository.
So how can i access the entityRepository inside the migration class? Or is there another way to create a default record?
The recommended way is to just create the table in the migration file and then upsert the default records in the activate and update methods of the Plugin class. See answer by #dneustadt
Please read the comments to this answer for further information.
You can't use an EntityRepository inside a migration file. You can only use raw SQL queries by using the $connection variable which is passed to the update method.
Example:
<?php declare(strict_types=1);
namespace Swag\BasicExample\Migration;
use Doctrine\DBAL\Connection;
use Shopware\Core\Framework\Migration\MigrationStep;
use Shopware\Core\Framework\Uuid\Uuid;
class Migration1611740369ExampleDescription extends MigrationStep
{
public function getCreationTimestamp(): int
{
return 1611740369;
}
public function update(Connection $connection): void
{
// create table
$createTableSql = <<<SQL
CREATE TABLE IF NOT EXISTS `swag_basic_example_general_settings` (
`id` INT NOT NULL,
`example_setting` VARCHAR(255) NOT NULL,
`created_at` DATETIME(3) NOT NULL,
`updated_at` DATETIME(3),
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
SQL;
$connection->executeStatement($createTableSql);
// insert default setting
$insertDefaultSettingSql = <<<SQL
INSERT INTO `swag_basic_example_general_settings`
(`id`, `example_setting`, `created_at`)
VALUES (:id, :example_setting, NOW())
SQL;
$connection->executeStatement(
$insertDefaultSettingSql,
[
'id' => Uuid::randomBytes(),
'example_setting' => 'example_value',
]
);
}
public function updateDestructive(Connection $connection): void
{
}
}
Note: When using Connection instead of an entity repository you need to use Uuid::randomBytes() instead of Uuid::randomHex(). If you want to use an existing ID instead of a generated one you can use Uuid::fromHexToBytes('0fa91ce3e96a4bc2be4bd9ce752c3425')
Inside the Plugin extension you can access the DI container and get any public services including the repositories:
class MyPlugin extends Plugin
{
public function activate(ActivateContext $context)
{
$productRepository = $this->container->get('product.repository');
}
}

Association is in database, but can't be retrieved via DAL. Will retrieve empty array of associations

I am following the advanced developer tutorial (https://docs.shopware.com/en/shopware-platform-dev-en/how-to/indepth-guide-bundle).
Currently I'm at step 7, and according to the tutorial what I've made so far should work.
But it doesn't.
In the database it shows the association, but I can't retrieve them from the repository.
You have to add the association to the Criteria.
$criteria->addAssociation("name_of_association")
Without it, the associations come as null.
Okay, turns out I switched up two parameters by accident. When I set them correctly it worked as it should.
<?php declare(strict_types=1);
namespace Swag\BundleExample\Core\Content\Product;
use Shopware\Core\Content\Product\ProductDefinition;
use Shopware\Core\Framework\DataAbstractionLayer\EntityExtension;
use Shopware\Core\Framework\DataAbstractionLayer\Field\Flag\Inherited;
use Shopware\Core\Framework\DataAbstractionLayer\Field\ManyToManyAssociationField;
use Shopware\Core\Framework\DataAbstractionLayer\FieldCollection;
use Swag\BundleExample\Core\Content\Bundle\Aggregate\BundleProduct\BundleProductDefinition;
use Swag\BundleExample\Core\Content\Bundle\BundleDefinition;
class ProductExtension extends EntityExtension
{
public function extendFields(FieldCollection $collection): void
{
$collection->add(
(new ManyToManyAssociationField(
'bundles',
BundleDefinition::class,
BundleProductDefinition::class,
'product_id',
'bundle_id'
))->addFlags(new Inherited())
);
}
public function getDefinitionClass(): string
{
return ProductDefinition::class;
}
}
I'm talking about the 'product_id' and 'bundle_id'. In my case I had the 'product_id' as the last parameter.

Can't get CollectionField to work in EasyAdmin 3.0

I am trying to use "Tags" in my Account Entity.
So
I have Entity "Account"
I have Entity "Tag"
In "Account" Entity, I have
/**
* #ORM\ManyToMany(targetEntity=Tag::class, inversedBy="accounts")
* #ORM\JoinTable(name="account_tag")
*/
private $tags;
In "Tag" entity I have
/**
* #ORM\ManyToMany(targetEntity=Account::class, mappedBy="tags")
*/
private $accounts;
In my AccountCrudController => ConfigureFields, I use "CollectionField" for my "tags" property
public function configureFields(string $pageName): iterable
{
return [
TextField::new('name'),
AssociationField::new('owner'),
AssociationField::new('parent'),
CollectionField::new('tags'),
];
}
I am getting below
[Expected value of type "App\Entity\Tag" for association field "App\Entity\Account#$tags", got "string" instead.1
You should be able to use an AssociationField here as well, which would fit your purpose.
AssociationField::new('tags') will allow you to reference existing Tags.
If you wish to create all new Tags together, you could use something like this as there is no way to add Tags on the fly in the AssociationField at the moment.
Have you tried setting your CollectionField like this:
CollectionField::new('tags')
->allowAdd()
->allowDelete()
->setEntryType(TagType::class)
;
The important part is the TagType where you define your own FormType. I am also trying to implement this feature, so if you have a fully working example, let us know!
public function configureFields(string $pageName): iterable
{
return [
TextField::new('name'),
AssociationField::new('owner'),
AssociationField::new('parent'),
CollectionField::new('tags')
->SetEntryType(Tag::class)
];
}

How to hardcode the entity varchar value?

The requirement is to store the hardcoded value for varchar which is in an entity file(.eti). I tried adding to the default option but it is not reflecting.
Default option works well with boolean values (true/false), typelists (you can choose a default typecode), monetary amounts too, but it looks like it is not allowed to specify a default varchar.
Therefore the easiest way would be to create a preupdate rule which inserts that default value every time when you create a new record in the database.
Preupdate rule example:
#gw.rules.RuleName("YourEntityAssignDefaultValue")
internal class YourEntityAssignDefaultValueRule {
static function doCondition(yourEntity : entity.YourEntity) : boolean {
return yourEntity.New
}
static function doAction(yourEntity : entity.YourEntity, actions : gw.rules.Action) {
yourEntity.yourColumn = "defaultValue"
}
}
you can achieve through getter and setter properties in an appropriate enhancement class.
public property get PolicyNumber(): String {
return this.PolicyNumber }
and somewhere class you must be assigned the value to the PolicyNumber field then it will reflect.

Access parameter from a resource defined using create_resources

I would like to know if it is possible to access a parameter from a class being instantiated using the create_resources function. I want to use that parameter in other class to conditionally install some things or not.
This is my scenario:
define myResource($myParam) { ... }
create_resources(myResource, $hashResources)
$hashResources = { "MyResource1" : { "myParam" : 1 },
"MyResource2" : { "myParam" : 2 }
}
myFancyPuppetClass($nameOfResource) {
if(******myParam from the resource defined with name $nameOfResource in the same catalog******) { ... }
}
Is this possible? If it is, how can I do the reference? Thank you!
Since the resources you are attempting to create are defined types, and the parameters in a defined resource are not accessible, this is not possible in the latest version of Puppet.
See a previous answer of mine regarding accessing parameters in defined resources for an alternative.

Resources