TheWebs
TheWebs

Reputation: 12923

Doctrine isn't saving my entities?

I have the following model, or as you call them entity, and I also have a controller, everything works in this action, but when I check the database there is no user. So I am curious as what I am missing. So lets start at the beginning as to what I have:

bootstrap.php contains the following code, among other things.

...
/** ---------------------------------------------------------------- **/
// Lets Setup Doctrine.
/** ---------------------------------------------------------------- **/
require_once 'vendor/autoload.php';

$loader = require 'vendor/autoload.php';
\Doctrine\Common\Annotations\AnnotationRegistry::registerLoader(array($loader, 'loadClass'));

use Doctrine\ORM\Tools\Setup;
use Doctrine\ORM\EntityManager;

/**
 * Set up Doctrine.
 */
class DoctrineSetup {

    /**
     * @var array $paths - where the entities live.
     */
    protected $paths = array(APP_MODELS);

    /**
     * @var bool $isDevMode - Are we considered "in development."
     */
    protected $isDevMode = false;

    /**
     * @var array $dbParams - The database paramters.
     */
    protected $dbParams = null;

    /**
     * Constructor to set some core values.
     */
    public function __construct(){
        if (!file_exists('db_config.ini')) {
            throw new \Exception(
                'Missing db_config.ini. You can create this from the db_config_sample.ini'
            );
        }

        $this->dbParams = array(
            'driver' => 'pdo_mysql',
            'user' => parse_ini_file('db_config.ini')['DB_USER'],
            'password' => parse_ini_file('db_config.ini')['DB_PASSWORD'],
            'dbname' => parse_ini_file('db_config.ini')['DB_NAME']
        );
    }

    /**
     * Get the entity manager for use through out the app.
     *
     * @return EntityManager
     */
    public function getEntityManager() {
        $config = Setup::createAnnotationMetadataConfiguration($this->paths, $this->isDevMode, null, null, false);
        return EntityManager::create($this->dbParams, $config);
    }
}

/**
 * Function that can be called through out the app.
 *
 * @return EntityManager
 */
function getEntityManager() {
    $ds = new DoctrineSetup();
    return $ds->getEntityManager();
}

/**
 * Function that returns the conection to the database.
 */
function getConnection() {
    $ds = new DoctrineSetup();
    return $ds->getEntityManager()->getConnection();
}
...

So now that we have doctrine set up its time to create a model (entity) and set which fields can and cannot be blank and so on and so forth.

Note At this point, you should know that I am not using Symfony other then its components on top of Doctrine. I am using Slim Framework. So if any suggestion is to use x or y from symfony, please make sure its a component.

Models/User.php

<?php

namespace ImageUploader\Models;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * @ORM\Entity
 * @ORM\Table(name="users", uniqueConstraints={
 *   @ORM\UniqueConstraint(name="user", columns={"userName", "email"})}
 * )
 */
class User {

    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue
     */
    protected $id;

    /**
     * @ORM\Column(type="string", length=32, nullable=false)
     * @Assert\NotBlank()
     */
    protected $firstName;

    /**
     * @ORM\Column(type="string", length=32, nullable=false)
     * @Assert\NotBlank()
     */
    protected $lastName;

    /**
     * @ORM\Column(type="string", length=100, unique=true, nullable=false)
     * @Assert\NotBlank(
     *    message = "Username cannot be blank"
     * )
     */
    protected $userName;

    /**
     * @ORM\Column(type="string", length=100, unique=true, nullable=false)
     * @Assert\NotBlank(
     *   message = "Email field cannot be blank."
     * )
     * @Assert\Email(
     *    message = "The email you entered is invalid.",
     *    checkMX = true
     * )
     */
    protected $email;

    /**
     * @ORM\Column(type="string", length=500, nullable=false)
     * @Assert\NotBlank(
     *  message = "The password field cannot be empty."
     * )
     */
    protected $password;

    /**
     * @ORM\Column(type="datetime", nullable=true)
     */
    protected $created_at;

    /**
     * @ORM\Column(type="datetime", nullable=true)
     */
    protected $updated_at;

    /**
     * Get the value of Created At
     *
     * @return mixed
     */
    public function getCreatedAt()
    {
        return $this->created_at;
    }

    /**
     * Set the value of Created At
     *
     * @param mixed created_at
     *
     * @return self
     */
    public function setCreatedAt(\DateTime $created_at = null)
    {
        $this->created_at = $created_at;

        return $this;
    }

    /**
     * Get the value of Updated At
     *
     * @return mixed
     */
    public function getUpdatedAt()
    {
        return $this->updated_at;
    }

    /**
     * Set the value of Updated At
     *
     * @param mixed updated_at
     *
     * @return self
     */
    public function setUpdatedAt(\DateTime $updated_at = null)
    {
        $this->updated_at = $updated_at;

        return $this;
    }

    /**
     * Get the value of First Name
     *
     * @return mixed
     */
    public function getFirstName()
    {
        return $this->firstName;
    }

    /**
     * Set the value of First Name
     *
     * @param mixed firstName
     *
     * @return self
     */
    public function setFirstName($firstName)
    {
        $this->firstName = $firstName;

        return $this;
    }

    /**
     * Get the value of Last Name
     *
     * @return mixed
     */
    public function getLastName()
    {
        return $this->lastName;
    }

    /**
     * Set the value of Last Name
     *
     * @param mixed lastName
     *
     * @return self
     */
    public function setLastName($lastName)
    {
        $this->lastName = $lastName;

        return $this;
    }

    /**
     * Get the value of User Name
     *
     * @return mixed
     */
    public function getUserName()
    {
        return $this->userName;
    }

    /**
     * Set the value of User Name
     *
     * @param mixed userName
     *
     * @return self
     */
    public function setUserName($userName)
    {
        $this->userName = $userName;

        return $this;
    }

    /**
     * Get the value of Email
     *
     * @return mixed
     */
    public function getEmail()
    {
        return $this->email;
    }

    /**
     * Set the value of Email
     *
     * @param mixed email
     *
     * @return self
     */
    public function setEmail($email)
    {
        $this->email = $email;

        return $this;
    }

    /**
     * Set ths password.
     *
     * @param string password
     *
     * @return self
     */
    public function setPassword($password) {
        $this->password = password_hash($password, PASSWORD_DEFAULT);
        return $this;
    }

    /**
     * Check the users password against that which is enterd.
     *
     * @param string password
     *
     * @return bool
     */
    public function checkPassword($password) {
        if (password_hash($password, PASSWORD_DEFAULT) === $this->getPassword()) {
            return true;
        }

        return false;
    }

    /**
     * Return the password value.
     *
     * @return hash
     */
    private function getPassword(){
        return $this->password;
    }

    /**
     * @ORM\PrePersist
     */
    public function setCreatedAtTimeStamp() {
        if (is_null($this->getCreatedAt())) {
            $this->setCreatedAt(new \DateTime());
        }
    }

    /**
     * @ORM\PreUpdate
     */
    public function setUpdatedAtTimeStamp() {
        if (is_null($this->getUpdatedAt())) {
            $this->setUpdatedAt(new \DateTime());
        }
    }
}

The above model is correct, as far as I know, I mean when I run "vendor/bin/doctrine migrations:migrate" a database table is created.

Now, where is all this used? it's used in a controller called SignupController under an action called createAction($params)

**createAction($params)**

public static function createAction($params){
  $postParams = $params->request()->post();
  $flash = new Flash();

  if ($postParams['password'] !== $postParams['repassword']) {
    $flash->createFlash('error', 'Your passwords do not match.');
    self::$createEncryptedPostParams($postParams);
    $params->redirect('/signup/error');
  }

  $user = new User();

  $user->setFirstName($postParams['firstname'])
       ->setLastName($postParams['lastname'])
       ->setUserName($postParams['username'])
       ->setEmail($postParams['email'])
       ->setPassword($postParams['password'])
       ->setCreatedAtTimeStamp();

  $validator = Validator::createValidatorBuilder();
  $validator->enableAnnotationMapping();

  $errors = $validator->getValidator()->validate($user);

  if (count($errors) > 0) {
      foreach($errors as $error) {
        $flash->createFlash(
            $error->getPropertyPath() . 'error',
            $error->getMessage()
        );
    }

    self::createEncryptedPostParams($postParams);
    $params->redirect('/signup/error');
  }

  $anyEncryptedErors = self::getEncryptedPostParams();
  if ($anyEncryptedErors !== null) {
    $anyEncryptedErors->destroy('error');
  }

  getEntityManager()->flush();
  getEntityManager()->persist($user);

  $flash->createFlash('success', ' You have signed up successfully! Please sign in!');
  $params->redirect('/signin');
}

Now should you enter everything in correctly I show a flash of success and redirect you. THIS WORKS it redirects, it shows a flash message. But its the:

  getEntityManager()->flush();
  getEntityManager()->persist($user);

That I don't think is working. Why? Because doing a select * from users on the database in question comes back with no records.

Why?

Upvotes: 1

Views: 5875

Answers (4)

Dan
Dan

Reputation: 118

As Samiul Amin Shanto said:

getEntityManager()->persist($user);
getEntityManager()->flush();

will be correct way, because persist action prepare the data to be stored in DB and flush "Flushes all changes to now to the database."

Upvotes: 0

eeskonivich
eeskonivich

Reputation: 131

I had a similar issue and thought I would post it here. I was creating an entity and everything was responding correctly, but when I checked the database no record had been created.

Just wrapped the flush in a try-catch and logged the error.

$this->em->persist($insectLifeCycle);
try {
    $this->em->flush();
} catch (\Exception $error) {
    $this->logger->debug($error);    
}

It turns out that one of properties was exceeding its character limit and the database was throwing an error. Also found out I need to improve my error handling....

Upvotes: 0

Simon Berton
Simon Berton

Reputation: 528

If you have the object id and then, the database is not showing it, you might have a "START TRANSACTION" and then you have your insert, after this insert you will have a "COMMIT". If any error appears between your persist and the COMMIT, object won't be stored in your database. Check your Symfony request profiler information. You can find it using the developer tool and checking your response for it.

Upvotes: -1

Samiul Amin Shanto
Samiul Amin Shanto

Reputation: 1397

Flush statement should be execute after persist. So Code should be:

getEntityManager()->persist($user);
getEntityManager()->flush();

Upvotes: 5

Related Questions