0

In a PHP project I have three layers (Logical)

UI :

Place to store UI php pages. ex: ManageUsers.php

Code :

All Entity Classes Related to system. ex: User.php

DataAccess :

Data Access Classes for Entity Classes ex: UserDataAccess.php

So to add user from UI, I create a instances of User class set properties of it & call AddUser method (in user class). In AddUser method it creates a instance of UserDataAccess class & pass the same ($this) object to UserDataAccess Insert function. It gets the data from User object properties & updates the table. (returns status back to UI through Code layer)

I repeat this for other functions like Edit & Delete.

  1. Is this the preferable OOP way to achive this CRUD functions or can I reduce one layer & combine Code & DataAccess layer to make it more simple?
  2. Is it ok to instanciate User class more than once in ManageUser page (one instance for Add, one for Edit and so on) or should instanciate it only once for a single page?

Sorry about the length & complexity of the question.. Thanks in advance...

4
  • Why not extend User from UserDataAccess? Allows you to keep your specialized code separate (good!) but still seemingly reduce one layer from your application. Commented Jan 6, 2012 at 11:42
  • 5
    Congratulations, you have discovered the MVC (Model, View, Controller) pattern! It is recommended practice to keep your three sections separated from each other. Commented Jan 6, 2012 at 11:45
  • @nikc.org Because usually you want to keep the data access layer separate from the corresponding value objects. Otherwise you cannot extend or change (here) UserDataAccess without changing User too. Commented Jan 6, 2012 at 11:56
  • @cillosis, Thanks for the comments, It seems this design is OK. Commented Jan 6, 2012 at 14:53

1 Answer 1

1

Is this the preferable OOP way to achive this CRUD functions or can I reduce one layer & combine Code & DataAccess layer to make it more simple?

The 3 layer method (Interface "U.I.", Business logic "Code" & Data Access), is the suggested way to do things.

You'll find that there are several business apps. that use the "2 layer" method that you suggested. If your think that application is going to "grow", you should use the 3 layer instead.

But, have in mind, that its complexity will also increase.

You may also want to get (download, develop, buy) a separate tool program that reads a database or data access, and generates your entity classes from it, instead of programming all by yourself.

If possible, do the same, for the "Code" or "Business logic" entities.

One more thing, avoid putting all you entities, in a single file.

Use a file per entity, instead. Make, unleast, a single "GUI" folder for your interface or "boundary" classes, a folder for your "Code" classes, and a folder for your "Data Access" classes.

Your website or application may be small, and this suggestions may seen very complex nad unnecesary.

But, by experience, apps. tend to grow, even "pet" or "personal" websites, unexpectly may grow, and become complex.

Even, if its a personal, small project, you may try to use the suggestions, in order to be prepare for large websites or apps.

Additional Suggestion

One trick I learn from a coworker, to make code more maintainable, its to use a program that generates the entities code, automatically, and, later, not make instances of those class entities, as usually done in the 3 layer method.

Instead, a second class entity was code, usually manually, adding some members or features, that may be updated regularly.

So the first (parent) class have the members that can be obtained from the database (or XML file), and the second (child) class, has the members that may not be obtained from the database, and also require to do a lot of changes, that require to be "coded by hand".

Example:

(1) You have a database table (or XML file or local file) like this:

CREATE TABLE User
(
  integer UserKey primary key,
  varchar(20) UserAlias,
  varchar(250) UserPasword,
  integer UserIsActive, -- My D.B. doesn't support boolean
)

(2) You generate a Data-Access-Layer entity like this, wheter manually or tool-generated:

abstract class FieldsUserDataAccessEntityClass
{
  /* integer */ protected $fieldUserKey = 0;
  /* string */ protected $fieldUserAlias = "";
  /* string */ protected $fieldUserPassword = "";
  /* integer */ protected $fieldUserIsActive = 0;

  /* integer */ public function CalculateNewKey();

  /* void */ public function Insert();
  /* void */ public function InsertWithKey(/* integer */ $newKey);

  /* void */ public function Update();

  /* void */ public function Delete();
} // class

This previous class is commonly used directly (without the "abstract" feature).

But, the suggestiuon is, that in other file, this, (I skip the methods code):

/* concrete */ class UserDataAccessEntityClass extends FieldsUserDataAccessEntityClass
{
  public /* integer */ function getUserKey();
  public function setUserKey(/* integer */ $newValue);

  public /* string */ function getUserAlias();
  public function setUserAlias(/* string */ $newValue);

  public /* string */ function getUserPassword();
  public function setUserPassword(/* string */ $newValue);

  public /* string */ function getUserPassword();
  public function setUserPassword(/* string */ $newValue);

  public /* bool */ function getUserIsActive();
  public function setUserIsActive(/* bool */ $newValue);
} // class

...
/* void */ function GlobalDoSomething()
{
  /* UserDataAccessEntityClass */ $CurrentUser = new UserDataAccessEntityClass();
    /* integer */ newKey = $CurrentUser->CalculateNewKey();

    $CurrentUser->setUserKey(newKey);
    $CurrentUser->setUserName("JohnDoe");
    $CurrentUser->setUserPassword("a9b8c7d6e5f4");
    $CurrentUser->setUserIsActive(true);

    $CurrentUser->Insert();
  $CurrentUser = null;
} // 
...

I use the casting of the "IsActive" field from "integer" to "boolean", as an example, could be other stuff like truncating a string that is too long.

Some developers will complain, and suggest to do this in the business logic entity.

(3) You generate a Business-Logic-Layer entity like this, wheter manually or tool-generated:

abstract class FieldsUserLogicAccessEntityClass
{
  /* integer */ protected $fieldUserKey = 0;
  /* string */ protected $fieldUserAlias = "";
  /* string */ protected $fieldUserPassword = "";
  /* integer */ protected $fieldUserIsActive = 0;

  /* void */ public function DoSomeThing();
} // class

In other file, this, (I skip the methods code):

class UserLogicAccessEntityClass extends FieldsUserLogicAccessEntityClass
{
  public /* integer */ function getUserKey();
  public function setUserKey(/* integer */ $newValue);

  public /* string */ function getUserAlias();
  public function setUserAlias(/* string */ $newValue);

  public /* string */ function getUserPassword();
  public function setUserPassword(/* string */ $newValue);

  public /* string */ function getUserPassword();
  public function setUserPassword(/* string */ $newValue);

  public /* bool */ function getUserIsActive();
  public function setUserIsActive(/* bool */ $newValue);

  /* void */ public function DoAnotherThing();
} // class


...
/* void */ function GlobalDoSomething()
{
  /* UserLogicAccessEntityClass */ $CurrentUser = new UserLogicAccessEntityClass();
    $CurrentUser->setUserName("JohnDoe");
    $CurrentUser->setUserPassword("a9b8c7d6e5f4");

    if ($CurrentUser->TryLogin())
    {
      echo "Welcome !!!";
    }
    else
    {
      echo "Security Alert !!!";
    }
  $CurrentUser = null;
} // 
...

These method helps a lot when, you have to add or remove or update fields in the database, but, its more complex, so a entity generator is required.

The idea its that a tool generates the "abstract with fields" entity classes, and you modify manually the "concrete child" entity classes, when required.

And in real world programming, modifying hte entities manually, happens a lot.

Is it ok to instanciate User class more than once in ManageUser page (one instance for Add, one for Edit and so on) or should instanciate it only once for a single page?

Its ok, to instantiate an entity class, several times, but, its more common, to have them as temporally objects int methods. In case of objects like the "currently logged user", you may use a "singleton" object.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.