Add element to array of form controls in cakephp 4.4

I have two tables with a belongstomany association (Contributions and Receipts, join table ContributionsReceipts) I want to go adding one Contribution by one by clicking on a button, this is the structure of ContributionsReceitps:

CREATE TABLE IF NOT EXISTS `contributions_receipts` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `receipt_id` int(11) NOT NULL,
  `contribution_id` int(11) NOT NULL,
  `concept_id` int(11) NOT NULL,
  `reference` varchar(200) NOT NULL,
  `amount` decimal(10,2) NOT NULL,
  `created` datetime NOT NULL,
  `modified` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

I want to select one contribution, one concept, enter the reference and the amount and finally click on a button to add these controls to an array of controls so that I can save each contribution with its data in the join table, is there a way to do that?

I don’t understand your question.

Do you want to add these at 1 go ?

  1. Create a new Receipt entity
  2. Select a Contribution from a drop-down list
  3. Select a Concept from a drop-down list
  4. Enter data for reference & amount

Yes, that’s exactly what I want to do

I did it before in Cake4, so here is generally what to do. It is a bit of a hack, and I am not sure whether this is the proper way to do it.
I have not tested the code below, but it is a good guide to get you started.

// In /templates/Receipts/add.php
// todo. Create your Receipt-form (like how it is done normally)
$this->Form->control(....)


// This is the 'hack' part, to link the 'belongsToMany' association. This will add 10 items
for( $index = 0;  $index < 10; $index++) {
	$this->Form->control( "Concepts[$index]._joinData.concept_id", [ 'type' => 'select', 'options' => $yourConceptsSelectionDataHere ] );
	$this->Form->control( "Contributions[$index]._joinData.contribution_id", [ 'type' => 'select', 'options' => $yourContributionsSelectionDataHere ] );
	$this->Form->control( "Concepts[$index]._joinData.amount", ['min' => 0] );
	$this->Form->control( "Concepts[$index]._joinData.reference", );
}

// todo. Complete the rest yourself.


Then in the controller

// In the ReceiptsController.php
// note that the associated needs to be as such
$data = $this->Receipts->patchEntity($receipt, $receivedData, [
	'associated' => [
		'Concepts._joinData', 'Contributions._joinData', 
		// todo. add on your others
	],
);

// See how the object/array is formed, so you get an idea on how to work on it.
debug( $data ); 

That’s not how I want to do it, what I want is to go adding one by one clicking on a button after I select and enter all the data requiered to save the receipt

It’s not clear whether you’re looking for a “one page” sort of thing where new fields are added without a reload when you click something and then you save all of them at once, or you fill in a “standard” form with one detail, then submit that form and it loads a new page with a fresh form for you to do it again.

The first option: one page where new fields are added without a reload when I click a button and then save all of them at once.

You need to use javascript to create the fields

Yes, JavaScript is required. You might do something like have a template in the JS code for what the fields look like, and replace some placeholder in it with the next available array index (maybe another JS variable required to remember the current one), and then add that after the latest one every time the “add” button is clicked. Many other ways of doing it, including Ajax calls. What is best for your situation will depend on your specifics and preferences.