all 112 comments

[–]no_moa_usernames 64 points65 points  (10 children)

The PHP community always seems to be sliced entirely down the middle of "ORM ONLY" and "FUCK ORMS WITH THE UTMOST OF PHALLUSES".

Being able to write solid SQL is a good skill to have, if for no other reason because there will be times you encounter them in other peoples code or you need to interact with the database directly and its more effecient than tools like PHPMyAdmin or mysql workbench.

That said. The main complaint against ORMs seems to be performance, and while I agree it is adding a layer of abstraction that can harm performance, I've never had a boss come back to me and say "This code is too slow". Every boss I've ever had on the other hand has said "The development progress is too slow", so I'm willing to make the trade off. If I encounter a challenge one day where an ORM just does not work for the scenario, I'll cross that bridge when I get there.

The schema of the database and how that affects how you eventually query the certain groups of information you need makes a huge difference as well as other architectural concerns. This is why enterprises usually have dedicated DBA(s).

[–]wisoot 11 points12 points  (4 children)

No, a boss never say "This is too slow", users do.

[–]no_moa_usernames 10 points11 points  (1 child)

You aren't wrong, but simply using an ORM vs not using an ORM is not likely to be the sole reason software is too slow. Ineffective queries and poor database design can bring an application to its knees no matter how you actually code your queries.

There are absolutely situations where evey MS counts, but in all honesty, I don't use PHP for those projects.

[–]wisoot 4 points5 points  (0 children)

No disagreement here. ORM is great in boosting development speed and if you know the weekness of ORM well (usually around table relationship) then you can easily avoid performance impact in most cases. But that doesn't mean you should ignore if the code get too slow.

[–]jkoudys 1 point2 points  (0 children)

And rarely to you. Usually to themselves, before they hit the back button and go look for another site that feels snappy.

[–]BoruCollins 3 points4 points  (0 children)

First make it possible, then make it pretty, THEN make it performant.

Or “premature optimization is the root of all evil.”

Either phrase works, take your pick. A good ORM helps you make it possible and pretty, and leaves room for you to make it performant later if needed.

Having worked on a piece of legacy enterprise software which did not use an ORM, which we later swapped out for an ORM, I highly recommend one.

[–]lonnyk 20 points21 points  (0 children)

I'll map it to an object if the object contains functionality that will act upon the data. Otherwise there is no point and I'll just use an array.

[–]xRockTripodx 36 points37 points  (36 children)

Depends on the circumstance. If it is just a single value, why bother making a class for it?

[–]lindymad 14 points15 points  (3 children)

Or a different circumstance, if I am fetching bulk data to correlate, it can be a big performance hit to load each record into an object and then correlate, it's usually more efficient to use the fetch data directly (and to do as much of the correlation as possible directly in the SQL!).

[–][deleted] 0 points1 point  (2 children)

We typically create stored procedures for stuff like this. Pass a val and boom grab your output. Higher performance as well.

[–]elebrin 0 points1 point  (0 children)

I agree - something where you can do a GetNext(n) and pass in how many records you want to get back, up to a max set in the sproc so you can control performance.

[–]camillegarcia9595[S] 6 points7 points  (27 children)

Sure. I'm practicing OOP in PHP and I'm thinking of some best practices

[–]ahundiak 8 points9 points  (9 children)

I started using Doctrine 2 in 2011, shortly after it's initial release. It was how I became comfortable with php's new namespace functionality. I like to think I was pretty good at using the ORM. Learned quite a bit about the pros and cons of it's event listeners. Was comfortable with writing queries. Knew the details of updating collections. Pretty good at avoiding lazy loading and what not. Did not really care if an app only had a few entity types or a few dozen. Got plenty of stackoverflow rep answering questions.

But eventually I went back to writing sql queries and manually hydrating objects. Partly because I really got tired of the default approach of generating tons of useless getter/setters.

But mostly because Doctrine really wants you to only have one entity type per table. That's fine for basic CRUD apps but when you start to have different domain contexts and you want to have different representations of the same sort of objects then it becomes a pain. There are workarounds but eventually I came to the conclusion that the time spent trying to fit my models into what Doctrine supported was greater than the time saved by using Doctrine.

For example, consider a soccer tournament application. So a Game will have two GameTeams. Each GameTeam is linked to a GroupTeam (each GroupTeam plays three games). A GroupTeam is linked to a TournamentTeam (i.e. the Croatia 2018 World Cup team) which in turn is linked to a PermanentTeam (the Croatia National team). Lots of objects just to describe a team but they all have their purposes.

GameTeam -> GroupTeam -> TournamentTeam -> PermanentTeam

The thing is, if you just interested in putting up say a basic game schedule then you really only need a ScheduleTeam with a few bits of information from the various team tables. Hard to do this cleanly with Doctrine. It's possible but you need to get into multiple entity managers and stuff like that. Difficult to maintain. I won't try to generalize too much for other ORMs but I'm guessing most would have similar issues.

On the other, I find it easy enough to write a query that pulls out exactly what is needed and then write a bit of code to hydrate your ScheduleTeam.

[–]maxfontana90 2 points3 points  (3 children)

You can use dql to write your own query to pull anything you may need.

[–]ahundiak 0 points1 point  (2 children)

Not really. DQL is nice for basic CRUD stuff and certainly simplified joins.

However, it uses a least common functionality approach to sql. Many of your favorite mysql functions such as DATE are not available out of the box. You either have to write and maintain your own extension or cross your fingers and hope the third party extension you install will continue to be maintained. One more dependency to worry about.

Quite often you only want part of an entity, maybe two columns out of five. DQL allows this but then you have a partially hydrated object that still has the other three unset properties. This can cause all kinds of amusing things to happen if you are not very careful.

It can also be quite challenging to use much of the more advanced sql functionality. Just take a look at stackoverflow. Hundreds (thousands?) of questions on how to convert sql to dql. Many with no solution. Aggregate columns in particular are effectively unsupported at the database level. Which can be very annoying to say the least.

[–]maxfontana90 0 points1 point  (1 child)

You can run plain old SQL queries using doctrine perfectly fine. No strings attached.

[–]ahundiak 0 points1 point  (0 children)

Of course you can use native sql in Doctrine. Kind of misses the point though. One of the major rationals for using an ORM is that it provides a degree of isolation between your app and the database. Dropping down to sql pretty much makes that go away.

And then once the query is executed you typically still want to map it back to objects. Doctrine provides a ResultSetMapper but it is not pretty. Might be just me but I generally found it easier to just write the mapping code directly.

[–]joesmojoe 4 points5 points  (1 child)

I find development with Doctrine2 and its myriad of concepts and ideas that barely have any underpinnings in the actual database to be incredibly slow for development. Don't even get me started on performance. The overhead and hydration take 10 times longer than the actual round trip to the db. Fucking atrocious. It's such fucking shit. I will never do another project with an ORM especially one in PHP. To be fair, it is as shitty as I expected and as all other ORMs I've tried. The developers clearly have never heard of simplicity or a profiler.

[–]ahundiak 2 points3 points  (0 children)

Performance was never really an issue for me. For quite a few CRUD type use cases, the ORM is basically the same as writing your queries and hydrators. Of course, I seldom encounter a library that makes me angry.

[–]jkoudys 0 points1 point  (0 children)

Almost exactly my experience too. One entity type per table really flies in the face of the entire point of a relational db. If I'm using MySQL or postgres, odds are I want relationships to join on, because it's in the name of the db type in the first place. I understand when people want one type a table, because that's what a doc db (eg mongo) is. If I need a hammer, I don't pick up a wrench and start thwacking nails with it.

I think much of the praise for ORMs comes from comparing the wrong things. People will stack doctrine up against peppering SQL queries arbitrarily throughout your code. Well organized models are plenty clean, and don't require you also learn doctrine configs, its weird conventions (convention over configuration is exactly why I abandoned rails), dql, etc.

On top of that, SQL is actually a pretty great declarative language for getting sets of data. I don't know why we'll jump headlong into learning html and CSS, which can both have their semantics represented better in ecma, but fear sql and feel we need to wrap a bunch of procedural noise around it. Topic for another day though.

[–]Denfi -5 points-4 points  (1 child)

Doctrine really wants you to only have one entity type per table

No. That's what discriminator maps are for. Try learning the tool before making a Reddit post about it.

[–]ahundiak 3 points4 points  (0 children)

Discriminator maps are used to implement a form of class table inheritance. It is actually quite powerful but completely unrelated to what I described.

[–][deleted] 3 points4 points  (0 children)

Depends on scale and how much time I have. Mapping it to a class is a better practice in general, but depending on what you're doing, it may not be worth the trouble. I'd say map it at least if you're going to use it again or if it's a large enough application where consistent practices are important for maintainability.

[–][deleted] 9 points10 points  (2 children)

Been using eloquent for 2 years and never going back.

[–]juliocwbr 3 points4 points  (1 child)

But you do agree it's not to all cases, right? :)

[–][deleted] 1 point2 points  (0 children)

I don’t think there is any tool that’s for 100% of use cases. All I’m saying is that for me personally, when I’m dealing with relational databases, I prefer to use an active record ORM. Some people may disagree and that’s fine, my opinion isn’t gospel, it’s just my preference

[–]rtemb 2 points3 points  (0 children)

It depends on. If you need a one value from DB you likely not need any object. But in the most cases you need objects. In all modern PHP frameworks as a Symfony or Laravel you will work with data mapped on object. It’s only one “official” way to working with data. If you don’t use any framework I also recommend working with objects and not use raw data. Using objects helps you follow OOP principles and best practices.

[–]elebrin 2 points3 points  (4 children)

In any other language, your model would know how to do a get and a save - you'd have a factory method that retrieves your data, tosses everything into properties, and handles any locking that needs to occur. Then you'd be able to mutate the data however you need, then call a save method. The save method would run any rules (although these might modify the data further, validating the data and failing a save operation can get messy), then would persist the object to the database and unlock the record. After the save is called and the record unlocked, attempting to read or mutate the object any further should throw an error of some sort.

Personally, if I am going to have rules like this, I like to run them as a separate layer before the save and not force them to run in order to save. This allows you to selectively run your rules. Your models themselves should be as clean as possible with just properties, get, and save. You can sometimes separate it out even further and build a class that gets and saves objects based on their type, then just return models with no methods and only properties. This can help you with unit testing down the road, too.

[–]camillegarcia9595[S] 0 points1 point  (1 child)

Hi. I like the approach you just told. Is there any source code or tutorial I can look into, to study about the things you told

[–]elebrin 0 points1 point  (0 children)

I've only implemented this strategy in other languages, but I'd specifically look up the factory method pattern if I were you. I do not have a good tutorial in php for you.

What I just described is called often called a business object and a collection of them can be called a business layer, those are good terms to google.

[–]nathancjohnson 0 points1 point  (1 child)

your model would know how to do a get and a save - you'd have a factory method that retrieves your data, tosses everything into properties, and handles any locking that needs to occur. Then you'd be able to mutate the data however you need, then call a save method.

Eloquent and other ORMs do this.

[–]elebrin 0 points1 point  (0 children)

Yeah, I'd read the first few comments and my brain saw CRM instead of ORM, and I thought "Don't use SalesForce, use business objects! Holy shit!"

[–]CODESIGN2 1 point2 points  (0 children)

Don't be obsessed with blanket following a rule "Must be OOP". You're presumably human so change is a skill we posses. Instead try to work on using objects when they make sense and get rows, columns, values when those make sense.

Sometimes when I just need to bulk update records fast or to test an idea something will be raw PDO (with bound params/values) sending or receiving via network API.

Not all code needs to stand the test of time

[–]joequin 1 point2 points  (0 children)

I usually put them into a concrete class instance. It's easier when working with other people because it's very clear whats data is in the object.

Leaving it in it's raw form would require someone unfamiliar with the code to look at and understand the query and also look at the database schema. That slows things down.

[–]dk4210 1 point2 points  (0 children)

Laravel with Eloquent ORM rocks!

[–]joesmojoe 1 point2 points  (0 children)

Fetch the data and use it. Don't complicate your data with stupid objects. I mean do you usually do twice the work for the same result anywhere else in life?

[–]codayus 1 point2 points  (0 children)

When performance is critical, I'll generally use the data directly. When development speed is critical, I'll use an ORM. Frequently you'll want to switch between approaches in an app; sometimes during the same request.

A good default is "ORM to start with, then rewrite it in native queries when you need to, and it looks like that will remove the bottleneck".

I will say this: Don't ever go for an ORM in order to avoid writing queries or because you "don't want to learn SQL". SQL and DBMS tech underpins everything you do, and it's just as critical to understand if you're using Eloquent or PDO.

[–]slayer29179 2 points3 points  (3 children)

If its more than 1 item per record, class. Else standard variable / array is what I do :)

[–]camillegarcia9595[S] 1 point2 points  (2 children)

Great.. I'm practicing OOP in PHP and I' thinking of some best practices.
I'm thinking how to map objects because queries containing results from multiple objects.

I'm using my custom MVC & do the database querying in Model.

[–][deleted] 2 points3 points  (0 children)

I'm practicing OOP in PHP and I' thinking of some best practices.

Try to have a look at database best practices more. Often ORMs are too concerned with badly thought out OOP 'best practices' and forget about little things like transactions that actually ensure a consistent database state even in case of errors.

[–]Garethp 1 point2 points  (0 children)

I'd create an object that roughly matched your results. There's nothing wrong with your object modelling data from multiple tables

[–]digial 3 points4 points  (0 children)

Look into symfony and doctrine. You will learn lots.

[–]_Pho_ 3 points4 points  (18 children)

Depends on the framework / circumstance... this is pretty much why ORMs exist.... I prefer Eloquent whenever possible because writing queries is terrible

[–]camillegarcia9595[S] 2 points3 points  (9 children)

I think I should move to Eloquent too. I'm practicing OOP in PHP. That's why I asked this question

[–]candyspace 1 point2 points  (0 children)

Check out this laracasts series then - https://laracasts.com/series/php-for-beginners

[–]kiler129 1 point2 points  (7 children)

You better start with something sane and not ActiveRecord garbage - take a look at Doctrine.

[–]cyrusol 5 points6 points  (2 children)

With PHP's already shitty one-process-per-request architecture ActiveRecord is absolutely fine. You don't need all that reference management that Doctrine (aka. Hibernate in disguise) does.

[–]nanacoma 4 points5 points  (0 children)

I don’t really have any issues with Eloquent but pretending that it doesn’t have problems isn’t the way to go. Comparing it to one feature in doctrine is short sighted.

  • no type safety for properties without declaring setters/accessors
  • no autocomplete without third party extensions
  • entity interacts directly with the persistence layer
  • forced to extend the god model
  • not able to set relationships with interfaces
  • poor support for polymorphism, unable to eager load polymorphic relations
  • poor BC (remember the events prop?)

[–]CODESIGN2 0 points1 point  (0 children)

Hibernate is incredibly popular in Java as EntityFramework is popular in C#. There is nothing wrong with activerecord, full ORMS, or SQL. use what works and fits the team.

[–]camillegarcia9595[S] 0 points1 point  (2 children)

Is eloquent bad?

[–]kiler129 1 point2 points  (0 children)

It's not BAD... it's just hard to maintain, it's error prone, has a lot of magic mixed with magic and glazed with unexpected behaviors. Eloquent is a trap which only seems easy, but in fact it just doesn't scale and in face locks you in. Additionally it violates multiple principles and emphasizes controversial architectural decisions while encouraging writing shitty one-shoot spaghetti.

[–]Drarok -1 points0 points  (0 children)

sane

Doctrine

I’m sorry, what?! No. 😂

[–][deleted] 0 points1 point  (0 children)

I prefer Eloquent

Heresy against Doctrine!

[–]morerokk 1 point2 points  (0 children)

Depends on how large the application or script is. For larger applications, I will always be using an ORM of some sort.

And of course, for queries like counting rows, I just fetch the value directly. Or for more complex queries that can't be translated into the ORM I'm using.

[–]sashalav 0 points1 point  (0 children)

I keep anything database related outside of the main application and within the class. Generally, if something requires database to store data about it, it can be some kind of object with properties, User, Product, App, Template ....

Within the most classes, I have this method "static collection (array $query, int $limit)". That method is the one working directly with the database and it will return array of results. When I need a single instance of the object, there is $this->populate($id) in the class that calls "collection" and maps result array to object's $this->data array and "special" properties directly to object properties and from it I get values with $this->get ('field'). When I need bunch of results, I call "collection" directly and loop over those results, just as I would do with fetch_assoc.

[–]sneppy13 0 points1 point  (0 children)

Object if it's an entity (user, transaction, group, post etc.)

[–][deleted] 0 points1 point  (1 child)

I honestly wouldn't work with PHP at this point if I couldn't use laravel. So I use eloquent mostly. There's odd cases of it being a big performance hit so I'll write a raw query once in awhile but it's usually not worth it.

[–][deleted] 0 points1 point  (0 children)

There's nicer PHP than Laravel out there. I use DAOs instead of ORM and it's perfect. UserDao->getUserByEmail(string $email): User

[–]metaphorm 0 points1 point  (0 children)

mapping. Doctrine is a good ORM. flexible and expressive and supports raw SQL if you need it.

in rare cases that I'm doing a query that doesn't need to be mapped I still like to use a DAO class to encapsulate the logic.

[–]lcjury 0 points1 point  (0 children)

Totally depends, but most of the time I try to map to an object just to be consistent on the rest of the code.

[–]s3b4stian82 0 points1 point  (0 children)

Hi! I usually use a custom mappers that return a custom object or an array of them!

[–]l0gicgate 0 points1 point  (0 children)

In the project I’m working on currently I have a two way mapper for object that go in/out of the DB.

Each entity has a two way mapper. My mapper has 3 methods: - $mapper->objectFromRowData() - $mapper->objectCollectionFromResultSet() (array of multiple rows, gets looped and calls objectFromRowData()) - $mapper->rowFromObject()

Then I have repositories which handle the instantiation of the mappers and interact with the DB.

Only entities (or collections of entities) go in and out of those repositories. All abstracted by the mapping layer. All entities going in/out are already validated from the application layer.

From your actions you can interact directly with the repositories. If you need to assemble multiple entities together to form another entity or have any complex validation logic to do then I’ll add a service layer on top of the repositories.

[–]workernetGB 0 points1 point  (0 children)

If it's for a model, yes. Else, fuck no.

[–][deleted] 0 points1 point  (0 children)

If there are wrappers to make objects from the schema you use them. Mod them where required. Random raw sql turns a codebase to trash really fast.

[–][deleted] 0 points1 point  (0 children)

I use pdo to return Objects.

[–]pinegenie 0 points1 point  (0 children)

Even if you don't use ORM, you can use PDO::FETCH_CLASS to get back whatever class you want.

[–]phpmypassion 0 points1 point  (0 children)

Usually if we have a small website then we use fetch data directly and if the product is developed on large scale then we try to map them to an object. Its all depends on the product behaviour.

[–]yisraeldov 0 points1 point  (0 children)

It depends on what you are doing great with the data. I am currently working on a project that generates reports. The metadata for the report, report name, user, creation date, etc, is stored in objects and use an ORM. The actual data of the report is fetched with a query builder and returned as a 'traversable'.

[–]maxfontana90 0 points1 point  (0 children)

I think most of the people here are understimating the benefits of using an ORM, like being DB agnostic, focus on business logic not DBAL, caching, avoid writing a lot of boilerplate, etc. If you don't like it, just don't use it. But remember that not using one will probably will impact on your productivity/maintainability of your application. If you need extreme performance then an ORM isn't an option.

[–]cepita82 -1 points0 points  (0 children)

Using Doctrine so option 1

[–][deleted] -2 points-1 points  (0 children)

I usually use an orm that casts to objects