I'm fairly new to OOP and I'm struggling with setting up my classes. I'm working on a project where I have the following classes: dogTag
, dog
, user
.
This is my current dogTag
class:
class DogTag
{
const POST_TYPE = 'dog-tag';
private ?int $id = null;
private string $number;
private ?Dog $dog;
private ?User $user;
private bool $isActive = false;
private bool $isLost = false;
private string $generationDate;
private ?string $activationDate;
private string $productionStatus;
public function __construct($id = null, string $number, ?Dog $dog = null, ?User $user = null, bool $isActive, bool $isLost, string $generationDate, ?string $activationDate, string $productionStatus)
{
$this->id = $id;
$this->number = $number;
$this->dog = $dog;
$this->user = $user;
$this->isActive = $isActive;
$this->isLost = $isLost;
$this->generationDate = $generationDate;
$this->activationDate = $activationDate;
$this->productionStatus = $productionStatus;
}
Let me explain the functionality of the dog tag. Dog Tags are being generated by a generator and stored into the database. So a dog tag only needs the following arguments when being generated: number
(this is a unique generated number and not a unique database ID), isActive
, isLost
(could be optional), generationDate
, productionStatus
. All other arguments are not necessarily needed for the generation.
So my first question is: "Do I need to set the optional arguments in the contructor?".
Let me explain why I did this for the moment. When a user receives the unique dog tag number they can activate the dog tag. Therefor I use a method called activateDogTag
. For a dog tag to be activated it needs to be attached to a user. Therefor I use the $user
argument in the constructor.
Here comes my second question: "Should I use a method setUser(User $user)
where I inject the user object into the dogtag
class?".
Another problem that I'm struggling with is that I also use an id
argument. This will be a bit harder to explain why I'm using this and why it feels wrong.
I'm also using the dogTag
class to I can instantiate it with all the data from the database. For the moment I have a static DogTag::get($id)
method. This class grabs the data from the database by the ID an instantiates a new DogTag
class where I fill all the arguments with the data received from the database.
For information: I'm using WordPress)
public static function get($postId): ?DogTag
{
$post = get_post($postId);
if (empty($post)) {
return null;
}
$dogTagId = $post->ID;
$generationDate = $post->post_date;
$dogTagNumber = get_post_meta($post->ID, 'dog_tag_number', true);
$dogId = get_post_meta($post->ID, 'dog_id', true);
if (empty($dogId)) {
$dog = null;
} else {
$dog = Dog::get($dogId);
}
$userId = $post->post_author;
$user = $userId ? User::get($userId) : null;
$isActive = get_post_meta($dogTagId, 'dog_tag_is_active', true);
$isLost = get_post_meta($dogTagId, 'dog_tag_is_lost', true);
$activationDate = get_post_meta($dogTagId, 'dog_tag_activation_date', true);
$productionStatus = get_post_meta($dogTagId, 'dog_tag_production_status', true);
$dogTag = new self($dogTagId, $dogTagNumber, $dog, $user, $isActive, $isLost,
$generationDate, $activationDate, $productionStatus);
$dogTag->post = get_post($postId);
return $dogTag;
}
This way all the arguments are filled and are available within the class.
So where am I going wrong and what I'm I doing correct? The problem is that I can't really find any solution in my online courses for these problems as they don't go this deep.
Where I'm also struggling is eg with the static activation class (DogTag::activateDogTag):
public static function activateDogTag()
{
// Here goes the form
$dogTag = self::getDogTagByDogTagNumber('4OV9NHOPXLAB6X9B');
// $dogTag = self::getDogTagByDogTagNumber('VBD6JZODTZ6L4YU7');
if (!$dogTag) {
var_dump('no dog tag with this ID found');
}
if(true == $dogTag->getIsActive()) {
var_dump('Dog Tag is already active');
}
if ($dogTag->getUser()) {
var_dump('user is set');
return;
}
var_dump('Activate');
$userId = get_current_user_id();
if (0 === $userId) {
var_dump('not logged in as a user');
}
$dogTag->setIsActive(true);
$dogTag->setUser($userId);
$user = $dogTag->getUser();
var_dump($dogTag);
// Update dog Tag
$args = [
'post_type' => 'dog-tag',
'post_status' => 'publish',
'post_title' => $dogTag->getNumber(),
'post_date' => $dogTag->generationDate,
'post_author' => $dogTag->getUser()->getId(),
'meta_input' => [
'dog_tag_number' => $dogTag->getNumber(),
'dog_tag_is_active' => $dogTag->getIsActive(),
'dog_tag_is_lost' => $dogTag->getIsLost(),
'dog_tag_production_status' => $dogTag->getProductionStatus(),
]
];
var_dump($args);
$postId = wp_update_post($args);
$dogTag->setId($postId);
return $dogTag;
}
Is this a good practice:
$dogTag->setIsActive(true);
$dogTag->setUser($userId);
$user = $dogTag->getUser();
and after the data is stored into the database via wp_update_post
by setting the id
property via DogTag->setId($postId)
?
My Answer:
It seems like you are on the right track with your OOP approach, but there are a few things that could be improved in your code.
1. Constructor:
- You mentioned that some arguments in the constructor are optional, but they are required for certain functionalities. In this case, it might be better to have separate methods to set these optional arguments when needed, rather than including them in the constructor. This will make your constructor cleaner and more focused on essential properties.
2. setUser method:
- It's a good practice to have a separate method like setUser to set the user for a dog tag. This way, you can ensure that the user is properly associated with the dog tag and maintain the integrity of your data.
3. Using ID:
- It's common to use an ID property in your class to uniquely identify instances, especially when dealing with database records. However, make sure to handle the ID properly and consistently throughout your code to avoid any inconsistencies.
4. Activation logic:
- The activation logic in your activateDogTag method seems fine, but you can improve it by separating the activation process into smaller, more focused methods. This will make your code more modular and easier to maintain.
5. Updating database:
- It's good practice to update the database after making changes to your object's properties. However, make sure to handle database operations carefully and consider using transactions to ensure data consistency.
Overall, it's important to keep your classes focused on their core responsibilities and avoid adding unnecessary complexity. Refactoring your code based on these suggestions can help improve the readability, maintainability, and overall quality of your OOP design.
Rate this post
5 of 5 based on 9050 votesComments