Reputation: 5395
I'm using Slim Framework version 3.
I've followed the tutorial on creating an app. Part of this involves setting up a classes
directory where you can put your own PHP classes.
What I can't understand is how you can access Slim inside those. For example if I have a class src/classes/Users.php
and wanted to use the Slim Response code e.g.
return $response->withStatus(302)->withHeader('Location', 'login');
Obviously, $response
, is not accessible at that point. It only seems to be in index.php
where each callback recieves it as an argument.
Do I have to pass something to every constructor of my own classes, or use
or require
statements in my classes?
Upvotes: 0
Views: 691
Reputation: 1579
I'd say when domain layer components need to access application level components - this is a code smell. So, consider doing things otherwise, request object describes request. Request contains some data, and that data should be passed to your User
class, not request object itself.
If you still wish to use Request
object in Users
class, simply pass it as argument, like this:
// in your routes
$app->post('users', function($request, $response) {
$user = new User;
$user->hydrateAndPersist($request); // there you pass it as argument
});
// in your user class
class User
{
public function hydrateAndPersist(
\Psr\Http\Message\ServerRequestInterface $request,
\Psr\Http\Message\ResponseInterface $response // yes, you force yourself into injecting response object
) {
// request is here, let's extract data from it
$submittedData = $request->getParams();
// terrible indeed, but this is just an example:
foreach ($submittedData as $prop => $value) {
$this->prop = $value;
}
$result = $this->save();
return $response->withJson($result);
}
}
However, in this case your User
class is coupled heavily with PSR-7 request and response objects. Sometimes coupling is not a problem, but in your case User
class belongs to domain layer (since it describes User entity), while $request
and $response
are components of application layer.
Try to reduce coupling:
$app->post('users', function($request, $response) {
$submittedData = $request->getParams();
$user = new User;
$result = $user->hydrateAndPersist($submittedData);
// response is already declared in this scope, let's "put" result of the operation into it
$response = $response->withJson($result);
return $response;
});
class User
{
public function hydrateAndPersist(array $data) : bool
{
$result = false;
foreach ($submittedData as $prop => $value) {
$this->prop = $value;
}
$result = $this->save();
return $result;
}
}
See the benefit? User::hydrateAndPersist
now accepts array as argument, it has no knowledge of $request
and $response
. So, it is not tied to HTTP (PSR-7
describes HTTP messages), it can work with anything. Classes separated, layers separated, ease of maintenance.
To sum up: you can access $request
object in your User
class by simply passing $request
to one of User
methods. However, this is poor design that will reduce maintainability of your code.
Upvotes: 1