Viewed   74 times

I'm fairly new to OOP in PHP, I've made a couple of basic scripts but nothing impressive. All I've really taken from it is that it would probably be easier just make a collection of functions and include them.

The structure of classes seems to just confuse what was otherwise a simple process. And in collating everything into a class it doesn't really add any functionality.

So I'm clearly missing something. Could someone explain what functionality is added by creating classes

 Answers

4

Classes are a notion of object-oriented design (and programming and analysis, respectively), where they are used to encapsulate data and methods.

Other object-oriented programming techniques may include features such as

  • information hiding,
  • data abstraction,
  • encapsulation,
  • modularity,
  • polymorphism and
  • inheritance

From an article .. top-15-best-practices-for-writing-super-readable-code:

Object oriented programming can help you create well structured code. But that does not mean you need to abandon procedural programming completely. Actually creating a mix of both styles can be good.

From http://java.sun.com/docs/books/tutorial/java/concepts/class.html:

In the real world, you'll often find many individual objects all of the same kind. There may be thousands of other bicycles in existence, all of the same make and model. Each bicycle was built from the same set of blueprints and therefore contains the same components. In object-oriented terms, we say that your bicycle is an instance of the class of objects known as bicycles. A class is the blueprint from which individual objects are created.

Finally, a short youtube video about the differences between the procedural and object-oriented programming paradigm ...

Friday, September 23, 2022
5

The serve command is just a shortcut for the PHP Built-in Webserver, something PHP has out of the box, so the point of using it is to start testing your application as fast as you could, you just need to install PHP, Composer and your application is up (if you don't need anything else, of course). But if you already have Nginx installed, there is no point at all, just use it.

It's not wise to use the Builtin Webserver in production.

Wednesday, October 12, 2022
 
3

I can think of a couple of cases when a separate layer of view model classes is a good way to go, and I'll try to explain them in terms of a general ORM tool and a general MVC framework - note that neither of these two cases are specific to ASP.NET MVC Framework with Entity Framework (nor even to programming in .NET...).

Also: please note that in the following few paragraphs I'm only referring to view models specifically. I'll adress problems like mass assignment vulnerabilities at the end of this post.

Reason 1: Give the View layer exactly the data it needs, and nothing else

This is a somewhat "purist" goal - in a true MVC application, the view layer only has access to data that it needs at the moment, and nothing else. The view model object now becomes a specification from the view layer to the controller: "This is the data I need to show the view you requested." In order to adhere to fundamental MVC principles, you want to make sure that all decisions on what data to display are made by the controller.

In other words, if you want to display a user's first and last name, username and picture, you don't need (or want) to give the view layer an object which also has information about the user's password, roles (or, to take some properties that might not be so sensitive, height or middle names). Instead, you give the view an object with properties for first name, last name, username and picture, and the view decides only how to present the data. That way, you're sure that the decision on what data is presented stays in the controller layer.

Reason 2: Avoid problems with your ORM tool's tracking abilities

Some ORM tools - even some of those that return regular objects1 - use quite sophisticated methods to keep track of changes in the objects you get from the data layer, in order to make changing the records easier. For instance, you might get an object from your data store, change some properties on that instance and then call a save() method somewhere else, and the object is updated in the database. Depending on the ORM tool, forwarding your ORM-entities to the view layer can have any range of consequenses, from performance issues (worst case: database connections kept open) to unwanted effects (say, a bug in the view layer changes properties in the data store). To avoid those, re-map your entities to "true regular objects", that have no relation to your ORM tool, before sending them too far down the application pipeline. View models is one way (of many) to achieve this goal.

Note that whether this is necessary or not is entirely dependent on your ORM tool. I don't know the inner workings of Entity Framework nearly well enough to know if you have to care - but in (very) early incarnations of EF this was a problem, at least when not using the Code-First approach.

Conclusions: do you have to care?

No, not necessarily. You could be doing just fine without view models, and in that case they're just another layer of abstraction which doesn't really add anything but complexity to your application. It all boils down to wheter your ORM tool puts any requirements on your code, and whether you're an "MVC purist".

Side note: But what about mass assignment vulnerabilities?

Queti-Mporta already pointed out that mass assignment vulnerabilities could be a problem. I agree that this is a serious concern, but I don't agree that it is solved by using view models.

To me, a view model is a data transfer object from the controller to the view, helping the controller to sort out and summarize the data that should be displayed. To avoid problems like mass assignment vulnerabilities, I usually use edit models, which are very similar to view models but in the other direction - i.e. to the controller. Not everyone makes this distinction - and I don't care very much if you do or not. But using this vocabulary, I'd recommend always using edit models when you let users alter your data, and using view models only when it helps you.


1 In .NET usually referred to as "POCO's", or Plain Old CLR Objects. Java has its equivalence in POJO's (Plain Old Java Objects) and if you can think of a language that can be used in object oriented programming, that language also has an equivalence.

Wednesday, December 7, 2022
 
1

It is not possible to prevent the constructor from being called when the object is constructed (line 9 in your code). If there is some functionality that happens in your __construct() method that you wish to postpone until after construction, you should move it to another method. A good name for that method might be init().

Why not just do this?

class Test {
    public function __construct($param1, $param2, $param3) {
        echo $param1.$param2.$param3;
    }
}

$ob = new Test('p1', 'p2', 'p3');

EDIT: I just thought of a hacky way you could prevent a constructor from being called (sort of). You could subclass Test and override the constructor with an empty, do-nothing constructor.

class SubTest extends Test {
    public function __construct() {
        // don't call parent::__construct()
    }

    public function init($param1, $param2, $param3) {
        parent::__construct($param1, $param2, $param3);
    }
}

$ob = new SubTest();
$ob->init('p1', 'p2', 'p3');

This is might make sense if you're dealing with some code that you cannot change for some reason and need to work around some annoying behavior of a poorly written constructor.

Saturday, September 10, 2022
 
4

You may use Factory Pattern. Basket, Billing and Delivery objects should be created by the 3rd-party service API wrapper class:

$svc = new The3rdPartyServiceApiWrapper();
$svc->init();  // connect, get session etc.
if ($svc->fail()) die("halp! error here!");

$basket = $svc->createBasket();
$baskSumm = $basket->getBasketSummary();

$billing = $svc->createBilling();
$billSumm = $billing->getBillingSummary();

$delivery = $svc->createDelivery();
$delSumm = $delivery->getDeliverySummary();

The best way to connect Basket, Billing and Delivery class with the API is storing a reference to the API class, then they can call any method of it, not just getSession().

Another advantage is, that if you have an identified entity, e.g. a User, then the wrapper class can grant you, that there will be no double objects in the scene.

If the main program creates the users, there should be different objects with the same user, which is wrong:

$user1 = new User("fred12");
$user2 = new User("fred12");

VS if the API wrapper creates them, the wrapper class should keep a "cache" of users, and return with the same User object for the same request:

$user1 = $svc->createUser("fred12");
$user2 = $svc->createUser("fred12");  // $user2 will be the same object

(Maybe it's not a best example, if a program creates twice the same User, it means that the program has major design faulty.)

UPDATE: explanation of svc class

The The3rdPartyServiceApiWrapper should look like this:

 function getSessionId() {
   return $this->sessionId;  // initialized by constructor
 } // getSessionId()

 function createBasket() {
   $basket = new Basket($this);
   return $basket;
 } // createBasket()

The Basket:

 function Basket($s) {  // constructor of Basket class

   $this->svc = $s;

   //... the rest part of constructor

 } // Basket() constructor

function doSomethingUseful() {

  // if you wanna use the session:
  $sess = $this->svc->getSessionId();
  echo("doing useful with session $session");

  // you may access other api functions, I don't know what functions they provide
  $this->svc->closeSession();

} // doSomethingUseful()
Tuesday, October 18, 2022
 
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :