Is it possible to define a public method in a base class without limit the parameter's type and how many parameters input?

The reason you are getting the incompatible signature error is because again. You are trying to declare saveRecord as public. The solution I posted will ONLY work if saveRecord is declared private. At which time phpstorm is not going to show him the method anyway, since technically the method is not visible to the extending class. The point is to be able to declare saveRecord with an entirely different signature and php not die because of it. This is bad practice in the best of circumstances and to be trying to implement to solely provide a means of auto completion within the IDE is beyond bad practice so I provide a different solution below that is just as flexible, but with a much better implementation.

Because of these limitations it is always better, at least for me, to have my “save” methods accept an Entity class. I myself prefer to use the ReflectionHydrator for populating and extracting the entity props for use in a Gateway class because that allows me to have all private class props for the entity class without having to bloat the code with a bunch of public getters and setters. A bonus to this is that you can use the same approach and classes with Laminas form which means you can pass $form->getData() directly to your saveRecord() method once have all the pieces in place.

So ideally, in your use case you would have something like a RecordInterface to represent the record(s). I have no idea how many types of records you have but all of the different implementers would implement RecordInterface. You would then type your saveRecord(RecordInterface $record).

In your abstract/parent class saveRecord method you would then have something like:

final public function saveRecord(RecordInterface $record): YourReturnType
{
     $set = (new ReflectionHydrator())->extract($record);
     // $set is now an array of all of the properties of the $record instance and can be passed to 
     // insert/update
}

You vary what is provided in the $set array by providing differing properties in your RecordInterface implementers. The final modifier prevents extending classes from overriding the saveRecord method.

Another thing I will note here is that your UtilsFuncs should not be passed as an argument. It should be considered a class dependency and injected into the construct of the MessageboardTable class. I generally avoid having request objects in gateway classes.

In other words in your provided example Messageboard would implement RecordInterface and would have a $ip property. There is several different hydrating strategies that could be used to populate Messageboard, or it could simply extend StdLib\ArrayObject etc. A lot of different ways to handle that. Those are up to you really. If you use the ArrayObject approach then inside saveRecord $set = $record->getArrayCopy(); instead of using a hydrator and extract. My point is that your $record should be ready to save by the time it is passed to saveRecord.

Hope it helps :slight_smile:

thanks for your reply!

pass $form->getData() directly to my saveRecord() functions seems good. I don’t know why the official documentation shows an entity passed into saving logic.

If the entity is bind to the form then the data is extracted and hydrated by the form. The method getData is not needed in this case.

1 Like

you are right, there is a exchangeArray function.
Maybe my demand is abnormal. I should save just data, any other logic is not doing here. and prepare the data before.