Symfony: Doctrine & the Database

Buy Access

With already two courses checked off, you are primed and ready to put Symfony to work! And that's what this course is all about: making things more interesting by talking to the database with Doctrine.

Doctrine has a reputation for being tough to learn, and that's unfortunate, because it's an amazing tool. In this tutorial, we'll get you rolling with Doctrine: learn how to use it, how to get hard work done easily and how to avoid the common pitfalls that can make Doctrine hard:

  • Creating entity classes
  • Managing migrations
  • Saving new data
  • Querying for data
  • Custom repositories
  • Custom queries and the query builder
  • Fixtures (Dummy data) using Faker

... and (like always) a lot more goodies are mixed in.

Your Guides

Ryan Weaver Leanna Pelham

Questions? Conversation?

  • 2017-11-16 Diego Aguiar

    You may need to create a model class that maps all the fields you need for this form, then create a FormType based on that class, it can contain embedded forms of your entities so you don't repeat yourself.
    You can watch an example of creating an embedded form here:
    or in the symfony docs:

  • 2017-11-15 Peter

    Thank you for response.

    Let me explain, I would like first - to prepare my spider of manufacturers, then add categories to them, and then - types, or models to categories.

    I'm (mostly) not shure how to handle doctrine to write those three entities in the same time. - I have already made the may-to-one relations from last category entity to manufacturer, gave fields passing right Object to 'set' methods in entities

    I sow in this tutorial on #3 or #4 episode smth that can help me:


    but how handle the form if I want set only manufacturer? - is it possible?, or better way is just make special form for manufacturer?.

    Ajax in symfony is a little bizzare for me...

  • 2017-11-15 Diego Aguiar

    For that case I would do it with JS, because you need to generate your forms dynamically. You gonna need an extra endpoint (backend) where you can pass the options selected by user, and then return a rendered form as the response of the AJAX call (I'm assuming you are familiar making AJAX calls, if not, you can watch our JS tutorials, they are awesome!)


  • 2017-11-15 Peter

    Hi, Yes Diego that is correct.

  • 2017-11-14 Diego Aguiar

    Hey Peter!

    Let me see if I understood you well. What you need is like a three steps form, where you have to choose an option first, so next form (step) gets filled up based on the chosen option (because they are related), and for step three is the same formula. Am I correct?


  • 2017-11-14 Peter

    BMD = BMW ; -)

  • 2017-11-14 Peter

    I already know that I can use EntityType, I'm confused how pass to next part of form variable.
    For example 1st is id of BMD category, so next part of form need to have only BMW matches and so on

  • 2017-11-14 Peter

    Hi Ryan and Leanna, Victor,
    thank you for your courses and great effort and work.

    It woud be great to hear some advices from You.

    I gave 3 entities.

    1) Manufacturer, 2) manufacturerModel, 3) ManufacturerModelTyp

    they connected many-to-one from 3->2->1
    so for example product will looks like

    1) BMW,
    2) seriie 5
    3) E12

    and product table (entity) have separate fields for id1, id2, id3

    how to handle with that kind of relation in form?

    some advices, links to examples?

    best regards,

  • 2017-11-07 weaverryan

    Hey Xal!

    Sorry for the late reply - for some reason Disqus put your comment in Spam :(. The latest version of Alice indeed contains a lot of changes. See our note about it near the top of the script - Basically, we recommend using the older version for following the tutorial :).


  • 2017-11-06 Diego Aguiar

    Yes, you should be able to keep your relationships in the base class only. Try configuring your base class with these annotations

    * @Entity
    * @InheritanceType("SINGLE_TABLE")
    * @DiscriminatorColumn(name="discr", type="string")
    * @DiscriminatorMap({"person" = "Person", "employee" = "Employee"})

    You can follow the steps here: http://docs.doctrine-projec...


  • 2017-11-06 Ferdinand Geerman

    Hey Diego,

    I tried that already, the Single Table approach, but without any success

    I have a abstract BasePerson class (/*@MappedSuperClass*/) and a abstract BaseAddress (/*@MappedSuperClass*/)
    In the BasePerson I have an $address property. I tried to set the relation as follow:

    * @ORM\OneToOne(targetEntity="BaseAddress")
    * @ORM\JoinColumn(name="address_id", referencedColumnName="id")

    For my project I have the subclasses Person and Address (/**@ORM\Table(name="person") @ORMEntity() */
    /**@ORM\Table(name="address") @ORMEntity() */)

    When I do doctrine:migrations:diff i get the error:

    Column name `id` referenced for relation from Entity\Person towards Entity\BaseAddress does not exist.

    I guess the Person entity tries to access the BaseAddress entity, which is not an entity. That's is the reason I defined the relation in the subclass Person to the subclass Address.

    Is there a way to define that relation solely in the abstract classes, so that the subclasses person and address inherit the relation?

  • 2017-11-06 Diego Aguiar

    Hey Ferdinand Geerman

    You are correct, the Base class should be the only one holding the relationship, but, you will need to configure your entities in a special way (I believe it's not covered in this course)
    Doctrine give us a way to manage subclass entities, there are two ways, via single table or multiple tables (each for subclass). Of course this depends on your use case, but if you are not going to add extra fields specific to every subclass (only different behaviour), you should consider using "Single Table" approach.

    You can read more detailed information for how to implement it here: http://docs.doctrine-projec...


  • 2017-11-06 Ferdinand Geerman

    Hi Ryan,

    A very nice tutorial!
    Just one question, could you give me some more insights about the relation between abstract entities?
    Consider the following situation:
    BaseClassA has a relation to BaseClassB, in which all the subclasses will inherit that relation. However when I run the doctrine:migrations:diff or doctrine:schema:update I get an error about:
    Column name `id` referenced for relation from SubClassA towards BaseClassB does not exist. Both base entities has the protected $id property. Right now I defined the relation in the subclasses to make it work, but I suppose the relation should be in the abstract entities, right?

  • 2017-10-29 Xal

    I couldn't get the dummy data fixtures work with the latest version of alice. I've changed the code to use NativeLoader instead of Fixtures, but when trying to run doctrine:fixtures:load from the console I get a [Symfony\Component\Debug\Exception\ContextErrorException] Notice: Undefined offset: -5 error. Any ideas?

  • 2017-09-01 Diego Aguiar

    Oh, a permissions problem, of course!
    Things like that happens all the time. I'm glad to hear you could fix your problem :)

    Have a nice day!

  • 2017-09-01 Weli Orlu

    I have dicovered the problem. It was caused by improper permissions on the cache directory. Reinstalled everything using composer

  • 2017-08-28 Diego Aguiar

    Hey Weli Orlu

    When running in dev mode, you shouldn't be worry about clearing cache (except for a few cases), can you double check that you are hitting the correct route? and can you tell me more about those changes?


  • 2017-08-27 Weli Orlu

    Hi Ryan and Leanna. I have been following through the course but now changes in my controller doesn't give a corresponding response. I have deleted emptied the cache directory. then ran bin/console cache:warmup --env=dev followed by bin/console cache:warmup --env=dev. With no change in response

  • 2017-06-26 weaverryan

    Awww, cheers! Thanks for the very nice comment - I'm very happy the tutorial is useful!

  • 2017-06-26 Yan Yong

    Hi Ryan and Leanna, Just want to say thank you for creating this tutorial. I have finished it without any trouble. I learned a lot by doing it, please keep working on it, this is very helpful.

  • 2017-04-11 Diego Aguiar

    Hey Claire!

    In this course we don't go through deleting a Genus, but there is other tutorial where we cover a lot more about working with entities "Doctrine Collections", it is a bit more advance topic but you can find it very helpful and fun!
    Check this chapter, it shows how to remove an item from an entity collection:

    Have a nice day!

  • 2017-04-11 claire


    Fantastic tutorials, it been a great way of learning Symfony ! I was wondering (you probably already have it covered and I am being blind) if you cover 'deleting a genus'?


  • 2017-02-21 Victor Bocharsky

    Yes, exactly what I mean! The query builder allows us easily do it. Thanks for sharing it ;)


  • 2017-02-20 Sergey

    I already found =)

  • 2017-02-20 Victor Bocharsky

    You're welcome! Btw, in some course we already do similar refactoring in a repository class (which I explained above) to get rid of code duplication, but to be honest, I don't remember what course and what chapter it was. :)


  • 2017-02-20 Sergey

    Thank you for quick feedback!!

  • 2017-02-20 Victor Bocharsky

    You're absolutely right ;)


  • 2017-02-20 maxii123

    Ignore. You have to open a specific video first and there it is. Thank you.

  • 2017-02-20 maxii123

    Where is the downloadable course script pdf for this tutorial?

  • 2017-02-20 Victor Bocharsky

    Hey Sergey,

    Yes, the findAllPublishedUpdatedMoreThan() method sounds great! What about duplicated logic - well, you can move duplicated code into the private method inside your repository method if you use query builder. So this way you'll get rid of code duplication - your public methods will contain only unique conditions and reuse private method which shares common logic.


  • 2017-02-19 Sergey

    Hi. Thanks a lot for great course. But i have a question.

    In last lesson "Custom Queries" we created findAllPublishedOrderedBySize method which return all published Genuses.

    What is the best way to have a method for getting all published Genuses that were update more than 3 months ago?

    Should i write another one findAllPublishedUpdatedMoreThan($date) {} ?

    It's so looking so strange... Because in this way i need to duplicate published logic and do it every time when i need to get Genuses filtered by another property (for example update more than and less then date)

    I'm confused now...

  • 2017-01-13 Victor Bocharsky

    Hey Cristian,

    Great! Let me know if you still have troubles with it.


  • 2017-01-12 Cristian Merli

    Hi Victor, no I couldn't connect but i found a way to reset my root password, and now i feel confident I can give it another try! thanks!

  • 2017-01-12 Victor Bocharsky

    Hi Cristian,

    Please, double-check your database credentials in `app/config/parameters.yml`. Are they valid for your database? Can you connect with these credentials using a MySQL client, like MySQL WorkBench or PhpMyAdmin?..


  • 2017-01-11 Cristian Merli

    Hi, unfortunately I am stuck at Lecture 2. Whenever I try to create the database from the console I get the "Access denied for user 'root'@'localhost'" errors.
    I am using Ubuntu, any clue?

  • 2016-10-15 Benson Twumasi

    Thanks Man

  • 2016-10-15 weaverryan

    Hey Beson!

    Awesome! To your questions:

    1) It's possible (I have never done it, but others certainly have) to reverse engineer your existing database in order to create entities that match it. Exactly how successful this will be depends on how clean or messy your current database is. Here are the details:

    2) If your empBirthday field is a Doctrine datetime or date type (e.g. @ORM\Column(type="date"), which it should be, then what you should set on this property is a DateTime *object* - not just a date string. The reason you're getting this error is that Doctrine is expecting a DateTime object, so it's trying to call format() on your string when inserting it into the database. So, your code should look something like this:

    $employee->setEmpBirthday(new \DateTime('1984-11-12'));

    Even though this will store as a string in the database, you'll always deal with DateTime objects with Doctrine, which is actually pretty nice. Later, if you wanted to print the birthday, it would be something like:

    echo $employee->getEmpBirthday()->format('Y-m-d');


  • 2016-10-15 Benson Twumasi

    it worked. You re Genus. lol. Thanks.

    However l have a new challenges. do i use exiting database in my projects instead of recreating using doctrine.
    2. i have update my database with birthday. l get this date format error
    "Call to a member function format() on a non-object" when inserting to the tables using this


  • 2016-10-15 weaverryan

    Hi Benson!

    Welcome to Symfony! I can definitely help you with this - it's just one *small* thing :). In your route, you have `/employee/{employeeName}`. This means that you are allowed to have a `$employeeName` argument to your controller. But, you have `$employeeId`. Symfony is basically saying:

    > Hey! I see `$employeeId` as an argument to showAction(), but I don't see a {employeeId} in your route, so I don't know what value to pass here!

    The fix is to make these match - probably in your case by changing the route to `/employee/{employeeId}`. Also, when you do this, if you have any links to this route (the employee_show route), you'll need to update those as well to now pass employeeId instead of employeeName (

    Let me know if this helps!


  • 2016-10-15 Benson Twumasi

    {{ employee.empId }}
    <td>{{ employee.empFirstname }}</td>
    <td>{{ employee.empLastname }}</td>

  • 2016-10-15 Benson Twumasi

    hi Ryan

    Am trying my hands on my first symfony project and having this difficulties.

    Controller "AppBundle\Controller\EmployeeController::showAction()"
    requires that you provide a value for the "$employeeId" argument. Either
    the argument is nullable and no null value has been provided, no
    default value has been provided or because there is a non optional
    argument after this one.

    this the code


    {{ employee.empId }}
    <td>{{ employee.empFirstname }}</td>


    * @Route("/employee/{employeeName}", name="employee_show")
    public function showAction($employeeId)

    $employee = $this->getDoctrine()->getManager();
    $employeeId =$employee->getRepository('AppBundle:Employee')
    ->findOneBy(['employeeId' =>$employeeId]);

    if (!$employee) {
    throw $this->createNotFoundException('employee not found');
    ->info('Showing Employee: '.$employeeId);

    return $this->render('employee/viewEmployeeDetails.html.twig', array(
    'name' =>$employeeId,
  • 2016-08-31 Victor Bocharsky

    Hey Marcelo,

    Could you debug it by running bin/console doctrine:schema:validate command? And let me know its result. It shows whether you have any invalid mapping.

    BTW, you probably use `user` column name instead of `user_id` in some of your indexes or uniqueConstraints. Please, recheck that all your entities (not only Course entity) have `user_id` column name instead of `user` inside @ORM\Table() annotation. Actually, you have to check all the entities which have relation to the User entity.


  • 2016-08-30 Marcelo

    Hi there!
    I'm having the same problem:
    My class:

    * Course
    * @ORM\Table(
    * name="course",
    * uniqueConstraints={
    * @ORM\UniqueConstraint(name="unique_course", columns={"name", "institution_id", "user_id"})
    * },
    * indexes={
    * @ORM\Index(name="IDX_169E6FB9A76ED395", columns={"user_id"})
    * }
    * )
    * @ORM\Entity(repositoryClass="MainBundle\Entity\CourseRepository")
    * @UniqueEntity(
    * fields={"name", "institution", "user"},
    * errorPath="name",
    * message=""
    * )
    * @ORM\HasLifecycleCallbacks
    class Course extends AbstractEntity
    * @var \MainBundle\Entity\User
    * @ORM\Column(name="user_id")
    * @ORM\ManyToOne(targetEntity="MainBundle\Entity\User", inversedBy="series")
    * @ORM\JoinColumn(name="user_id", referencedColumnName="id")
    private $user;

    Then when I run:

    console doctrine:migrations:diff
    There is no column with name 'user' on table 'course'.
  • 2016-08-15 Henri Tompodung

    Thank you Ryan!

  • 2016-08-11 weaverryan

    Hi Henri!

    It depends :). I'm not really sure how the database looks - as it's really custom to your application. The first step would be to setup a Menu entity with the proper relationships. Once you have that, it should be pretty easy to figure out how you would do all of this.

    BUT, there is always another option. If you have a really custom query, there's nothing wrong with writing and using a raw SQL query, instead of doing things through Doctrine. In fact, in some cases, this might be the best idea. We talk about how to do that here:


  • 2016-08-09 Henri Tompodung

    How to make recursive function in symfony 3 with doctrine?
    I have script PHP native like below:


    function html_menu(&$strmenu="", $parent=0) {
    $query = "SELECT * FROM menu
    WHERE code_parent='$parent'
    ORDER BY code_menu";
    $sql = mysql_query($query);

    if (mysql_num_rows($sql) > 0) {
    $strmenu .= '<ul>'.PHP_EOL;

    // show children
    while ($row = mysql_fetch_array($sql)) {
    $strmenu .= "<li>".PHP_EOL;
    $strmenu .= sprintf(" % s ", $row['link'], $row['nm_menu'], $row['nm_menu']).PHP_EOL;

    html_menu($strmenu, $row['code_menu']);
    $strmenu .= "</li>".PHP_EOL;

    if (mysql_num_rows($sql) > 0) {
    $strmenu .= '</ul>'.PHP_EOL;


    $strmenu = "";
    html_menu($strmenu, 0);
    echo $strmenu;

  • 2016-07-20 JLChafardet

    weaverryan yeah! suddenly i became swamped in work, a company in the netherlands hired some hours (i work as a freelance contractor some hours a week aside from my business, you know, extra coins wont hurt ever, as long as they dont take up sleep time nor weekends [I myself used to work even weekends for the past 18 years, lost a lot of time on that, so now im properly taking care of not just my mental health but also my body's health and my spiritual peace haha]) so got 2 projects going on my 8h/day mon-fri work routine, 3 extra hours a day contracted in the NL for this laravel project, havent had much time to browse or comment! but I take to heart everything I learnt here! I'm still much inexperienced, but im growing with each line of code i write, getting to know symfony better bit by bit.

    regarding laravel, well its indeed nice, it has a lot of out of the box features that are really cool, yet it feels way too much microframeworkish, thats just overgrown, it doesnt feel by any means a fully featured framework in and on itself, but as stated a "overgrown" microframework. I may be wrong tho.

  • 2016-07-20 weaverryan

    Hey! No worries :) Laravel is not my preference, but it's nice too - you can probably bring back some nice tools/lessons from it back to Symfony.

    I look forward to having you back! - I noticed you hadn't commented in awhile ;)

  • 2016-07-20 JLChafardet

    weaverryan my subscription expired, but ill renew it next month, this month im tied down horribly with a laravel project that i gota take care of. (:S didnt want to write in laravel, but the customer's mind is dead set on it, wanted to try to get them to use symfony)

  • 2016-07-20 weaverryan

    Awesome :) - glad you got it figured out. It's configurable, but out-of-the box with Doctrine in Symfony, property names are "snaked-cased" like this, which I kinda like (but it can surprise at first!)

    Cheers JLChafardet!

  • 2016-07-19 JLChafardet

    ok my bad, found the issue, was on the indexes, as im using isRead variable, but the table name is in fact "is_read"

  • 2016-07-19 JLChafardet

    hey guys, I'm having an issue with the migrations here.

    * @ORM\Column(type="boolean")
    private $isRead;

    when I run console doctrine:migrations:diff i get the following error

    jl@josefo-d: /var/www/vhosts/project-s3 on master [!?]
    $ console doctrine:migrations:diff

    There is no column with name 'isRead' on table 'contact'.

    what could be the issue here?

  • 2016-06-28 JLChafardet

    Consider this tho: this works flawlessly in propel! (just for argument sake, if it works in propel, out of the box, no extra bundle required, i think it would be great for doctrine to have it too).
    back on topic:
    yeah i think ill get rid of loggable/versionable behavior. as the translatable one is more important for the customer, offering "versions" was an idea of mine and i actually never really offered it, i just "wanted" to give it as an extra

    i was pointed at seems its a more robust audit tool, which could serve, ill consider it for later implementation to see if it works in my favor

  • 2016-06-28 weaverryan

    Those two behaviors specifically will be very difficult to get working together. And it kind of makes sense - versioning is already hard in a relational database (you need to duplicate each row before it's changed). Add onto that the fact that each row now has many translations, and you quickly (and correctly) get a big, ugly matrix. I use some of the more magic behaviors sparingly - learning from Doctrine version 1 that the magic has costs. For example, on our apps, we don't use Loggable/versionable or soft deletable.

    So, my best advice is to consider doing *less* - these behaviors try to make a relational database do things that it doesn't naturally do well. If you layer on too many, I don't think you'll be happy.


  • 2016-06-28 JLChafardet

    seems is not possible to use them together. i hate this, i really dont want to implement my own behaviors.

  • 2016-06-27 JLChafardet

    ok, getting on my way to properly have Versioned and Translatable working together! what a freaking long day.

    the issue seems to be related to the fact that to add a new language you have to actually "edit" and when you "edit" it generates a new version.

    its pissing me off badly.

  • 2016-06-27 JLChafardet

    translatable and versionable (loggable) dont seem to be friendly. adding a new translation is interpreted by loggable as a new version of the row.

  • 2016-06-27 JLChafardet

    i seem to be advancing on the translations, ill keep you posted lol

  • 2016-06-27 weaverryan

    Yep, I am aware of this - it's tricky because if you *do* include the unfolded code blocks, then some of them are HUGE (in some tutorials, we show a cached file that is a few thousand lines long) and you also lose perspective of the 5 lines that we want you to focus on. But, if they're folded, then sometimes you can't see enough :). I don't think there's a perfect way - except to check out the code on the site ;)


  • 2016-06-27 weaverryan

    Nice work JLChafardet

    I think what happens in a lot of cases with Doctrine is that:

    A) it requires more typing to set something up and
    B) The documentation often isn't clear (so that it's difficult to know what to type!)

    Anyways - nice job, and thanks for sharing your thoughts - I definitely have this on the "idea" list :)


  • 2016-06-27 JLChafardet

    I think it would do great to have a full blown tutorial/track coverage.

    I've been playing with the Versioned and Translatable behaviors, and at least in 5 hours of work, i CANNOT get them to work properly.

    heres the basic main reason why now that I see how Dogtrine works why some people prefer to use Propel.

    I'm going to keep at it, as i just cant accept defeat, but this is just ridiculously complex for something that should be ridiculously simple.

    getting "Versioned" fields doesnt seem to work on the fly as it should, what i mean is this:

    namespace AppBundle\Entity;

    use Doctrine\ORM\Mapping as ORM;
    use Gedmo\Mapping\Annotation as Gedmo;
    use Gedmo\Translatable\Translatable;

    * @ORM\Entity
    * @Gedmo\Loggable()
    * @Gedmo\SoftDeleteable(fieldName="deletedAt", timeAware=false)
    * @ORM\Table(name="blog", indexes={@ORM\Index(name="title_idx", columns={"title"}),@ORM\Index(name="slug_idx", columns={"slug"})})
    class Blog implements Translatable
    * @ORM\Id
    * @ORM\GeneratedValue(strategy="AUTO")
    * @ORM\Column(type="integer", unique=true)
    private $id;

    * @Gedmo\Translatable()
    * @Gedmo\Versioned()
    * @ORM\Column(type="string")
    private $title;

    * @Gedmo\Timestampable(on="create")
    * @ORM\Column(type="datetime")
    private $createdAt;

    * @Gedmo\Timestampable(on="update")
    * @ORM\Column(type="datetime", nullable=true)
    private $updatedAt;

    * @ORM\Column(type="datetime", nullable=true)
    private $deletedAt;

    public function getId()
    return $this->id;

    public function getTitle()
    return $this->title;

    public function setTitle($title)
    $this->title = $title;
    return $this;



    namespace AppBundle\Controller;

    use AppBundle\Entity\Blog;
    use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
    use Symfony\Bundle\FrameworkBundle\Controller\Controller;

    class BlogController extends Controller
    * @Route("/test")
    public function newAction()
    //we insert
    $blog = new Blog();
    $blog->setTitle('Titulo 1 ');
    $blog->setDescription('Lorem ipsum dolor sit amet, consectetur adipiscing elit.');

    Praesent eleifend facilisis sapien a lobortis. Aliquam semper feugiat lectus. Cras non ligula nec odio gravida maximus sed eu sem. Quisque in ornare sem odio

    $em = $this->getDoctrine()->getManager();

    //we retrieve (comment the above code and run the code below this line)
    $em = $this->getDoctrine()->getManager();
    $blogEm = $this->getDoctrine()
    $articles = $blogEm->findAll();

    //IT DOESNT get any of the Versioned fields.

    the answer from the dump is:

    BlogController.php on line 36:
    array:1 [▼
    0 => Blog {#565 ▼
    -id: 1
    -title: ""
    -slug: "article-one-1"
    -mainImage: "image"
    -description: ""
    -content: ""
    -isVisible: false
    -locale: null
    -createdAt: DateTime {#561 ▼
    +"date": "2016-06-27 15:45:36.000000"
    +"timezone_type": 3
    +"timezone": "America/Caracas"
    -updatedAt: DateTime {#562 ▼
    +"date": "2016-06-27 15:45:36.000000"
    +"timezone_type": 3
    +"timezone": "America/Caracas"
    -deletedAt: null
  • 2016-06-27 JLChafardet

    BTW! weaverryan are you aware that when you download the transcript for the courses, the code is folded when the pdf is created?

    you should look into that, so the pdf is generated with the code entirely expanded.

  • 2016-06-27 JLChafardet

    Heya weaverryan !

    Tried alone first, pure doctrine extensions, installation was a bit rough, but went ok! tho couldnt get translatable to work, then went with StofDE and got it working, believe it or not, was touger to get StofDE working tho.

    just find really irritating it seems translatable uses a single table to translate everything, will have to see that a little bit ahead! i will port some apps from silex to s3, but on my free time, for now gota keep up working on what gota be done hehe

  • 2016-06-26 weaverryan

    Yo JLChafardet!

    You beat me to it - but I was going to recommend gedmo - so very happy you found it. It's a great library, though sometimes its documentation isn't AS great as it could be :). Are you using it with StofDoctrineExtensionBundle? It doesn't do much, but if helps alleviate some of the setup work (but it's docs aren't great). I'm not sure about Translatable - that's one I haven't used yet.

    But yea, the extensions are super fun - it might be good for a mini-tutorial :)


  • 2016-06-26 JLChafardet

    ok I've been playing with the gedmo/doctrine-extensions, seems i've gotten most of it to work, except translatable, or at least im not seeing it create any tables for the translations, loggable, softdeletable, timestampable, sluggable tho seems to work just fine.

    gota keep playing with it it seems.

    dogtrine's learning curve is really step! oh well, who doesnt love a good challenge eh!

  • 2016-06-26 JLChafardet

    yo yo weaverryan

    hows all going? I have a question, lol highly important to me atm (maybe its covered in a different tutorial yet i havent had much time lately to browse around, if so would you please point me in the right direction?).

    I'm interested in knowing about doctrine behaviors, for example, I use a lot in propel timestampable, softdelete and well of course, i18n
    I'm not sure how to even begin to work that out on doctrine the annotations. i checked you have a knp bundle called doctrine-behaviors but they seem to be overly complicated to use, is there nothing of the sort native out of doctrine as they are entirelly and totally native in propel?

    I'm attempting to port a project i wrote in silex1+propel1 into S3+dogtrine, to practice and well if possible actually really migrating it, and those behaviors are a requirement.

  • 2016-06-01 David Thorne

    Great introduction Ryan! Thanks. Keep up the good work.

  • 2016-04-26 weaverryan

    Hi Andrés!

    Hmm, that usually means that you are trying to persist and entity (e.g. Genus) - but Doctrine does not think it's an entity. For example, if you mistakenly put `Genus` in a directory called `Model` instead of `Entity`, then Doctrine wouldn't know to read its annotation metadata, and it would look like a normal class, not an entity. This would cause this error. It's a very uncommon error, exception in edge-cases when you're working with third-party libraries that give you entities. In those cases, sometimes you have to add configuration so Doctrine is aware of the extra entity classes :).

    I hope that helps!

  • 2016-04-24 Andrés Vr

    Hello Ryan

    when I create an entity I have this error:
    The class 'xxx' was not found in the chain configured namespaces

    Do you have any idea to resolve them??

  • 2016-04-21 Shairyar Baig


    All i had to do was move '$currentProfileImage = $college->getLogo();' at the beginning of the action and it worked :)

    Thanks for your comments and looking into it anyways.


  • 2016-04-21 weaverryan

    Hey Shairyar!

    Hmm, I'm not sure. But! To find out, here's what I would do. Suppose that the persisted property on College for the image is called imagePath. First, I'd see if anything in College modifies the imagePath property other than setImagePath(). If anything else *does* modify imagePath, then temporarily comment that out and edit the College - see if the image is lost. Also, throw a new \Exception() in setImagePath() to see if something is calling it on College edit.

    My guess is that you might be setting $this->imagePath = null; inside setLogo() or something similar, but I'm not sure :).


  • 2016-04-21 Shairyar Baig

    Hi Ryan,

    I am stuck in a situation and hoping that your expertise will push me in right direction.

    It is a really simple task, in admin panel i need to give admin an option to add image and add the description, this is working fine but as soon the admin edit's the description and saves it the image name becomes null in database. so it works the first time and then later on, on edit the image name goes missing.

    This is the action, in this i am using `currentProfileImage ` and saving the existing image in case user does not provide the new one while editing so i dont lose the only that is already there, but this does not work.

    public function editAction(Request $request, College $college)


    $em = $this->getDoctrine()->getManager();
    $editForm = $this->createForm('AppBundle\Form\CollegeType', $college);
    $currentProfileImage = $college->getLogo();

    if ($editForm->isSubmitted() && $editForm->isValid()) {

    if ($editForm->get('logo')->getData() == null) {

    // if an image has not been provided


    } else {

    $profileImageDir = $this->container->getParameter('kernel.root_dir') . '/../web/uploads';

    $file = $college->getLogo();

    // Generate a unique name for the file before saving it
    $fileName = md5(uniqid() . $file) . '.' . $file->guessExtension();

    // Move the file to the directory where profile images are stored
    $file->move($profileImageDir, $fileName);



    //display successful message

    return $this->render('AppBundle:admin/college:edit.html.twig', array(
    'college' => $college,
    'edit_form' => $editForm->createView(),


    return $this->render('AppBundle:admin/college:edit.html.twig', array(
    'college' => $college,
    'edit_form' => $editForm->createView(),


    What am i doing wrong here?

  • 2016-01-27 weaverryan

    Hey there!

    Welcome! Yes, it's not exactly a beginner problem, but maybe I can help:

    1) The only thing that will live in your repository are queries. From flat PHP, think of it this way: any time that you *used* to literally write a query - e.g. $sql = 'SELECT * FROM ...', followed by $conn->execute($sql) or something similar - put that logic as a new method in a repository. That's the only purpose of a repository: to try to prevent query logic from being all around your project. If you're selecting from multiple tables, just put the new method in the repository that you feel most appropriately fits.

    2) Depending on your user flow, your form might be quite complicated for this. If the user is creating an event, then adding a drop-down of all of the themes in the system is simple - just use the EntityType. But, if you need to do some crazy AJAX logic once the user selects the theme (e.g. in order to load a list of products in that theme, or something) - that can get more complicated. My advice on the form system is always this: use it when it works for you. But if you get in a real complex situation, it's ok to revert back and use some normal HTML forms and process the input manually in your controller (a bit more like flat PHP)

    3) If you need to do some validation after a form is submitted to see if the required products are available, then you can do that in your controller (and just render the template with an error message if there is a problem). If you want to get a bit more advanced, you can create a custom validation constraint. I talk about some of the possibilities on this post:

    Overall, don't worry too much. Symfony gives you a lot of tools, but optional tools. If you feel overwhelmed, it's ok to choose to use less of Symfony's tools, while you get going :).

    Good luck!

  • 2016-01-27 Bettinz

    Hello, this is a beginner question :D I've an entity called product, one called event, and one called theme. To make an event, you must select a theme; based on theme, the event will require some products and I need to check if that products are available. I need to write custom queries (like select quantity from product_in_theme and verify if is available in product) but..where I write that code? In repository? If yes, the full code, will be in repository? (For example: check the theme passed with form, select the product from the form, etc). I know it's not the beginner situation, and maybe years writing plain php is giving me the wrong idea, so please, help me :)

  • 2016-01-20 weaverryan

    Hey Sudhir! I'm still aiming for the next few weeks :)

  • 2016-01-20 Sudhir

    hi , when it will released??
    I are awaiting like hungry

  • 2016-01-06 weaverryan

    Hey Igor!

    This is the 2nd episode in the Symfony 3 series after, which we're just finishing now. My hope is to get this episode this month. In the mean time, Doctrine hasn't changed that much, so here are some links that might be useful:

    * (and the chapter after)
    * and most of

    I hope that helps!

  • 2016-01-05 Igor Lula

    Hello there, when this screencast will be released?