Adding a method to a collection or a response means subclassing, and subclassing a framework class means every place that constructs one has to know about your subclass.
Collection::macro('sumMoney', function (string $field) {
return new Money($this->sum($field), 'GBP');
});
Response::macro('csv', function (array $rows, string $name) {
return response()->streamDownload(function () use ($rows) {
$out = fopen('php://output', 'w');
foreach ($rows as $row) {
fputcsv($out, $row);
}
}, $name);
});
Registered in a service provider, available everywhere, and completely invisible to anyone reading the class — which is the trade. A macro is a global mutation of a shared type, so two packages defining the same name silently overwrite each other. Worth confining to a small number of well-named additions and documenting them in one place, because the alternative is a codebase where the collection class behaves differently depending on what is installed.