Doctrine persist: - mysql

I'm a beginner at Symfony. My problem is that I try to add values to my base MySQL and the problem is that I have the same id, but i verified my entity and i generate values #ORM/GeneratedValues, i don't understand where is my fault.
Routing :
esprit_parc_AjoutVoiture:
path: /Ajout_voiture/
defaults: { _controller: ParcBundle:Voiture:add }
My controller:
public function addAction (Request $Request)
{
$Voiture = new Voiture();
$form = $this->createForm(VoitureType::class,$Voiture);
$form->handleRequest($Request);
if ($form->isValid())
{
$em=$this->getDoctrine()->getManager();
$em->persist($Voiture);
$em->flush();
return $this->redirect($this->generateUrl(
'esprit_parc_Affichage'
));
}
return $this->render(
'ParcBundle:Voiture:ajout.html.twig',
array('form'=>$form->createView()
));
}
}
Entity Voiture:
<?php
namespace ParcBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Class voiture
* #package ParcBundle\Entity
* #ORM\Entity
* #ORM\Table(name="Voiture")
*/
class Voiture
{
/**
* #ORM\Column( type="integer")
* #ORM\Id
* #ORM\GeneratedValue
*/
private $id;
/**
* #ORM\Column(type="string",length=255)
*
*/
private $Serie;
/**
* #ORM\Column(type="datetime",length=255)
*/
private $DateMiseCirculation;
/**
* #ORM\Column(type="string",length=255)
*/
private $Marque;
/**
* #ORM\ManyToOne(targetEntity="ParcBundle\Entity\Modele" )
* #ORM\JoinColumn(name="id", referencedColumnName="id");
*/
private $modele;
public function getId()
{
return $this->id;
}
public function setId($id)
{
$this->id = $id;
}
public function getModele()
{
return $this->modele;
}
public function setModele($modele)
{
$this->modele = $modele;
}
public function getSerie()
{
return $this->Serie;
}
public function setSerie($Serie)
{
$this->Serie = $Serie;
}
public function getDateMiseCirculation()
{
return $this->DateMiseCirculation;
}
public function setDateMiseCirculation($DateMiseCirculation)
{
$this->DateMiseCirculation = $DateMiseCirculation;
}
public function getMarque()
{
return $this->Marque;
}
public function setMarque($Marque)
{
$this->Marque = $Marque;
}
}
Error:
An exception occurred while executing 'INSERT INTO Voiture (serie, date_mise_circulation, marque, id) VALUES (?, ?, ?, ?)' with params ["2313", "2012-12-03 02:02:00", "sd", 1]:
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '1' for key 'PRIMARY'
PS : i have values with id = "1" and it should increment automatically the id.
[EDIT]: Class VoitureType:
<?php
namespace ParcBundle\Form;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class VoitureType extends AbstractType
{
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('Serie')
->add('DateMiseCirculation')
->add('Marque')
->add('modele', EntityType::class, array(
"class" => "ParcBundle:Modele",
"choice_label"=> "libelle"
))
->add("Ajouter",SubmitType::class);
}
/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'ParcBundle\Entity\Voiture'
));
}
/**
* {#inheritdoc}
*/
public function getBlockPrefix()
{
return 'parcbundle_voiture';
}
}

You have an old schema in your database and MySQL does not know that attribute id is auto increment value. To update your schema you can use one of methods:
Internal tool from Doctrine: php bin/console doctrine:schema:update --force.
Use DoctrineMigrationsBundle.
Remember that sometimes schema do not want to update because of foreign keys. Solution for this is just remove existing data.

Related

How to bypass error "Invalid type "json_array""

I have an entity:
<?php
namespace App\Entity\Aero;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass="App\Repository\Aero\ScheduleRepository")
*/
class Schedule
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="date")
*/
private $dateOfFlight;
/**
* #ORM\Column(type="json")
*/
private $timeOfFlightAndStations = [];
public function getId(): ?int
{
return $this->id;
}
public function getDateOfFlight(): ?\DateTimeInterface
{
return $this->dateOfFlight;
}
public function setDateOfFlight(\DateTimeInterface $dateOfFlight): self
{
$this->dateOfFlight = $dateOfFlight;
return $this;
}
public function getTimeOfFlightAndStations(): ?array
{
return $this->timeOfFlightAndStations;
}
public function setTimeOfFlightAndStations(array $timeOfFlightAndStations): self
{
$this->timeOfFlightAndStations = $timeOfFlightAndStations;
return $this;
}
}
When I try to add field with type json_array via con make:entity it shows me error:
[ERROR] Invalid type "json_array".
My computer says that type "json_array" is invalid, but also says that it is in the list of valid types. How is it possible?
Please, help me, how to deal with this error?
Solved it by adding "json_array" manually instead of "json" in:
/**
* #ORM\Column(type="json_array")
*/

How should looks like a json form with other forms embeded

I'm using postman to test my json-api. I have to related entities:
Publication:
<?php
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Entity(repositoryClass="App\Repository\PublicationRepository")
*/
class Publication
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #Assert\NotBlank
* #ORM\Column(type="string", length=100)
*/
private $title;
/**
* #Assert\NotBlank
* #ORM\Column(type="string", length=500)
*/
private $body;
/**
* #ORM\OneToMany(targetEntity="App\Entity\Comment", mappedBy="publication", orphanRemoval=true)
*/
private $comments;
public function __construct()
{
$this->comments = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getTitle(): ?string
{
return $this->title;
}
public function setTitle(string $title): self
{
$this->title = $title;
return $this;
}
public function getBody(): ?string
{
return $this->body;
}
public function setBody(string $body): self
{
$this->body = $body;
return $this;
}
/**
* #return Collection|Comment[]
*/
public function getComments(): Collection
{
return $this->comments;
}
public function addComment(Comment $comment): self
{
if (!$this->comments->contains($comment)) {
$this->comments[] = $comment;
$comment->setPublication($this);
}
return $this;
}
public function removeComment(Comment $comment): self
{
if ($this->comments->contains($comment)) {
$this->comments->removeElement($comment);
// set the owning side to null (unless already changed)
if ($comment->getPublication() === $this) {
$comment->setPublication(null);
}
}
return $this;
}
}
Comment:
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Entity(repositoryClass="App\Repository\CommentRepository")
*
*/
class Comment
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #Assert\NotBlank
* #ORM\Column(type="string", length=255)
*/
private $body;
/**
* #Assert\Positive
* #ORM\Column(type="integer")
*/
private $likeCount;
/**
* #return mixed
*/
public function getLikeCount()
{
return $this->likeCount;
}
/**
* #param mixed $likeCount
*/
public function setLikeCount($likeCount): void
{
$this->likeCount = $likeCount;
}
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Publication", inversedBy="comments")
* #ORM\JoinColumn(nullable=false)
*/
private $publication;
public function getId(): ?int
{
return $this->id;
}
public function getBody(): ?string
{
return $this->body;
}
public function setBody(string $body): self
{
$this->body = $body;
return $this;
}
public function getPublication(): ?Publication
{
return $this->publication;
}
public function setPublication(?Publication $publication): self
{
$this->publication = $publication;
return $this;
}
}
And the Form classes:
PublicationType:
<?php
namespace App\Form;
use App\Entity\Publication;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class PublicationType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('title')
->add('body')
->add('comments', CollectionType::class, [
'entry_type' => CommentType::class,
'entry_options' => ['label' => false],
]);
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Publication::class,
'csrf_protection'=> false
]);
}
}
CommentType:
<?php
namespace App\Form;
use App\Entity\Comment;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class CommentType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('body')
->add('publication')
->add('likeCount');
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Comment::class,
'csrf_protection'=> false
]);
}
}
According with this: https://symfony.com/doc/current/form/form_collections.html the Publication form is able to receive a Comment form embeded:
I tried something like this in a postman POST request:
{
"title":"post with comments",
"body":"some text",
"comments":[
{"body":"comment1","likeCount":"5"},
{"body":"comment2","likeCount":"8"}
]
}
But I get this:
{ "code": 400, "message": "Validation Failed", "errors": { "errors": [ "This form should not contain extra fields." ], "children": { "title": {}, "body": {}, "comments": {} } } }
The question is:
How should looks like the json request?
Edit:
I don't think that the trouble is in the root keys, cause before setting the ManyToOne relation I used to submit the form like this:
{
"title":"post with comments",
"body":"some text"
}
extra info:
This is the controller code:
$form = $this->formFactory->create(PublicationType::class, new Publication());
$form->submit($request->request->all());
if (false === $form->isValid()) {
return $this->viewhandler->createResponse($this->view($form),$request,'json');
}
$this->entityManager->persist($form->getData());
$this->entityManager->flush();
return new JsonResponse(
[
'status' => 'ok',
]
);
Contrary to my first assumption, the error message, actually does provide the fields that were expected:
{
"code": 400,
"message": "Validation Failed",
"errors": {
"errors": [
"This form should not contain extra fields."
],
"children": {
"title": {},
"body": {},
"comments": {}
}
}
}
However, that message is not particularly helpful, when exactly those fields are provided and the problem lies in the collection (sub form / sub fields).
The CollectionType for the comments however doesn't allow adding or removing children (comments) unless configured to do so. Adding the allow_add (and optionally allow_delete) fixes the problem.

How to create nested objects with FOSRestBundle and FormType?

I'm developing an API with symfony2 + FOSRestBundle and I have two errors.
Below is my code:
Property
/**
* Property
*
* #ORM\Table(name="property")
* #ORM\Entity
* #ORM\InheritanceType("JOINED")
* #ORM\DiscriminatorColumn(name="discr", type="string")
* #ORM\DiscriminatorMap({"house" = "House"})
*/
abstract class Property {
/**
* #ORM\OneToMany(targetEntity="Image", mappedBy="property", cascade={"persist"})
* */
private $images;
function getImages() {
return $this->images;
}
function setImages($images) {
$this->images = $images;
}
}
House
class House extends Property
{
/* More code */
}
Image
class Image {
/**
* #ORM\Column(name="content", type="text", nullable=false)
*/
private $content;
/**
* #ORM\ManyToOne(targetEntity="Property", inversedBy="images")
* #ORM\JoinColumn(name="propertyId", referencedColumnName="id")
* */
private $property;
}
PropertyType
class PropertyType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->add('images');
$builder->get('images')
->addModelTransformer(new CallbackTransformer(
function($images) {
$image = new \Cboujon\PropertyBundle\Entity\Image();
$image->setContent('test of content');
return array($image);
}, function($imagesContents) {
}));
}
HouseRESTController
/**
* #View(statusCode=201, serializerEnableMaxDepthChecks=true)
*
* #param Request $request
*
* #return Response
*
*/
public function postAction(Request $request)
{
$entity = new House();
$form = $this->createForm(new HouseType(), $entity, array("method" => $request->getMethod()));
$this->removeExtraFields($request, $form);
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($entity);
$em->flush();
return $entity;
}
When I create a new house, I send this (simplified) JSON:
{"images":["base64ContentImage_1", "base64ContentImage_2"]}
First Problem: The $images parameter in the first function passed to the CallbackTransformer is NULL. Why?
Second problem: I order to test and understand the first problem, I forced to create an image entity as you can see but I get a JSON response with the error "Entities passed to the choice field must be managed. Maybe persist them in the entity manager?"
Can anyone help me to solve any of two problem?
I have found one solution
I have been created ImageType
public function buildForm(FormBuilderInterface $builder, array $options)
{
parent::buildForm($builder, $options);
$builder
->add('content')
;
}
And also I have been modified PropertyType
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('title')
->add('description')
->add('price')
->add('services')
->add('images', 'collection', array(
'type' => new ImageType(),
'allow_add' => true,
))
;
}
And finally, I was changed the JSON structure of my request:
{"images":[{content: "base64ContentImage_1"}, {content:"base64ContentImage_2"}]}

Yii2 - Unable to find 'app\models\User' in file: backend/models/User.php. Namespace missing? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I used both namespace in this file backend/models/User.php
When I use namespace app\models; It shows Unable to find 'backend\models\User'.
If I use namespace backend\models; It shows Unable to find 'app\models\User'
<?php
//namespace app\models;
namespace backend\models;
use Yii;
use yii\base\NotSupportedException;
use yii\behaviors\TimestampBehavior;
use yii\db\ActiveRecord;
use yii\web\IdentityInterface;
class User extends ActiveRecord implements IdentityInterface
{
const STATUS_DELETED = 0;
const STATUS_ACTIVE = 10;
const ROLE_USER = 10;
/**
* #inheritdoc
*/
public static function tableName()
{
return 'admin';
}
/**
* #inheritdoc
*/
public function behaviors()
{
return [
TimestampBehavior::className(),
];
}
/**
* #inheritdoc
*/
public function rules()
{
return [
['status', 'default', 'value' => self::STATUS_ACTIVE],
['status', 'in', 'range' => [self::STATUS_ACTIVE, self::STATUS_DELETED]],
['role', 'default', 'value' => self::ROLE_USER],
['role', 'in', 'range' => [self::ROLE_USER]],
];
}
/**
* #inheritdoc
*/
public static function findIdentity($id)
{
return static::findOne(['id' => $id, 'status' => self::STATUS_ACTIVE]);
}
/**
* #inheritdoc
*/
public static function findIdentityByAccessToken($token, $type = null)
{
throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');
}
/**
* Finds user by username
*
* #param string $username
* #return static|null
*/
public static function findByUsername($username)
{
return static::findOne(['username' => $username, 'status' => self::STATUS_ACTIVE]);
}
/**
* Finds user by password reset token
*
* #param string $token password reset token
* #return static|null
*/
public static function findByPasswordResetToken($token)
{
if (!static::isPasswordResetTokenValid($token)) {
return null;
}
return static::findOne([
'password_reset_token' => $token,
'status' => self::STATUS_ACTIVE,
]);
}
/**
* Finds out if password reset token is valid
*
* #param string $token password reset token
* #return boolean
*/
public static function isPasswordResetTokenValid($token)
{
if (empty($token)) {
return false;
}
$expire = Yii::$app->params['user.passwordResetTokenExpire'];
$parts = explode('_', $token);
$timestamp = (int) end($parts);
return $timestamp + $expire >= time();
}
/**
* #inheritdoc
*/
public function getId()
{
return $this->getPrimaryKey();
}
/**
* #inheritdoc
*/
public function getAuthKey()
{
return $this->auth_key;
}
/**
* #inheritdoc
*/
public function validateAuthKey($authKey)
{
return $this->getAuthKey() === $authKey;
}
/**
* Validates password
*
* #param string $password password to validate
* #return boolean if password provided is valid for current user
*/
public function validatePassword($password)
{
return Yii::$app->security->validatePassword($password, $this->password_hash);
}
/**
* Generates password hash from password and sets it to the model
*
* #param string $password
*/
public function setPassword($password)
{
$this->password_hash = Yii::$app->security->generatePasswordHash($password);
}
/**
* Generates "remember me" authentication key
*/
public function generateAuthKey()
{
$this->auth_key = Yii::$app->security->generateRandomString();
}
/**
* Generates new password reset token
*/
public function generatePasswordResetToken()
{
$this->password_reset_token = Yii::$app->security->generateRandomString() . '_' . time();
}
/**
* Removes password reset token
*/
public function removePasswordResetToken()
{
$this->password_reset_token = null;
}
}
I think your problem is, that you have two different models and try to use them both in one namespace, but this won't work.
You can alias one namespace, so you can use both different models.
eg.:
<?php
namespace app\models;
// there exist a model "User"
// and you wanna use also the User model under common\models\
use common\models\User as CUser;
Another solution is to prefixing the namespace to the model like
<?php
namespace app\models;
$cuser = new \common\models\User();
see PHP Namespaces explained

Doctrine, Zend, Entity QueryException has no field or association named

I'm having an OrderEntity. First time i just needed three properties from the table. But now I need two more.
So I'm adding this two properties to my entity:
namespace Stock\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="orders")
*/
class OrderEntity
{
/**
* #ORM\Id
* #ORM\Column(type="integer", name="orders_id")
*/
private $ordersId;
/**
* #ORM\Column(type="string", name="order_number")
*/
private $orderNumber;
/**
* #ORM\Column(type="integer", name="stores_id")
*/
private $storesId;
/**
* #ORM\Column(type="string", length=3, name="currency")
*/
private $currency;
/**
* #ORM\Column(type="decimal", precision=6, scale=14, name="currency_value")
*/
private $currencyValue;
public function getOrdersId()
{
return $this->ordersId;
}
public function setOrdersId($ordersId)
{
$this->ordersId = $ordersId;
}
public function getOrderNumber()
{
return $this->orderNumber;
}
public function setOrderNumber($orderNumber)
{
$this->orderNumber = $orderNumber;
}
public function getStoresId()
{
return $this->storesId;
}
public function setStoresId($storesId)
{
$this->storesId = $storesId;
}
public function getCurrency()
{
return $this->currency;
}
public function getCurrencyValue()
{
return $this->currencyValue;
}
public function setCurrency($currency)
{
$this->currency = $currency;
return $this;
}
public function setCurrencyValue($currencyValue)
{
$this->currencyValue = $currencyValue;
return $this;
}
The new properties are the currency and currencyValue.
$query = $this->getEm()->createQuery(
"SELECT o.ordersId, o.currency FROM "
. "Stock\Entity\OrderEntity o WHERE "
. "o.ordersId ='".$orderId."'"
);
If I want to create a query with using the newer properties I got a QueryException:
[Semantical Error] line 0, col 21 near 'currency FROM': Error: Class Stock\Entity\OrderEntity has no field or association named currency
I don't exactly understand where the problem is!