I am using Cassandra with heavy denormalization so I cannot use some kind of universal class to delete/add/update/etc.. objects since every type of object has its own list of tables that needs to be changed.
For example to delete User I will need to touch 3 tables, not just one. To delete Item I will need to touch 7 tables, etc.. It means that logic is completely different based on object type.
Scenario 1
User class contains only fields that I need (id, name, etc..) and static functions to find users, delete users etc..
<?php
class User {
private $id;
private $name;
// Magic getters and setters removed to save space here
public static function delete($id) {
// find user by id
// delete that user
}
}
Scenario 2
User class has everything - fields (id, name, etc..) and also functions that will delete/edit/create/etc.. that particular user
<?php
class User {
private $id;
private $name;
// Magic getters and setters removed to save space here
public function delete() {
// find user by $this->id
// delete that user
}
}
Which scenario is better and maybe there is some other way to do this that is even better?
I vote #2.
The main thing is to choose one, be clear why and stick to it. Things are going to get very confusing if you mix these approaches or you are not clear about why you have chosen a particular approach.
I Scenario 2 because its clear what you are deleting, its always related to $this.
Also in Scenario 2 your delete method needs less validation as this validation can be offloaded to the constructor, or simple check if $id is set before deleting the object or database row.
In Scenario 1 though you would need to take $id and check that is exists before attempting to remove it in order to be sure you are actually removing something. You could also return the number of rows deleted too, which could be validation in itself too. But in the future this validation may be more complex than just checking what is being deleted.
Better to let the construction or a load() function deal with as much of the validation.
Related
I need to extensively use statuses in mt project. I need them for my users (active, suspended, etc), an entity (active, pending_activation, inactive) and for my subscriptions(active, on_grace_period, not_subscribed, never_subscribed).
So far I thought that the best way is to store them in the DB but i have a feeling it's much easier to have them in the other 3 options.
I also thought that i can store them in my Eloquent Model as constants. For example my subscription model would look like this:
// SubscriptionModel
const SUBSCRIBED_ACTIVE = 1;
const SUBSCRIBED_ON_GRACE_PERIOD = 2;
const NOT_SUBSCRIBED = 3;
const NEVER_SUBSCRIBED = 4;
and retrieving them, for example in a blade view:
// subscription/index.blade.php
#if($user->subscription->status == /App/SubscriptionModel::SUBSCRIBED_ACTIVE)
<div>You are subscribed. Thank you</div>
#elseif($user->subscription->status == /App/SubscriptionModel::NEVER_SUBSCRIBED)
<div>You need to create a subscription before being granted full access!</div>
#elseif(...)
// and so on
How about doing the same but using the config folder and adding a file called status.php. Accessing it in the view would be like:
#if($user->subscription->status == Config::get('status.subscription.SUBSCRIBED_ACTIVE'))
<div>You are subscribed. Thank you</div>
#elseif(...)
// etc
Is there a better way?
Also, how about the other part of the equation, meaning the status stored in the DB. Should I only have a status column for the subscription table and store what the app dictates or even bettter create a separate table subscription_statuses and have a foreign_key subscription_status_id in the subscriptions table?
I tend to create a specific model for statuses, that acts as an enum. So if I have an Event model, I may have a corresponding EventStatus model that looks like this:
class EventStatus
{
public const CANCELLED = 'EventCancelled';
public const POSTPONED = 'EventPostponed';
public const RESCHEDULED = 'EventRescheduled';
public const SCHEDULED = 'EventScheduled';
}
I can then do checks like this:
$event->status === EventStatus::CANCELLED;
And I’ll usually add convenience methods to my models too:
class Event extends Model
{
public function isCancelled(): bool
{
return $this->status === EventStatus::CANCELLED;
}
}
For the “human-friendly” strings, I’ll then have a language file that has the text strings:
<?php // resources/lang/en/event_status.php
return [
EventStatus::CANCELLED => 'Cancelled',
EventStatus::POSTPONED => 'Postponed',
EventStatus::RESCHEDULED => 'Rescheduled',
EventStatus::SCHEDULED => 'Scheduled',
];
In my applications I do similar to #Martin Bean except I don't create separate classes for status, I store that inside the existent class/Model.
I'm going to call user, subscription and entity a entity.
Entity have a status that exists in it's Model and table in the database.
Each Model have constants of possible values of status like ACTIVE, INACTIVE, PENDING, etc, and those may vary for each Model.
Create methods for dealing with it like getStatusLabel(), listStatus(), isActive(), isX(), etc.
Those isActive/X() are only created if really necessary, maybe a Model have 4 status but you only do comparisons against one specific, so I'd create only one isX() for that status.
Example
class User
{
const STATUS_ACTIVE = 1;
const STATUS_SUSPENDED = 2;
const STATUS_INACTIVE = 3;
/**
* Return list of status codes and labels
* #return array
*/
public static function listStatus()
{
return [
self::STATUS_ACTIVE => 'Active',
self::STATUS_SUSPENDED => 'Suspended',
self::STATUS_INACTIVE => 'Inactive'
]
}
/**
* Returns label of actual status
* #param string
*/
public function statusLabel()
{
$list = self::listStatus();
// little validation here just in case someone mess things
// up and there's a ghost status saved in DB
return isset($list[$this->status])
? $list[$this->status]
: $this->status;
}
/**
* Some actions will happen only if it's active, so I have
* this method for making things easier.
* Other status doesn't have a specific method because
* I usually don't compare agains them
* #return Boolean
*/
public function isActive()
{
return $this->status == self::STATUS_ACTIVE;
}
}
I do not agree with the other answers. Your status information should be stored in the database. A well designed database should be clear and usable without the application. What happens if you decide to use this database to power something like a mobile application as well? You will be taking some of the information away from the database and storing it only in Laravel, meaning you would have to duplicate that list of statuses in your mobile application too, and maintain it across the two.
This kind of information should be stored in the database.
Option 1
If your users can only ever have one status, then you should use an enum field with the values subscribed, subscribed-grace, not-subscribed, never-subscribed
This is just as simple in your views:
#if($user->subscription->status == 'subscribed'
Option 2
If however, you might have multiple statuses, then you should almost certainly have a separate field for each status, and use a TINYINT to store a 1 or 0.
Separate status table?
I cannot see a good reason to use a separate status table unless you anticipate you might add many more statuses, and even if you are adding more, you can just add new values to the enum or add a new field depending on which option would suit.
A status table would be ideal if you plan to use the statuses for many other tables in the database besides users.
The only other reason for a seperate status table would be if you decided to change the meaning of a particular status. This would mean you could rename the status in the status table, but the users would still be linked to it via it's primary key. Changing the meaning of a status with the previous two methods would involve changes to the structure.
It really comes down to how you anticipate you will use them, but there is no reason not to keep them in the database.
There are advantages and disadvantages to each method. It's good to be aware of each.
Table - Pros and cons (AJReading's method):
Adding and maintaining a table SEEMS tedious
Just having another table and model can make our code feel more cluttered (not saying it's a good reason not to use just saying it's kinda true)
It gets awkward when we have application logic dependent upon something in the database (things in the database feel like they should be variable, when we base application logic on them they're required)
Now we have migrations, but before them these used to be the bane of developers existence (they would make switching between servers an awful chore because you had to remember to add new statuses or your app would crash)...you would have had to do this with any database change but still these were the ones I'd have to do the most frequently
Good for data integrity
Using constants: Pros/cons (Martin Bean's method):
Avoids the disadvantages above
These are easy to reference in your code and base logic on
You don't have to create a new model or table even (he does in his example, but you could also just put them in the Events model)
They're great for values that will ONLY be used behind the scenes
They reduce the amount of queries
They just don't feel like as much work. They seem easier to refactor.
Con: they get kinda awkward when you get into labeling them, retrieving all of them, getting descriptions, etc. The translation solution is a good one but if you don't use translations in your app then this is a bit awkward as well.
Ultimately they're breaking the ORM flow you have going. If all your other models extend Eloquent then this breaks the mold a bit.
There's no real agreement on how to best do this. A lot of people use a different method each time.
Like AJReading said, if you need to use the database alone for another aspect of the project it won't work
I use the constant method but sometimes I'd think my code might be cleaner and simpler if I'd used tables. It's a hard call. I'd like there to be a well documented solution for the constant method to at least create consistency but I haven't seen one yet. Either way I don't think there's a right or wrong answer. Pick one and go with it!
For decisions of this nature, ask yourself this:
"Will there ever be an instance of my application where it would make
sense for these constants to have different values?"
e.g. a test environment, some sort of clone, some not yet defined but possible future version...
If the answer to that question is "yes", then it should probably go in application config.
If it is unlikely, (or daft) to have the values change, they belong to, and should go in the model.
I suggest in this case there would be no sensible reason to ever have a version of the application with different values, so I'd put it in the model.
I'm struggling with this kind of issue and I can't find direct answer to my question through Google.
Let's say we have a table 'users' in the database and it has the following columns: id, username, password, real_name.
Then my problems starts after that.
I know we can make an independent class for that like:
class User
{
private $_id;
private $_username;
private $_password;
private $_real_name;
// getters
// setters
}
Now, should I add functions like fetchById on that class? I mean, is it a good practice?
public function fetchById($id)
{
// validate param
// query database
// copy results to appropriate properties
}
Or should it be done by another class, like UserManager? Then for every result, we convert the array result to of that object?
Also, where should I put functions like fetchUsers where it will fetch multiple users from the database? Functions which deals with multiple records of the same entity.
I am looking for code efficiency and performance.
I know 'some' ideas but I can't justify it. I need help.
I'm currently working with CodeIgniter but I think this problem is PHP OOP in general.
For me personally, I have my models (objects that represent database tables) extend an abstractModel object that has the ID attirbute and shared static functions like fetchById(). This abstract model also has methods like save() which use the ID of the object to save.
You don't have to have an 'id' field in the table, the id of the model just has to be one of the unique key fields in the table.
Instead of fetchUsers() I have a generic loadAll() static function in the abstract class. Thus you could call Users::loadAll() to get all the models of your users. This means that most of your models can be interfaced with in the same way and reduces duplication of code. Of course if there are methods specific to the model, then you will need to define them in child model.
Build a class for table management and another for entity.
see other ORMs like doctrine, propel, or frameworks ORM like cakephp.
Lets say I'm working with an entity named Person. Person has properties such as height, weight, ect... that can be changed over time.
class Person
{
private $id;
private $weight;
private $height;
// etc...
}
I would like the User to be able to go back and see the changes over time on some form of graph. What is the best way to store each successive change for each separate property?
I've looked at the DoctrineExtension Loggable interface, but that creates a change entry for the entire object, so you can't 'browse' backwards by a specific property independent of the object, that has changed.
As well, reverting back to a previous version with Loggable will cause you to lose any changes between said version and current (as intended, but I want to be able to remove specific entries).
Would the best approach be a classic OneToMany/ManyToOne relationship from Person to "entry objects", such as PersonHeightEntry or PersonWeightEntry (which contain the value and a timestamp for the entry), pulling the most current timestamp as the current value?
Example:
class Person
{
// #ORM\OneToMany(...)
private $weight_entries;
}
class PersonWeightEntry
{
private $value;
private $timestamp;
// #ORM\ManyToOne(...)
private $person;
}
Actually, the Loggable Interface can be used to store the different versions of an object in the database while presenting the data in another form to the user. For example you can read the different heights from the database and present them with no need to show the whole object.
You can also "revert" changes for only one property by overwriting the property of the actual object with the old value which you get from the old version of that object.
Having many properties mapped with OneToMany relations will cause load on your database and make the computing heavier.
I would use the Loggable Interface, storing full objects in the database, and then alter the representation in your application according to your needs.
Question:
Is there a preferred design pattern for handling an object under different contexts? For example: if I need to GET a user from the database then that object needs to have an id and a privilege level. However, if I want to create a NEW user for registration then it does not need an id since this will be added in the database via auto_increment. A GUEST user does not need an id but should have a username of 'Guest'.
Attempted Solutions
Using a constructor seems to neglect context.
Creating new objects for registered_user, new_user, and guest_user seems wasteful.
Creating methods within the user object that can be used to initialize it in unique ways is tempting.
As of now I believe that I should create a separate factory that has functions such as create_guest($x), create_new_user($x, $y), create_registered_user($x, $y, $z)? This would allow the user object to have one purpose: hold a user (while still allowing it to have a constructor to establish a bare minimum requirement), and also have a user factory with the sole purpose of: initiating different types of users.
Please excuse any ignorance, just looking for the best design pattern for handling the same object in unique contexts.
Example:
<?php
class user
{
private id;
private username;
private privilege;
public function __construct()
{
some code...
}
public function is_admin()
{
some code...
}
}
?>
Using the provided class, you can always autoinitialize the value for $this->id to be 0 and use it to determine if this user is a guest. Main idea is that you will never have an id of 0 in your database (if you are using auto-increment for this column).
This can also be used to check if you are to update or create the record. A simple check on the id would reveal either 0 or another int. If it is 0, then it is either guest or it should be created. If it is greater than 0, it has already been created and it needs to be updated.
Generally, I prefer to pack the create and update into the user class itself by adding load(), update(), create() and delete() methods, where load() would accept an array/object which if passed will be used to load the data into the current context or if not supplied, the function will try to read the data from a different source (such as a DB).
Problem
Suppose you have a class user. You want to be able to return this user object to others so they can use it to extract information using getters. However, you don't want people to be able to readily set the internal state because the internal information should directly relate to a row in the database. Does it make sense to have protected mutators (setters) so that only an extended class could set the variables? Is this a bad practice, irrelevant, overkill or useless?
I have considered trying to limit __construct to one use ( I believe this is sometimes refereed to as a singleton pattern - although I am not sure if I understand entirely. )
I am an amateur programer, forgive any ignorance. Thanks.
Example:
<?php
class user
{
private username;
protected function set_username($username)
{
$this->username = $username;
}
public function get_username()
{
return $this->username;
}
?>
Depends. If nothing in particular needs to happen when the state is changed then you can leave the setters out altogether. Any subclass will have direct access to the properties that are set protected or looser.
If you need something to happen when the state changes (for example having a database UPDATE happen when the state changes) then the setters will make your life a lot easier, as the call to the database updating code be put in the setter. This means if you always go through the setter then the DB will always update when you change the object's state.
So in short, it depends.
If you have a constructor that accepts an id for instance, why would you want to have setters at all. There is no rule forcing you to give an object setters just because it has getters. If your usecase is constructing the object somewhere and after that only use it to extract data from it, simply create no setter at all.
Extending objects can manipulate the protected class variables itself so they don't require any form of setter as well. If you don't want the "outside world" to be able to set something to the class, don't allow it.
Your code is totaly fine and IMHO it encapsulates perfectly. Tt also supports loose coupling.
For easier use, you can add all needed (must have) members as constructor parameters.
Regarding the singleton pattern, use it with care. Users in common aren't singletons. Refer to Refactoring to Patterns (Joshua Kerievsky).