I recently started working with Yii PHP MVC Framework. I'm looking for advice on how should I continue working with the database through the framework: should I use framework's base class CActiveRecord which deals with the DB, or should I go with the classic SQL query functions (in my case mssql)?
Obviously or not, for me it seems easier to deal with the DB through classic SQL queries, but, at some point, I imagine there has to be an advantage in using framework's way.
Some SQL queries will get pretty complex pretty often. I just can't comprehend how the framework could help me and not make things more complicated than they actually are.
Very General rule from my experience with Yii and massive databases:
Use Yii Active Record when:
You want to retrieve and post single to a few rows in the database (e.g. user changing his/her settings, updating users balance, adding a vote, getting a count of users online, getting the number of posts under a topic, checking if a model exists)
You want to rapidly design a hierarchical model structure between your tables, (e.g. $user->info->email,$user->settings->currency) allowing you to quickly adjust displayed currency/settings per use.
Stay away from Yii Active Record when:
You want to update several 100 records at a time. (too much overhead for the model)
Yii::app()->db->command()
allows you to avoid the heavy objects and retrieves data in simple arrays.
You want to do advanced joins and queries that involve multiple tables.
Any batch job!! (e.g. checking a payments table to see which customers are overdue on their payments, updating database values etc.)
I love Yii Active Record, but I interchange between the Active Record Model and plain SQL (using Yii::app()->db) based on the requirement in the application.
At the end I have the option whether I want to update a single users currency
$user->info->currency = 'USD';
$user->info->save();
or if I want to update all users currencies:
Yii::app()->db->command('UPDATE ..... SET Currency="USD" where ...');
In any language when dealing with the database a framework can help you by providing an abstraction over the database.
Here is a scenario I know I found myself in many times during my earlier development days:
I have an application that needs a database.
I write a ton of code.
I put the SQL statements in the code along with everything else.
The database changes somehow.
I'm stuck with having to go back and make 100 changes to all my SQL statements.
It's very frustrating.
Another scenario I found:
I write a ton of code against a database.
Bugs come in. Lots of bugs. I can't figure them all out.
I'm asked to write tests for my code.
This is impossible because all my code relies on a direct implementation of the database. How do you test SQL statements when they're with the actual code?
So my advice is to use the framework because it can provide an abstraction over the database. This gives you two really big advantages:
You can potentially swap out the database later and your code stays the same! If you're using interfaces/some framework, then most likely you're dealing with objects and not SQL statements directly. A given implementation might know how to write to MySQL or SQL Server, but in general your code just says "Write this object", "Read that list."
You can test your code! A good framework that deals with data will let you mock the database so you can test it easily.
Try to avoid writing SQL statements directly in the application. It'll save you pain later.
I'm unfamiliar with the database system bundled with Yii, but would advise you to use it a little bit to start with. My experience is with Propel, a popular PHP ORM. In general, ORM systems have a class per table (Propel has three per table).
Now, there'll probably be a syntax to do lookups and joins etc, but the first thing to do is to work out how to use raw SQL in your queries (for any of the CRUD operations). Put methods to do these queries in your model classes, so at least you will be benefitting from centralisation of code.
Once you've got that working, you can migrate to the recommended approach at a later time, without getting overwhelmed with the amount of material you have to learn in one go. Learning Yii (especially how to share code amongst controllers, and to write maintainable view templates) takes a while, so it may be sensible not to over-complicate it with many other things as well.
Why to use Yii:
Just imagine that you have many modules and for each module you have to write a pagination code; writing in old fashion style, will need a lot of time;
Why not use Yii ClistView widget? Oh, and this widget comes with a bonus: the data provider and the auto checking for the existance of the article that is about to be printed;
When using Yii CListView with results from ... Sphinx search engine, the widget will check if the article do really exists, because the result may not be correct
How long will it take for you to write a detection code for non existing registration?
And when you have different types of projects will you addapt the methods?
NO! Yii does this for you.
How long would it take for you to write the code in crud style ? create, read, update, delete ?
Are you going to adapt the old code from another project ?
Yii has a miracle module, called Gii, that generates models, modules, forms, controllers, the crud ... and many more
at first it might seem hard, but when you get experienced, it's easy
I would suggest you should use CActiveRecord.It will give many advantages -
You can use many widgets within yii directly as mentioned above.(For paginations,grids etc)
The queries which are generated by the Yii ORM are highly optimized.
You dont need to put the results extracted from SQLs in your VO objects.
If the tables for some reason modified(addition/deletion of column,changing data type), you just need to regenerate the models using the tool provided by yii.Just make sure you try to avoid doing any code changes in the models generated by yii, that will save your merging efforts.
If you plan to change the DB from MYSQL to other vendor in futur, it would be just config change for you.
Also you and your team would save your precious development time.
Related
In codeigniter PHP framework we can use normal SQL query and also we can use active record. Here i have understood active record syntax is less than normal SQL queries.
Can any one tell me what is the main advantage of active record in codeigniter?
Thanks in advance
The Active Record design pattern provides an easy way to handle the data (create/load, modify, update, delete) without the need to take care of the technical details.
Its main drawback is that it makes the unit testing impossible without using a database (which increases the test execution time a lot and breaks the isolation needed by the unit testing.)
Why the creators of CodeIgniter have chosen to use Active Record as their main way to implement the data persistence in the framework? I don't know.
Use it as it is or step forward and use another framework.
This is like comparing SQL with the ORM features because ACTIVE RECORD works as ORM in CI.
Here is the list of benefits of ORM:
Productivity: The data access code is usually a significant portion
of a typical application, and the time needed to write that code can
be a significant portion of the overall development schedule. When
using an ORM tool, the amount of code is unlikely to be reduced—in
fact, it might even go up—but the ORM tool generates 100% of the
data access code automatically based on the data model you define,
in mere moments.
Application design: A good ORM tool designed by very experienced
software architects will implement effective design patterns that
almost force you to use good programming practices in an
application. This can help support a clean separation of concerns
and independent development that allows parallel, simultaneous
development of application layers.
Code Reuse: If you create a class library to generate a separate DLL
for the ORM-generated data access code, you can easily reuse the data
objects in a variety of applications. This way, each of the
applications that use the class library need have no data access code
at all.
Application Maintainability: All of the code generated by the ORM is
presumably well-tested, so you usually don’t need to worry about
testing it extensively. Obviously you need to make sure that the
code does what you need, but a widely used ORM is likely to have
code banged on by many developers at all skill levels. Over the long
term, you can refactor the database schema or the model definition
without affecting how the application uses the data objects.
You can change the backend database anything as you don't need to
worry about query syntax as you are playing with OBJECTS instead of
queries.
It definitely makes your code cleaner to read, and I only not use it when I have to do some seriously complex SQL stuff, like building multitable search queries. I recommend it for its code cleanliness highly.
It helps to prevent Sql Injection.
But for some complex sql queries you can prefer your normal sql queries.
We are evaluating some PHP Frameworks for a productive website. CakePHP looks pretty interesting but we have no clue if it fits our needs.
Basically when you check the documentation and the tutorials for CakePHP it looks really promising. Nevertheless there were always some things that bugged me with frameworks so far, maybe someone who already used CakePHP in a productive project could answer this questions for me?
Writing/Reading data for single records looks pretty neat in CakePHP. What happens if you want to read data from multiple tables with complex conditions, group by, where clauses? How does CakePHP handle it?
Scaffolding looks pretty nice for basic administration interfaces. How easy is it to customize this stuff. Let's say I have a foreign key on one of my tables. When I create a scaffolding page, does CakePHP automatically create a dropdown list for me with all the possible items? What if I want to filter the possible items? Let's say I want to combine two fields into one field in the view part, but when I edit it, I should be able to edit both of those fields individually. Does this work?
Do you think you were faster in development with CakePHP than with let's say plain PHP?
I've used CakePHP, Zend Framework and I've also written applications "from the ground up" with nothing more than homegrown classes and such. To that I'd like to mention that I use CakePHP regularly so, take that as you will.
(Writing/reading data, complex conditions) You can certainly do everything you mentioned. Others are correct in that it attempts to abstract away SQL operations for you. I've yet to have a query that I couldn't translate into Cake's "parlance"; complex geospatial queries, joins, etc.
(Scaffolding, complex conditions) The scaffolding is really only meant to serve as a "jump start" of sorts to help make sure your model associations and such are setup correctly and should not be used as a permanent solution. To that end, yes it will do a fairly good job at introspecting your relationships and providing relevant markup.
(Faster development) Of course. There is a large community with a vast number of plugins or examples out there to help get you started. Regardless of what you pick, choosing a framework will almost certainly make you "faster" if only for handling the minutiae that comes with setting up an application.
It really depends on your definition of "large". Are you referring to big datasets? A very complex domain model? Or just lots and lots of different controllers/actions?
Writing/Reading data.
Anything you can do with plain SQL you can do in CakePHP. It may not always be very nice to do, but at it's worst it's no worse than straight SQL.
But you really shouldn't be thinking about queries. You should be thinking about your domain model. CakePHP implements the active record pattern. It works very well if your domain model maps nicely to an active record pattern. But if it does not, then I would not recommend CakePHP. If your domain model doesn't map to Active Record then you will spend a lot of time fighting the Cake way of doing things. And that's no fun. You would be much better off with a framework that implements a Data Mapper pattern (e.g. Zend).
Scaffolding
Scaffolding is temporary. It does handle foreign keys (if you define them in the model as well as in the database) but that's it. You can't modify the scaffolding. But, you can bake them!
When you bake a controller or view then you're basically writing the scaffold to a file as a jump-off point for your own implementation. After baking, you can do anything that you want. The downside of baking is that it doesn't update anymore when the models or database changes. So, if you bake a controller and views and you add fields to your model, then you need to add those fields manually to your controller and view code.
speed of development
In my case, I'm a lot faster developing a website in CakePHP then in plain code. But only if Active Record suits the application! See my first point. Even then, Cake is probably still faster, but I would be faster still with a better suiting framework.
Some other thoughts
large datasets
If you have very large datasets and big query results then Cake can be a problem. A find() operation wants to return an associative array, so all the rows are read, parsed and converted to arrays. If your result set is too large you will run out of memory. CakePHP does not implement ResultSet objects like many other Active Record implementations and that is a definite downside. You end up manually paging through your own data with subqueries. Yuck. Wich brings me to my next point:
arrays
Learn to love them because CakePHP does. Everything is an array and often they are large, complex and deep. It gets really annoying after a while. You can't add functions to arrays so your code is more messy than if CakePHP would have used nested object instances. The functions you can add to those objects can help keep your code clean.
oddities and inconsistencies
CakePHP has some real nasty stinkers hidden deep within. If Active Record suits your application then you will probably never run into them, but if you try to mold CakePHP into something more complex, then you will have to fight these. Some examples:
HABTM through a custom model uses the definition from the other side of the relationship that you're working on.
Some really odd places where your before/after triggers aren't called (e.g. not from an updateAll)
odd Model->field() behavior. It always queries from the database. So, be careful about updating model data without immediately saving it to the database. Some CakePHP functions fetch data from Model->$_data and some use Model->field(). The result may be entirely different resulting in some very hard to track down bugs.
In short
I would highly recommend CakePHP even for "large" sites, as long as your domain model fits nicely on top of Active Record. If not, pick a different framework.
Since you are asking for opinions, then I have to say that I advise AGAINST CakePHP.
My biggest gripe with it, is that it's still using PHP4 (written in and code generated). So, why go backwards? It is compatible for PHP5, but the framework itself revolves around PHP4.
I would recommend taking a look at Symfony or Zend. Symfony being the best if you want more structure in place - it forces you to adhere to the MVC structure that it has established.
The alternative is Zend, but it's more of a 'do-it-yourself' framework, or rather more of a set of libraries. You need to put it all together yourself, and it doesn't have any strict structure like Symfony.
There are obviously other frameworks, but I recommend the fore-said. Another one that you may want to look at is Codeigniter.
CakePHP tries to abstract away the database, so you write very little SQL (however, you write a lot of SQL snippets).
The basic process is to define your models, then define the relationship between models (hasOne, belongsTo, hasMany, hasAndBelongsToMany). You can put any conditions or default ordering on these associations you like. Then, whenever you fetch a row from the database, any associated rows are automatically fetched with it. It's very easy and powerful.
Everything comes with a bunch of configuration options, giving further flexibility. For example, when fetching data there is a recursion option which takes an integer. This value is how many associations deep Cake should fetch data. So if you wanted to fetch a user with all their associated data, and all the joined data to THAT, it's trivial.
Pretty much anything can be overridden on defined on the fly, and you can always fall back to writing your own SQL, so there's nothing Cake prevents you from doing...
I've not found much use for scaffolding. The answer to your question is yes, it'll auto populate joined dropdowns, etc. But I've never used it as a basis to build an interface. I tend to use a database tool to populate data early on rather than scaffolding.
I've built and also maintain several web-apps on CakePHP, and it is without question faster than 'rolling your own'. But I think that's true of any decent framework!
Unfortunately one of the weaker points is the documentation. Often you need to Google for answers as the official documentation is a bit hit-and-miss at times.
Just go with Yii framework, it's the best in this category.
(Note: This is a subjective question. You are asking for opinions. So I hope you don't mind if I give mine.)
(Edit: Ops. I mixed Cake with CI)
I used Code Igniter a while back. It did everything it should and was fairly easy to understand. However, for big projects, it lacked features. Many CI proponents say that this is it's strength as it keeps it fast and can make little RAM. This is true.
However, after developing one application with it, I found myself looking elsewhere so I would not have to write code that must have been written before. I looked at CakePHP and found it too restrictive and automagical. In particular, I needed some kind of ACL functionality. This lead me to Zend Framework. I learned that it is loosely coupled. I can include only the files I need. I can also make use of Zend_Application for large projects. It's object oriented design is a must when developing and maintaining large projects.
Yes, CI and CakePHP helped me to develop faster than with plain PHP. However, there are much more powerful frameworks. I hear and see good things about Symphony. There are quite a few more. I'm sure others will point them out.
I am fond of dbstructure definition of msaccess which lets defining at once and creating the data entry forms, datatables and reports at once easily.
I have been searching for some framework which would generate the data entry forms, data tables and reports easily. I guess the only thing I need to define is complete datatable structure.
Is there any like that or better one than that?
EDIT:
well i am afraid that PHP frameworks have been limited to programmers only. I would like to extend it with some automated functions like autoform in msaccess which would generate data entry form, auto report for data listing. So that my development time would be again some less. I found doctrine nearly matching my specification but not sure as i haven't fully explored doctrine
Cake offers both "hard" (bake) and "soft" scaffolding, which should be very close to what you want. It's still only meant as a quick proof-of-concept tool and to get you up and running faster so you can concentrate on programming the business logic. It's not meant as a hands-off solution nor to be used in production.
What you seem to be looking for is a database frontend like phpMyAdmin or SQL Buddy, not a PHP framework.
Symfony provides an admin generator that builds all the forms on the fly and it will also update itself when you change your db schema. It is based on doctrine which you say you looked at so that would make things a bit easier for you.
I'm creating a movies website, IMDB.com like.. I'm really new to PHP and programming at all but I have some books and StackOverflow of course :)
I have already done lot of the work, but now I have more than 600 lines of code (PHO only) per page and more than 20 database tables only for storing and geting the movie data (many-to-many relationships)
Most of the code are MySQLi queries (prepared statements) to insert/get data and loops. Nothing fancy, just basic PHP/MySQL.
I have some questions:
It is recommended to use MySQLi prepared statements for every SQL query or is better just to use old MySQL for internal PHP/database queries and leave prepared statements for user input only?
To get all the movie data and show it I need to get the data from more than 16 different tables. I use one MySQL query per table (somethimes more) and lots of loops. This is the correct way a website need to work?? I mean.. this is normal???
How can I simplify the code to simplify the reading? Can I separete all those queries to external files?? Can I create functions to handle each table query??
Hope you can give me a hand and maybe you have some more suggestions for correctly building such a website.
Thanks!!
As mentioned in the anwsers above I would also point you to using a framework that impliments the MVC design pattern. Along with that most of the frameworks have an ORM built in but if they do not you can look at Symphony or EZPDO is another good ORM to tie into your Model in (M)VC.
CodeIgniter is a very fast and light weight MVC framework that would allow you to bootstrap pretty quickly but you may also want to look into ZF (ZendFramework). ZF has a great framework feature set and is pretty flexible overall.
Beyond that be sure to seperate your reads and your writes in either or Model or your calls to the ORM of choice. This will allow you to slave data to multiple MySQL Boxes for bigger performance but allows you to use one database engine to start out.
Add in the ability to use Memcached so that you can cache your data/objects vs hitting the database.
When using cache put some thought into how you would expire cache for a database update. In other words if your selecting data from a database to display in a view and that data is has not changed you should not need to hit the database every time but rather pull it from memory. Once the data actually does change you'd want to invalidate that cache so it's not stale and then re-cache the new data.
memcached: http://www.danga.com/memcached/'
-facebook also has a version
CodeIgniter - http://codeigniter.com/
EZPDO - http://www.ezpdo.net/blog/?p=2
ZendFramework -http://framework.zend.com/
Consider looking at or using a web framework for your website.
symfony
CakePHP
CodeIgniter
Are some of the more mainstream ones. Learn from them if anything.
Prepared statements are just fine for your own internal queries to. You'll have a strutured approach for all queries.
Well it depends on what you're showing. But I would say that you normally could use joins to get the data you need from more tables. You'll have a lot less quering to get the correct data, and it sounds like all your data is connected somehow to the one movie you're showing.
As Peter D comments, I would recommend using a web framework to learn how to seperate out the database handling from the view. Are you using an object oriented approach now? Look at the MVC pattern that some of these frameworks implement, that'll get you going.
Like Peter D mention before add this one to the list of framework to use. Zend Framework http://framework.zend.com
Open source and free.
It is recommended to use MySQLi ...
Definitely MySQLi, but it's a big question by itself, if you start coding you'll need to grasp the basic of T-SQL to understand the difference.
To get all the movie data ...
It depends on alot of things. Size of database. Wanted results i.e. the information that need to be displayed, response time of the queries vs displaying in user view. Do you know about JOIN, UNION?
How can I simplify the code to ...
Yes to all theses questions. www.w3schools.com/php/ if it can be of any help and learn the MVC pattern. Useful to alot of programming language these days. Maybe a framework would help you here
To this questions:
"To get all the movie data and show it
I need to get the data from more than
16 different tables. I use one MySQL
query per table (somethimes more) and
lots of loops. This is the correct way
a website need to work?? I mean.. this
is normal???"
No. If I understand you correctly, you should be using some type of JOIN depending on the data you're retrieving from the database. Getting results for huge amounts of data, and then picking out only the pieces you want in PHP is much slower than letting the database do the work of sorting/retrieving only the records/info you want to show.
I highly recommend a somewhat dated but very easy to grasp book that covers PHP and MySQL/Databases in general: http://www.dmcinsights.com/phpmysql2/ - It covers a lot of "in practice" techniques along with the code, so it'd be great to learn from.
There is a apparently a third edition with updated info, but I have not looked at it.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
What's your experience with doctrine?
I've never been much of an ORM kind of guy, I mostlymanaged with just some basic db abstraction layer like adodb.
But I understood all the concepts and benifits of it. So when a project came along that needed an ORM I thought that I'd give one of the ORM framework a try.
I've to decide between doctrine and propel so I choose doctrine because I didn't want to handle the phing requirement.
I don't know what I did wrong. I came in with the right mindset. And I am by no means a 'junior' php kiddie. But I've been fighting the system each step of the way. There's a lot of documentation but it all feels a little disorganize. And simple stuff like YAML to db table creation just wouldn;t work and just bork out without even an error or anything. A lot of other stuff works a little funky require just that extra bit of tweaking before working.
Maybe I made some soft of stupid newbie assumption here that once I found out what it is I'll have the aha moment. But now I'm totally hating the system.
Is there maybe some tips anyone can give or maybe point me to a good resource on the subject or some authoritative site/person about this? Or maybe just recommend another ORM framework that 'just works"?
I have mixed feelings. I am a master at SQL only because it is so easy to verify. You can test SELECT statements quickly until you get the results right. And to refactor is a snap.
In Doctorine, or any ORM, there are so many layers of abstraction it almost seems OCD (obsessive/compulsive). In my latest project, in which I tried out Doctrine, I hit several walls. It took me days to figure out a solution for something that I knew I could have written in SQL in a matter of minutes. That is soooo frustrating.
I'm being grumpy. The community for SQL is HUGE. The community/support for Doctrine is minuscule. Sure you could look at the source and try to figure it out ... and those are the issues that take days to figure out.
Bottom line: don't try out Doctrine, or any ORM, without planning in a lot of time for grokking on your own.
I think mtbikemike sums it up perfectly: "It took me days to figure out a solution for something that I knew I could have written in SQL in a matter of minutes." That was also my experience. SAD (Slow Application Development) is guaranteed. Not to mention ugly code and limitations around every corner. Things that should take minutes take days and things that would normally be more complicated and take hours or days are just not doable (or not worth the time). The resulting code is much more verbose and cryptic (because we really need another query language, DQL, to make things even less readable). Strange bugs are all around and most of the time is spent hunting them down and running into limitations and problems. Doctrine (I only used v2.x) is akin to an exercise in futility and has absolutely no benefits. It's by far the most hated component of my current system and really the only one with huge problems. Coming into a new system, I'm always going back and forth from the db to the entity classes trying to figure out which name is proper in different places in the code. A total nightmare.
I don't see a single pro to Doctrine, only cons. I don't know why it exists, and every day I wish it didn't (at least in my projects).
we have been using Propel with Symfony for 2 years and Doctrine with Symfony for more than 1 year. I can say that moving to ORM with MVC framework was the best step we've made. I would recommend sticking with Doctrine eventhough it takes some time to learn how to work with it. In the end you'll find your code more readable and flexible.
If you're searching for some place where to start, I would recommend Symfony Jobeet tutorial http://www.symfony-project.org/jobeet/1_4/Doctrine/en/ (chapters 3, 6 covers the basics) and of course Doctrine documentation.
As I wrote above we have been using Doctrine for some time now. To make our work more comfortable we developed a tool called ORM Designer (www.orm-designer.com) where you can define DB model in a graphical user interface (no more YAML files :-), which aren't btw bad at all). You can find there also some helpful tutorials.
My experiences sound similar to yours. I've only just started using doctrine, and have never used Propel. However I am very disapointed in Doctrine. It's documentation is terrible. Poorly organised, and quite incomplete.
Propel and Doctrine uses PDO. PDO has a lot of open bugs with the Oracle Database. All of them related with CLOB fields. Please keep this in mind before starting a new project if you are working with Oracle. The bugs are open since years ago. Doctrine and PDO will crash working with Oracle and CLOBs
I'm using Doctrine in a medium sized project where I had to work from pre-existing databases I don't own. It gives you alot of built in features, but I have one major complaint.
Since I had to generate my models from the databases and not vice-versa, my models are too close to the database: the fields have very similar names to the database columns, to get objects you have to query in what is essential sql (where do I put that code, and how do I test it?), etc.
In the end I had to write a complex wrapper for doctrine that makes me question if it wouldn't have been easier to just use the old dao/model approach and leave doctrine out of the picture. The jury is still out on that. Good luck!
Using Doctrine 2.5 in 2015. It was seemingly going well. Until I wanted to use two entities (in a JOIN). [it's better now after I got a hang of DQL]
Good:
generating SQL for me
use of Foreign Keys and Referential Integrity
InnoDB generation by default
updates made to SQL with doctrine command line tool
Okay:
being hyper-aware of naming and mapping and how to name and how to map entities to actual tables
The Bad
takes a lot of time - learning custom API of query builder. Or figuring out how to do a simple JOIN, wondering if better techniques are out there.. Simple JOINs seem to require writing custom functions if you want to do object oriented queries.
[update on first impression above] -- I chose to use DQL as it is most similar to SQL
It seems to me that the tool is great in concept but its proper execution desires much of developer's time to get onboard. I am tempted to use it for entity SQL generation but then use PDO for actual Input/Output. Only because I didn't learn yet how to do Foreign Key and Referential Integrity with SQL. But learning those seems to be much easier task than learning Doctrine ins and outs even with simple stuff like a entity equivalent of a JOIN.
Doctrine in Existing Projects
I (am just starting to) use Doctrine to develop new features on an existing project. So instead of adding new mysql table for example for the feature, I have added entities (which created the tables for me using Doctrine schema generation). I reserve not using Doctrine for existing tables until I get to know it better.
If I were to use it on existing tables, I would first ... clean the tables up, which includes:
adding id column which is a primary/surrogate key
using InnoDb/transaction-capable table
map it appropriately to an entity
run Doctrine validate tool (doctrine orm:validate-schema)
This is because Doctrine makes certain assumptions about your tables. And because you are essentially going to drive your tables via code. So your code and your tables have to be in as much as 1:1 agreement as possible. As such, Doctrine is not suitable for just any "free-form" tables in general.
But then, you might be able to, with some care and in some cases, get away with little things like an extra columns not being accounted for in your entities (I do not think that Doctrine checks unless you ask it to). You will have to construct your queries knowing what you are getting away with. i.e. when you request an "entity" as a whole, Doctrine requests all fields of the entity specifically by column name. If your actual schema contains more column names, I don't think Doctrine will mind (It does not, as I have verified by creating an extra column in my schema).
So yes it is possible to use Doctrine but I'd start small and with care. You will most likely have to convert your tables to support transactions and to have the surrogate index (primary key), to start with. For things like Foreign Keys, and Referential Integrity, you'll have to work with Doctrine on polishing your entities and matching them up perfectly. You may have to let Doctrine re-build your schema to use its own index names so that it can use FK and RI properly. You are essentially giving up some control of your tables to Doctrine, so I believe it has to know the schema in its own way (like being able to use its own index names, etc).
A little late for the party, but let me throw my two cents here. I will make connections with Laravel, because that is the framework I use.
Active Record vs. Data Mapping vs. Proper OOP
Laravel and many other frameworks love Active Record. It might be great for simple applications, and it saves you time for trivial DB management. However, from the OOP perspective it is a pure anti-pattern. SoC (Separation of Concerns) just got killed. It creates a coupling between the model attributes and SQL column names. Terrible for extensions and future updates.
As your project growths (and yes, it will!), ActiveRecord will be more and more of pain. Don't even think of updating SQL structure easily. Remember, you have the column names all over your PHP code.
I was hired for a project that aims to be quite big down the road. I saw the limits of ActiveRecord. I sat back for 3 weeks and rewrote everything using a Data Mapper, which separates DB from the layers above.
Now, back to the Data Mapper and why I didn't choose Doctrine.
The main idea of Data Mapper is, that it separates your database from your code. And that is the correct approach from the OOP perspective. SoC rules! I reviewed Doctrine in detail, and I immediately didn't like several aspects.
The mapping. Why in a world would anyone use comments as commands? I consider this to be an extremely bad practise. Why not just use a PHP Class to store the mapping relations?
Yaml or XML for the map. Again, Why?? Why wasting time parsing text files, when a regular PHP Class can be used. Plus, a class can be extended, inhereted, can contain methods, not just data. Etc.
If we have a mapper and a model carrying data, then it should be the mapper storing the model. Methods such as $product->save() ar just not good. Model handles data, it should not care about storing anything to the DB. It is a very tight coupling. If we spend time building a mapper, then why not having $mapper->save($product). By definition, it shall be the mapper knowing how to save the data.
Tools such as Doctrine or Eloquent save time at the beginning, no doubt about it. But here is the tricky question for everyone individually. What is the right compromise between /development time/future updates/price/simplicity/following OOP principles/? In the end, it is up to you to answer and decide properly.
My own DataMapper instead of Doctrine
I ended up developing my own DataMapper and I have already used it for several of my small projects. It works very nicely, easy to extend and reuse. Most of the time we just set up parameters and no new code is required.
Here are the key principles:
Model carries data, similar to Laravel's model. Example variable $model for the following examples.
ModelMap contains a field that maps the attributes of the Model to the columns of the table in the SQL database. ModelMaps knows the table name, id, etc. It knows which attributes should be tranfromed to json, which attributes should be hidden (e.g. deleted_at). This ModelMap contains aliases for columns with the same name (connected tables). Example variable: $modelMap.
ModelDataMapper is a class that accepts Model and ModelMap in the controller and provides the store/getById/deleteById functionalities. You simply call $modelMapper->store($model) and that's all.
The base DataMapper also handles pagination, search ability, converting arrays to json, it adds time stamps, it checks for soft deletes, etc. For simple usages, the base DataMapper is enough. For anything more complex, it is easy to extend it using inheritance.
Using Doctrine ORM in 2016 with Approx experience ~2 - 2.5 years.
Inherent Inconsistency
SELECT i, p
FROM \Entity\Item i
JOIN i.product p
WHERE ...
Assume entities are Item and Product. They are connected via Item.product_id to Product.id, and Product contains Product.model that we want to display along with Item.
Here is retrieval of same "product.model" from database, using the above SQL but varying SQL parameters:
//SELECT i, p
$ret[0]->getProduct()->getModel();
//SELECT i as item, p as product
$ret[0]['item']->getProduct()->getModel();
//SELECT i as item, p.model as model
$ret[0]['model'];
Point I am making is this:
Output ResultSet structure can change drastically depending on how you write your DQL/ORM SELECT statement.
From array of objects to array of associative array of objects, to array of associative array, depending on how you want to SELECT. Imagine you have to make a change to your SQL, then imagine having to go back to your code and re-do all the code associated with reading data from the result set. Ouch! Ouch! Ouch! Even if it's a few lines of code, you depend on the structure of result set, there is no full decoupling/common standard.
What Doctrine is good at
In some ways it removes dealing with SQL, crafting and maintaining your own tables. It's not perfect. Sometimes it fails and you have to go to MySQL command line and type SQL to adjust things to the point where Doctrine and you are happy, to where Doctrine sees column types as valid and to where you are happy with column types. You don't have to define your own foreign keys or indices, it is done for you auto-magically.
What Doctrine is bad at
Whenever you need to translate any significantly advanced SQL to DQL/ORM, you may struggle. Separately from that, you may also deal with inconsistencies like one above.
Final thoughts
I love Doctrine for creating/modifying tables for me and for converting table data to Objects, and persisting them back, and for using prepared statements and other checks and balances, making my data safer.
I love the feeling of persistent storage being taken care of by Doctrine from within the object oriented interface of PHP. I get that tingly feeling that I can think of my data as being part of my code, and ORM takes care of the dirty stuff of interacting with the database. Database feels more like a local variable and I have gained an appreciation that if you take care of your data, it will love you back.
I hate Doctrine for its inconsistencies and tough learning curve, and having to look up proprietary syntax for DQL when I know how to write stuff in SQL. SQL knowledge is readily available, DQL does not have that many experts out in the wild, nor an accumulated body of knowledge (compared to SQL) to help you when you get stuck.
I'm not an expert with Doctrine - just started using it myself and I have to admit it is a bit of a mixed experience. It does a lot for you, but it's not always immediately obvious how to tell it to do this or that.
For example when trying to use YAML files with the automatic relationship discovery the many-to-many relationship did not translate correctly into the php model definition. No errors as you mention, because it just did not treat it as many-to-many at all.
I would say that you probably need time to get your head around this or that way of doing things and how the elements interact together. And having the time to do things one step at a time would be a good thing and deal with the issues one at a time in a sort of isolation. Trying to do too much at once can be overwhelming and might make it harder to actually find the place something is going wrong.
After some research into the various ORM libraries for PHP, I decided on PHP ActiveRecord (see phpactiverecord). My decision came down to the little-to-no configuration, light-weight nature of the library, and the lack of code generation. Doctrine is simply too powerful for what I need; what PHP ActiveRecord doesn't do I can implement in my wrapper layer. I would suggest taking a moment and examining what your requirements are in an ORM and see if either a simple one like PHP ActiveRecord offers what you need or if a home-rolled active record implementation would be better.
For now I'm using Symfony framework with Doctrine ORM,
how about using Doctrine together with plain queries?
For e.g. from knpuniversity, I can create custom repository method like:
public function countNumberPrintedForCategory(Category $category)
{
$conn = $this->getEntityManager()
->getConnection();
$sql = '
SELECT SUM(fc.numberPrinted) as fortunesPrinted, AVG(fc.numberPrinted) as fortunesAverage, cat.name
FROM fortune_cookie fc
INNER JOIN category cat ON cat.id = fc.category_id
WHERE fc.category_id = :category
';
$stmt = $conn->prepare($sql);
$stmt->execute(array('category' => $category->getId()));
return $stmt->fetch();
... lines 30 - 37
}
I'm just use Doctrine Entities for e.g. creating an processing forms,
When I need more complex query I just make plain statement and take values I need, from this example I can also pass Entity as variable and take it values for making query. I think this solution is easy understand and it takes less time for building forms, passing data for them and writing complex queries is not as hard as writing them with Doctrine.