How to call Service from legacy code?

I used some parts of the “Slim 4 eBook Vol. 1” (Actions, Services, Repositories, Factory), that works well (PHP 7.4), e.g.

routes.php:

<?php
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Routing\RouteCollectorProxy;
...
$app->group  ('/v1', function (RouteCollectorProxy $group) use ($app) {
	...
	$group->get    ('/companies/{id}/addons/eventcalendar/events/{eventId}', \App\Action\Addons\EventCalendar\EventsDetails::class);
	...
});

\src\Action\Addons\EventCalendar\EventsDetails.php:

<?php
namespace App\Action\Addons\EventCalendar;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;
use App\Domain\Addons\EventCalendar\EventsService;
use App\Renderer\Json;

final class EventsDetails {
	private EventsService $service;
	private Json $renderer;
	public function __construct (EventsService $service, Json $json) {
		$this->service = $service;
		$this->renderer = $json;
	}
	public function __invoke (Request $request, Response $response, array $args): Response {
		$id = (int) filter_var ($args['id'], FILTER_SANITIZE_NUMBER_INT);
		$eventId = (int) filter_var ($args['eventId'], FILTER_SANITIZE_NUMBER_INT);
		$result = $this->service->getById ($eventId);
		return $this->renderer->json ($response, $result['errors']['status'] ?? 200, $result);
	}
}

\src\Domain\Addons\EventCalendar\EventsService.php:

<?php
namespace App\Domain\Addons\EventCalendar;
use App\Domain\Addons\EventCalendar\EventsRepository;
final class EventsService {
	protected array $myConfig, $myRequest;
	private EventsRepository $repository;
	private array $event = [];
	public function __construct (EventsRepository $repository) {
		$this->repository = $repository;
	}
	public function getById (int $id): array {
		return $this->event = $this->repository->getById ($id);
	}
	...
}

\src\Domain\Addons\EventCalendar\EventsRepository.php:

<?php
namespace App\Domain\Addons\EventCalendar;
use App\Factory\QueryFactory;
final class EventsRepository {
	private QueryFactory $queryFactory;
	private string $tableName = 'eventCalendarEvents';
	public function __construct (QueryFactory $queryFactory) {
		$this->queryFactory = $queryFactory;
	}
	public function getById (int $id): array {
		$result = $this->queryFactory->getRow ($this->tableName, '*', [ 'id' => $id ]);
		return empty ($result) ? [] : $result;
	}
	...
}

\src\Factory\QueryFactory.php:

<?php
namespace App\Factory;
use \PDO;
use Psr\Container\ContainerInterface;
class QueryFactory {
	private ContainerInterface $container;
	private \PDO $pdo;

	public function __construct (ContainerInterface $c) {
		$this->container = $c;
		$this->pdo = $this->container->get ('db');
	}
	public function getRow (string $table, string $field, $where): array {
		$params = ...;
		$sql = 'SELECT ...';
		$stmt = $this->pdo->prepare ($sql);
		$stmt->execute ($params);
		$result = $stmt->fetch ();
		return $result !== false ? $result : [];
	}
}

But i do have working legacy code in many other classes, called from the same routes.php and separate Actions, but without the structure above - only with access to the PDO object.

How can i call a new service method (in EventsService.php) like “$this->service->getById ($eventId)” from legacy “nonservice” classes?

Kind regards,
Eduard Müller

Hi!

How can i call a new service method (in EventsService.php) like “$this->service->getById ($eventId)” from legacy “nonservice” classes?

This depends, but generally you could refactor this legacy classes by declaring the required classes within the constructor of these legacy classes.

Yes, i tried that and it’s working fine :-).

But with the change of the constructor, i have to change (refactor) all other depending classes (which calls the refactored class and so on). Over one hundred classes with lots of dependencies - a hell lot of nice work.