I'm working on a RESTFull API with Symfony and FOSRESTBundle. I use the JMS Serializer with groups to show differents fields depending on the context.
For listing my resources, I want implement PagerFantaBundle. All work fine except that PagerFanta does not consider the serialization groups.
Below my code :
Pagination function :
protected function paginate(QueryBuilder $qb, $limit = 20, $offset = 0) {
if($limit == 0 || $offset < 0) {
throw new \LogicException("$limit & $offset must be greater than 0");
}
$pager = new Pagerfanta(new DoctrineORMAdapter($qb));
$currentPage = ceil($offset + 1 / $limit);
$pager->setCurrentPage($currentPage);
$pager->setMaxPerPage((int) $limit);
return $pager;
}
List apartment function :
public function listApartments(Location $location, $order = 'asc', $limit = 20, $offset = 0) {
$qb = $this->createQueryBuilder('a')
->select('a')
->orderBy('a.title', $order);
return $this->paginate($qb, $limit, $offset);
}
Controller :
/**
* #Rest\Get(
* path = "/apartments",
* name = "apartments_get_all"
* )
* #Rest\QueryParam(
* name="order",
* requirements="asc|desc",
* nullable=true,
* description="Sort order (asc or desc)"
* )
* #Rest\QueryParam(
* name="limit",
* requirements="\d+",
* default="20",
* description="Max number of apartments per page"
* )
* #Rest\QueryParam(
* name="offset",
* requirements="\d+",
* default="0",
* description="Pagination offset"
* )
* #Rest\View(statusCode=200, serializerGroups={"listApartment"})
*/
public function getApartmentsAction(ParamFetcherInterface $paramFetcher)
{
$pager = $this->getDoctrine()->getRepository("HGBCoreBundle:Apartment")->listApartments(
new Location(),
$paramFetcher->get('order'),
$paramFetcher->get('limit'),
$paramFetcher->get('offset')
);
return new Apartments($pager);
}
Apartments representation :
class Apartments
{
/**
* #Type("array<HGB\CoreBundle\Entity\Apartment>")
*/
public $data;
public $meta;
public function __construct(Pagerfanta $data)
{
$this->data = $data->getCurrentPageResults();
$this->addMeta('limit', $data->getMaxPerPage());
$this->addMeta('current_items', count($data->getCurrentPageResults()));
$this->addMeta('total_items', $data->getNbResults());
$this->addMeta('offset', $data->getCurrentPageOffsetStart());
}
public function addMeta($name, $value)
{
if (isset($this->meta[$name])) {
throw new \LogicException(sprintf('This meta already exists. You are trying to override this meta, use the setMeta method instead for the %s meta.', $name));
}
$this->setMeta($name, $value);
}
public function setMeta($name, $value)
{
$this->meta[$name] = $value;
}
}
Apartment Entity :
/**
* Apartment
*
* #ORM\Table(name="apartment")
* #ORM\Entity(repositoryClass="HGB\CoreBundle\Repository\ApartmentRepository")
* #JMS\ExclusionPolicy("all")
*/
class Apartment
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #JMS\Groups({"listApartment"})
* #JMS\Expose()
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="title", type="string", length=200)
* #JMS\Groups({"listApartment"})
* #JMS\Expose()
* #Assert\NotBlank()
*/
private $title;
...
So, how can I use group serialization with PagerFanta, or what pagination system could I use with groups serialization ?
Thanks
I've found the solution. Just need to configure the serialization groups for the Apartments representation like this :
<?php
namespace HGB\CoreBundle\Representation;
use JMS\Serializer\Annotation as Serializer;
use Pagerfanta\Pagerfanta;
/**
* Class Apartments
* #package HGB\CoreBundle\Representation
* #Serializer\ExclusionPolicy("all")
*/
class Apartments
{
/**
* #Serializer\Type("array<HGB\CoreBundle\Entity\Apartment>")
* #Serializer\Groups("listApartment")
* #Serializer\Expose()
*/
public $data;
/**
* #Serializer\Groups("listApartment")
* #Serializer\Expose()
*/
public $meta;
public function __construct(Pagerfanta $data)
{
$this->data = $data;
$this->addMeta('limit', $data->getMaxPerPage());
$this->addMeta('current_items', count($data->getCurrentPageResults()));
$this->addMeta('total_items', $data->getNbResults());
$this->addMeta('offset', $data->getCurrentPageOffsetStart());
}
public function addMeta($name, $value)
{
if (isset($this->meta[$name])) {
throw new \LogicException(sprintf('This meta already exists. You are trying to override this meta, use the setMeta method instead for the %s meta.', $name));
}
$this->setMeta($name, $value);
}
public function setMeta($name, $value)
{
$this->meta[$name] = $value;
}
}
Related
i have added a new field/column to my "listing" entity, which is a boolean named "promoted" which is like one already present in the db "certified", it is created to behave exactly the same, however, it is'nt working..
The mariadb db updated correctly with the new row containing a boolean, but when i try to use it in a partial query or to update the field from 0 to 1 with a form it dont update, like it's unmapped, here's my code (not all just the important parts are it is 3 functions with 1000~+ lines: BaseListing.php
/**
* Listing
*
* #CocoricoAssert\ListingConstraint()
*
* #ORM\MappedSuperclass
*/
abstract class BaseListing
{
protected $price = 0;
/**
*
* #ORM\Column(name="certified", type="boolean", nullable=true)
*
* #var boolean
*/
protected $certified;
/**
*
* #ORM\Column(name="min_duration", type="smallint", nullable=true)
*
* #var integer
*/
/**
*
* #ORM\Column(name="promoted", type="boolean", nullable=true)
*
* #var boolean
*/
protected $promoted;
/**
* #return boolean
*/
public function isCertified()
{
return $this->certified;
}
/**
* #param boolean $certified
*/
public function setCertified($certified)
{
$this->certified = $certified;
}
/**
* #return boolean
*/
public function isPromoted()
{
return $this->promoted;
}
/**
* #param boolean $promoted
*/
public function setPromoted($promoted)
{
$this->promoted = $promoted;
}
}
here's AdminListing.php to generate the form for the admin panel to pass certified on / off and as i wish promoted on / off (cuted because it's a too large file):
class ListingAdmin extends AbstractAdmin
{
/** #inheritdoc */
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->with('admin.listing.title')
->add(
'status',
ChoiceType::class,
array(
'choices' => array_flip(Listing::$statusValues),
'placeholder' => 'admin.listing.status.label',
'translation_domain' => 'cocorico_listing',
'label' => 'admin.listing.status.label',
)
)
->add(
'adminNotation',
ChoiceType::class,
array(
'choices' => array_combine(
range(0, 10, 0.5),
array_map(
function ($num) {
return number_format($num, 1);
},
range(0, 10, 0.5)
)
),
'placeholder' => 'admin.listing.admin_notation.label',
'label' => 'admin.listing.admin_notation.label',
'required' => false,
)
)
->add(
'certified',
null,
array(
'label' => 'admin.listing.certified.label',
)
)
->add(
'promoted',
CheckboxType::class,
array(
'label' => 'admin.listing.promoted.label',
'required' => false,
)
)
This is not working because i have a query in ListingRepository that use "certified":
public function getFindSelectPart(QueryBuilder $queryBuilder)
{
$queryBuilder
->select("partial l.{id, price, averageRating, certified, createdAt, commentCount}")
->addSelect("partial t.{id, locale, slug, title, description}")
->addSelect("partial llcat.{id, listing, category}")
->addSelect("partial ca.{id, lft, lvl, rgt, root}")
->addSelect("partial cat.{id, locale, name}")
->addSelect("partial i.{id, name}")
->addSelect("partial u.{id, firstName}")
->addSelect("partial ln.{id, city, route, country}")
->addSelect("partial co.{id, lat, lng}")
->addSelect("partial ui.{id, name}")
->addSelect("'' AS DUMMY");//To maintain fields on same array level when extra fields are added
return $queryBuilder;
}
And when i put promoted just behind the certified in the partial query it says:
[Semantical Error] line 0, col 88 near partial.l Error: There is no mapped field named 'promoted' on class Cocorico\ListingBundle\Entity\Listing
besides i have done exactly the same setup as the certified value, i have cleared cache and updated DB scheme.
Here's my Entity\Listing.php :
?php
namespace Cocorico\ListingBundle\Entity;
use Cocorico\BookingBundle\Entity\Booking;
use Cocorico\ListingBundle\Model\BaseListing;
use Cocorico\ListingBundle\Model\ListingOptionInterface;
use Cocorico\ListingCategoryBundle\Entity\ListingListingCategory;
use Cocorico\ListingCharacteristicBundle\Entity\ListingListingCharacteristic;
use Cocorico\ListingDiscountBundle\Entity\ListingDiscount;
use Cocorico\ListingImageBundle\Entity\ListingImage;
use Cocorico\ListingLocationBundle\Entity\ListingLocation;
use Cocorico\MessageBundle\Entity\Thread;
use Cocorico\UserBundle\Entity\User;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Knp\DoctrineBehaviors\Model as ORMBehaviors;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Listing
*
* #ORM\Entity(repositoryClass="Cocorico\ListingBundle\Repository\ListingRepository")
*
* #ORM\Table(name="listing",indexes={
* #ORM\Index(name="created_at_l_idx", columns={"created_at"}),
* #ORM\Index(name="status_l_idx", columns={"status"}),
* #ORM\Index(name="price_idx", columns={"price"}),
* #ORM\Index(name="type_idx", columns={"type"}),
* #ORM\Index(name="min_duration_idx", columns={"min_duration"}),
* #ORM\Index(name="max_duration_idx", columns={"max_duration"}),
* #ORM\Index(name="average_rating_idx", columns={"average_rating"}),
* #ORM\Index(name="admin_notation_idx", columns={"admin_notation"}),
* #ORM\Index(name="platform_notation_idx", columns={"platform_notation"})
* })
*/
class Listing extends BaseListing
{
use ORMBehaviors\Timestampable\Timestampable;
use ORMBehaviors\Translatable\Translatable;
use \Cocorico\ListingSearchAdvancedBundle\Model\ListingSearchableTrait;
// use \Cocorico\ListingCategoryFieldBundle\Model\ListingCategoryFieldableTrait;
// use \Cocorico\DeliveryBundle\Model\ListingDeliverableTrait;
// use \Cocorico\ListingDepositBundle\Model\ListingDepositableTrait;
// use \Cocorico\ListingSessionBundle\Model\ListingSessionableTrait;
// use \Cocorico\ServiceBundle\Model\ListingTrait;
// use \Cocorico\ListingVideoBundle\Model\ListingVideoTrait;
// use \Cocorico\CarrierBundle\Model\ListingCarrierableTrait;
/**
* #ORM\Id
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\GeneratedValue(strategy="CUSTOM")
* #ORM\CustomIdGenerator(class="Cocorico\CoreBundle\Model\CustomIdGenerator")
*
* #var integer
*/
protected $id;
/**
* #Assert\NotBlank(message="assert.not_blank")
*
* #ORM\ManyToOne(targetEntity="Cocorico\UserBundle\Entity\User", inversedBy="listings", cascade={"persist"})
* #ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=false, onDelete="CASCADE")
*
* #var User
*/
protected $user;
/**
* #ORM\OneToOne(targetEntity="Cocorico\ListingLocationBundle\Entity\ListingLocation", inversedBy="listing", cas\
cade={"persist", "remove"}, orphanRemoval=true)
* #ORM\JoinColumn(name="location_id", referencedColumnName="id", onDelete="CASCADE")
*
* #var ListingLocation
**/
protected $location;
/**
* #ORM\OneToMany(targetEntity="Cocorico\ListingCategoryBundle\Entity\ListingListingCategory", mappedBy="listing\
", cascade={"persist", "remove"}, orphanRemoval=true)//, fetch="EAGER"
*
*/
protected $listingListingCategories;
/**
* For Asserts #see \Cocorico\ListingBundle\Validator\Constraints\ListingValidator
*
* #ORM\OneToMany(targetEntity="Cocorico\ListingImageBundle\Entity\ListingImage", mappedBy="listing", cascade={"\
persist", "remove"}, orphanRemoval=true)
* #ORM\OrderBy({"position" = "asc"})
*/
protected $images;
/**
* #ORM\OneToMany(targetEntity="Cocorico\ListingCharacteristicBundle\Entity\ListingListingCharacteristic", mappe\
dBy="listing", cascade={"persist", "remove"}, orphanRemoval=true) //, fetch="EAGER"
*
*/
protected $listingListingCharacteristics;
/**
*
* #ORM\OneToMany(targetEntity="Cocorico\ListingDiscountBundle\Entity\ListingDiscount", mappedBy="listing", casc\
ade={"persist", "remove"}, orphanRemoval=true)
* #ORM\OrderBy({"fromQuantity" = "asc"})
*/
protected $discounts;
/**
* #ORM\OneToMany(targetEntity="Cocorico\BookingBundle\Entity\Booking", mappedBy="listing", cascade={"persist", \
"remove"}, orphanRemoval=true)
* #ORM\OrderBy({"createdAt" = "desc"})
*/
protected $bookings;
/**
* #ORM\OneToMany(targetEntity="Cocorico\MessageBundle\Entity\Thread", mappedBy="listing", cascade={"remove"}, o\
rphanRemoval=true)
* #ORM\OrderBy({"createdAt" = "desc"})
*/
protected $threads;
/**
*
* #ORM\OneToMany(targetEntity="Cocorico\ListingBundle\Model\ListingOptionInterface", mappedBy="listing", cascad\
e={"persist", "remove"}, orphanRemoval=true)
*/
protected $options;
public function __construct()
{
$this->images = new ArrayCollection();
$this->listingListingCharacteristics = new ArrayCollection();
$this->listingListingCategories = new ArrayCollection();
$this->discounts = new ArrayCollection();
$this->bookings = new ArrayCollection();
$this->threads = new ArrayCollection();
$this->options = new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Add characteristics
*
* #param ListingListingCharacteristic $listingListingCharacteristic
* #return Listing
*/
public function addListingListingCharacteristic(ListingListingCharacteristic $listingListingCharacteristic)
{
$this->listingListingCharacteristics[] = $listingListingCharacteristic;
return $this;
}
/**
* Remove characteristics
*
* #param ListingListingCharacteristic $listingListingCharacteristic
*/
public function removeListingListingCharacteristic(ListingListingCharacteristic $listingListingCharacteristic)
{
$this->listingListingCharacteristics->removeElement($listingListingCharacteristic);
$listingListingCharacteristic->setListing(null);
}
/**
* Get characteristics
*
* #return \Doctrine\Common\Collections\Collection|ListingListingCharacteristic[]
*/
public function getListingListingCharacteristics()
{
return $this->listingListingCharacteristics;
}
/**
* Get characteristics ordered by Group and Characteristic
*
* #return ArrayCollection
*/
public function getListingListingCharacteristicsOrderedByGroup()
{
$iterator = $this->listingListingCharacteristics->getIterator();
$iterator->uasort(
function ($a, $b) {
/**
* #var ListingListingCharacteristic $a
* #var ListingListingCharacteristic $b
*/
$groupPosA = $a->getListingCharacteristic()->getListingCharacteristicGroup()->getPosition();
$groupPosB = $b->getListingCharacteristic()->getListingCharacteristicGroup()->getPosition();
$characteristicPosA = $a->getListingCharacteristic()->getPosition();
$characteristicPosB = $b->getListingCharacteristic()->getPosition();
if ($groupPosA == $groupPosB) {
if ($characteristicPosA == $characteristicPosB) {
return 0;
}
return ($characteristicPosA < $characteristicPosB) ? -1 : 1;
}
return ($groupPosA < $groupPosB) ? -1 : 1;
}
);
return new ArrayCollection(iterator_to_array($iterator));
}
/**
* Add characteristics
*
* #param ListingListingCharacteristic $listingListingCharacteristic
* #return Listing
*/
public function addListingListingCharacteristicsOrderedByGroup(
ListingListingCharacteristic $listingListingCharacteristic
) {
return $this->addListingListingCharacteristic($listingListingCharacteristic);
}
/**
* Remove characteristics
*
* #param ListingListingCharacteristic $listingListingCharacteristic
*/
public function removeListingListingCharacteristicsOrderedByGroup(
ListingListingCharacteristic $listingListingCharacteristic
) {
$this->removeListingListingCharacteristic($listingListingCharacteristic);
}
/**
* Add category
*
* #param ListingListingCategory $listingListingCategory
* #return Listing
*/
public function addListingListingCategory(ListingListingCategory $listingListingCategory)
{
$listingListingCategory->setListing($this);
$this->listingListingCategories[] = $listingListingCategory;
return $this;
}
/**
* Remove category
*
* #param ListingListingCategory $listingListingCategory
*/
public function removeListingListingCategory(ListingListingCategory $listingListingCategory)
{
// foreach ($listingListingCategory->getValues() as $value) {
// $listingListingCategory->removeValue($value);
// }
$this->listingListingCategories->removeElement($listingListingCategory);
}
/**
* Get categories
*
* #return \Doctrine\Common\Collections\Collection|ListingListingCategory[]
*/
public function getListingListingCategories()
{
return $this->listingListingCategories;
}
/**
* Set user
*
* #param \Cocorico\UserBundle\Entity\User $user
* #return Listing
*/
public function setUser(User $user = null)
{
$this->user = $user;
return $this;
}
/**
* Get user
*
* #return \Cocorico\UserBundle\Entity\User
*/
public function getUser()
{
return $this->user;
}
/**
* Add images
*
* #param ListingImage $image
* #return Listing
*/
public function addImage(ListingImage $image)
{
$image->setListing($this); //Because the owning side of this relation is listing image
$this->images[] = $image;
return $this;
}
/**
* Remove images
*
* #param ListingImage $image
*/
public function removeImage(ListingImage $image)
{
$this->images->removeElement($image);
$image->setListing(null);
}
/**
* Get images
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getImages()
{
return $this->images;
}
/**
* Set location
*
* #param ListingLocation $location
* #return Listing
*/
public function setLocation(ListingLocation $location = null)
{
$this->location = $location;
//Needed to persist listing_id on listing_location table when inserting a new listing embedding a listing location form
$this->location->setListing($this);
}
/**
* Get location
*
* #return ListingLocation
*/
public function getLocation()
{
return $this->location;
}
/**
* Add discount
*
* #param ListingDiscount $discount
* #return Listing
*/
public function addDiscount(ListingDiscount $discount)
{
$discount->setListing($this);
$this->discounts[] = $discount;
return $this;
}
/**
* Remove discount
*
* #param ListingDiscount $discount
*/
public function removeDiscount(ListingDiscount $discount)
{
$this->discounts->removeElement($discount);
$discount->setListing(null);
}
/**
* Get discounts
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getDiscounts()
{
return $this->discounts;
}
/**
* #param ArrayCollection|ListingDiscount[] $discounts
*/
public function setDiscounts(ArrayCollection $discounts)
{
foreach ($discounts as $discount) {
$discount->setListing($this);
}
$this->discounts = $discounts;
}
/**
* #return \Doctrine\Common\Collections\Collection|Booking[]
*/
public function getBookings()
{
return $this->bookings;
}
/**
* #param ArrayCollection|Booking[] $bookings
*/
public function setBookings(ArrayCollection $bookings)
{
foreach ($bookings as $booking) {
$booking->setListing($this);
}
$this->bookings = $bookings;
}
/**
* Add booking
*
* #param Booking $booking
*
* #return Listing
*/
public function addBooking(Booking $booking)
{
$this->bookings[] = $booking;
return $this;
}
/**
* Remove booking
*
* #param Booking $booking
*/
public function removeBooking(Booking $booking)
{
$this->bookings->removeElement($booking);
}
/**
* #return mixed
*/
public function getThreads()
{
return $this->threads;
}
/**
* #param ArrayCollection|Thread[] $threads
*/
public function setThreads(ArrayCollection $threads)
{
foreach ($threads as $thread) {
$thread->setListing($this);
}
$this->threads = $threads;
}
/**
* Add thread
*
* #param Thread $thread
*
* #return Listing
*/
public function addThread(Thread $thread)
{
$this->threads[] = $thread;
return $this;
}
/**
* Remove thread
*
* #param Thread $thread
*/
public function removeThread(Thread $thread)
{
$this->threads->removeElement($thread);
}
/**
* Add ListingOption
*
* #param ListingOptionInterface $option
* #return Listing
*/
public function addOption($option)
{
$option->setListing($this);
$this->options[] = $option;
return $this;
}
/**
* Remove ListingOption
*
* #param ListingOptionInterface $option
*/
public function removeOption($option)
{
$this->options->removeElement($option);
}foreach ($threads as $thread) {
$thread->setListing($this);
}
$this->threads = $threads;
}
/**
* Add thread
*
* #param Thread $thread
*
* #return Listing
*/
public function addThread(Thread $thread)
{
$this->threads[] = $thread;
return $this;
}
/**
* Remove thread
*
* #param Thread $thread
*/
public function removeThread(Thread $thread)
{
$this->threads->removeElement($thread);
}
/**
* Add ListingOption
*
* #param ListingOptionInterface $option
* #return Listing
*/
public function addOption($option)
{
$option->setListing($this);
$this->options[] = $option;
return $this;
}
/**
* Remove ListingOption
*
* #param ListingOptionInterface $option
*/
public function removeOption($option)
{
$this->options->removeElement($option);
}
/**
* Get ListingOptions
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getOptions()
{
return $this->options;
}
/**
* #param ArrayCollection $options
* #return $this
*/
public function setOptions(ArrayCollection $options)
{
foreach ($options as $option) {
$option->setListing($this);
}
$this->options = $options;
return $this;
}
/**
* #param int $minImages
* #param bool $strict
*
* #return array
*/
public function getCompletionInformations($minImages, $strict = true)
{
$characteristic = 0;
foreach ($this->getListingListingCharacteristics() as $characteristics) {
if ($characteristics->getListingCharacteristicValue()) {
$characteristic = 1;
}
}
return array(
"title" => $this->getTitle() ? 1 : 0,
"description" => (
($strict && $this->getDescription()) ||
(!$strict && strlen($this->getDescription()) > 250)
) ? 1 : 0,
"price" => $this->getPrice() ? 1 : 0,
"image" => (
($strict && count($this->getImages()) >= $minImages) ||
(!$strict && count($this->getImages()) > $minImages)
) ? 1 : 0,
"characteristic" => $characteristic,
);
}
public function getTitle()
{
return (string)$this->translate()->getTitle();
}
public function getSlug()
{
return (string)$this->translate()->getSlug();
}
public function __toString()
{
return (string)$this->getTitle();
}
/**
* To add impersonating link into admin :
*
* #return User
*/
public function getImpersonating()
{
return $this->getUser();
}
}
I make an API with Symfony4 and
I use the PagerFanta bundle. I made an AbstractRepository abstract class for my pagination:
<?php
namespace App\Repository;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\QueryBuilder;
use Pagerfanta\Adapter\DoctrineORMAdapter;
use Pagerfanta\Pagerfanta;
class AbstractRepository extends EntityRepository
{
protected function paginate(QueryBuilder $qb, $limit = 20, $offset = 0)
{
if (0 == $limit || 0 == $offset) {
throw new \LogicException('$limit & $offstet must be greater
than 0.');
}
$pager = new Pagerfanta(new DoctrineORMAdapter($qb));
$currentPage = ceil($offset + 1) / $limit;
$pager->setCurrentPage($currentPage);
$pager->setMaxPerPage((int)$limit);
return $pager;
}
}
My Entity Article:
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation\Expose;
use JMS\Serializer\Annotation\ExclusionPolicy;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Class Article
* #ORM\Entity(repositoryClass="App\Repository\ArticleRepository")
* #ORM\Table(name="article")
*
* #ExclusionPolicy("all")
*/
class Article
{
/**
* #ORM\Id()
* #ORM\Column(type="integer")
* #ORM\GeneratedValue()
*
* #Expose()
*/
private $id;
/**
* #ORM\Column(type="string")
* #Assert\NotBlank(groups={"Create"})
* #Expose()
*/
private $title;
/**
* #ORM\Column(type="string")
* #Assert\NotBlank(groups={"Create"})
* #Expose()
*/
private $content;
/**
* #return mixed
*/
public function getId()
{
return $this->id;
}
/**
* #param mixed $id
*/
public function setId($id): void
{
$this->id = $id;
}
/**
* #return mixed
*/
public function getTitle()
{
return $this->title;
}
/**
* #param mixed $title
*/
public function setTitle($title): void
{
$this->title = $title;
}
/**
* #return mixed
*/
public function getContent()
{
return $this->content;
}
/**
* #param mixed $content
*/
public function setContent($content): void
{
$this->content = $content;
}
}
I tested a var_dump of $ qb but I do not get the items already, My ArticleRepository:
<?php
namespace App\Repository;
class ArticleRepository extends AbstractRepository
{
public function search($term, $order = 'asc', $limit = 20, $offset = 0)
{
$qb = $this
->createQueryBuilder('a')
->select('a')
->orderBy('a.title', $order);
if ($term) {
$qb
->where('a.title LIKE ?1')
->setParameter(1, '%'.$term.'%');
}
return $this->paginate($qb, $limit, $offset);
}
}
My ArticleController:
<?php
namespace App\Controller;
use App\Entity\Article;
use FOS\RestBundle\Controller\Annotations as Rest;
use FOS\RestBundle\Controller\FOSRestController;
use FOS\RestBundle\Request\ParamFetcherInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use App\Representation\Articles;
use Symfony\Component\Validator\ConstraintViolationList;
class ArticleController extends FOSRestController
{
/**
* #Rest\Get(
* path = "/articles/{id}",
* name = "app_article_show",
* requirements = {"id"="\d+"}
* )
* #Rest\View()
*/
public function showAction(Article $article)
{
return $article;
}
/**
* #Rest\Post(
* path = "/articles",
* name= "app_article_show",
* )
* #Rest\View(StatusCode= 201)
* #ParamConverter(
* "article", converter="fos_rest.request_body",
* options={
"validator"={ "groups"="Create"}
* }
* )
*/
public function createAction(Article $article, ConstraintViolationList $violations)
{
if (count($violations)) {
return $this->view($violations, Response::HTTP_BAD_REQUEST);
}
$em = $this->getDoctrine()->getManager();
$em->persist($article);
$em->flush();
return $this->view(
$article,
Response::HTTP_CREATED,
[
'Location' => $this->generateUrl('app_article_show', ['id', $article->getId()], UrlGeneratorInterface::ABSOLUTE_URL)
]
);
}
/**
* #Rest\Get(
* path="/articles",
* name="app_article_list"
* )
* #Rest\QueryParam(
* name="keyword",
* requirements="[a-zA-Z0-9]",
* nullable=true,
* description="The keyword to search for."
* )
* #Rest\QueryParam(
* name="order",
* requirements="asc|desc",
* default="asc",
* description="Sort order (asc or desc)"
* )
* #Rest\QueryParam(
* name="limit",
* requirements="\d+",
* default="15",
* description="Max number of movies per page."
* )
* #Rest\QueryParam(
* name="offset",
* requirements="\d+",
* default="0",
* description="The pagination offset"
* )
* #Rest\View()
*/
public function listAction(ParamFetcherInterface $paramFetcher)
{
$pager = $this->getDoctrine()->getRepository('App:Article')->search(
$paramFetcher->get('keyword'),
$paramFetcher->get('order'),
$paramFetcher->get('limit'),
$paramFetcher->get('offset')
);
return new Articles($pager);
}
}
My Articles in Representation:
<?php
namespace App\Representation;
use Pagerfanta\Pagerfanta;
use JMS\Serializer\Annotation\Type;
class Articles
{
/**
* #Type("ArrayCollection<App\Entity\Article>")
*/
public $data;
public $meta;
public function __construct(Pagerfanta $data)
{
$this->data = $data->getCurrentPageResults();
$this->addMeta('limit', $data->getMaxPerPage());
$this->addMeta('current_items', count($data->getCurrentPageResults()));
$this->addMeta('total_items', $data->getNbResults());
$this->addMeta('offset', $data->getCurrentPageOffsetStart());
}
public function addMeta($name, $value)
{
if (isset($this->meta[$name])) {
throw new \LogicException(sprintf('This meta already exists. You are trying to override this meta, use the setMeta method instead for the %s meta.', $name));
}
$this->setMeta($name, $value);
}
public function setMeta($name, $value)
{
$this->meta[$name] = $value;
}
}
And that's the mistake that returns to me postman:
When I var_dump in the repository I do not already recover the articles but I do not see why
I see my problem in AbstractRepository replace
$currentPage = ceil($offset + 1) / $limit;
per:
$currentPage = ceil(($offset + 1) / $limit);
And my ArticleController replace
* #Rest\QueryParam(
* name="offset",
* requirements="\d+",
* default="0",
* description="The pagination offset"
* )
* #Rest\View()
*/
per
* #Rest\QueryParam(
* name="offset",
* requirements="\d+",
* default="1",
* description="The pagination offset"
* )
* #Rest\View()
*/
Thanks
Introduction
I am using:
Windows 10 Pro
XAMPP with PHP v7.0.9
Symfony v3.1.7
Doctrine v2.5.4
StofDoctrineExtensionsBundle [1] in order to manage Tree structure.
Setting up
To setup Tree structure I used documentation on Symfony.com [2] followed by documentation on GitHub [3]. Then I proceeded with tree setup - used tree entity from example [4] and used code in [5] to create a tree.
I did setup the tree structure (that represents directories and files) called FileTree. I added several custom fields to the tree: item_name, item_extension and is_file. Removed title as I have item_name...
My FileTree entity:
<?php
namespace AppBundle\Entity;
use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\Mapping\ManyToOne;
use Doctrine\ORM\Mapping\JoinColumn;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\Common\Collections\ArrayCollection as ArrayCollection;
/**
* #Gedmo\Tree(type="nested")
* #ORM\Table(name="file_tree")
* use repository for handy tree functions
* #ORM\Entity(repositoryClass="AppBundle\Repository\FileTreeRepository")
*/
class FileTree
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue
*/
private $id;
/**
* #ORM\Column(type="string", length=1024)
*
* #var string
*/
private $item_path;
/**
* #ORM\Column(type="string", length=240)
*
* #var string
*/
private $item_name;
/**
* #ORM\Column(type="string", length=20)
*
* #var string
*/
private $item_extension;
/**
* #ORM\Column(type="boolean")
*/
private $is_file;
/**
* #Gedmo\TreeLeft
* #ORM\Column(type="integer")
*/
private $lft;
/**
* #Gedmo\TreeLevel
* #ORM\Column(type="integer")
*/
private $lvl;
/**
* #Gedmo\TreeRight
* #ORM\Column(type="integer")
*/
private $rgt;
/**
* #Gedmo\TreeRoot
* #ORM\ManyToOne(targetEntity="FileTree")
* #ORM\JoinColumn(referencedColumnName="id", onDelete="CASCADE")
*/
private $root;
/**
* #Gedmo\TreeParent
* #ORM\ManyToOne(targetEntity="FileTree", inversedBy="children")
* #ORM\JoinColumn(referencedColumnName="id", onDelete="CASCADE")
*/
private $parent;
/**
* #ORM\OneToMany(targetEntity="FileTree", mappedBy="parent")
* #ORM\OrderBy({"lft" = "ASC"})
*/
private $children;
/**
* #ManyToOne(targetEntity="Project", inversedBy="file_tree")
* #JoinColumn(name="project_id", referencedColumnName="id")
*/
private $project;
/**
* Constructor
*/
public function __construct()
{
$this->children = new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set itemPath
*
* #param string $itemPath
*
* #return FileTree
*/
public function setItemPath($itemPath)
{
$this->item_path = $itemPath;
return $this;
}
/**
* Get itemPath
*
* #return string
*/
public function getItemPath()
{
return $this->item_path;
}
/**
* Set itemName
*
* #param string $itemName
*
* #return FileTree
*/
public function setItemName($itemName)
{
$this->item_name = $itemName;
return $this;
}
/**
* Get itemName
*
* #return string
*/
public function getItemName()
{
return $this->item_name;
}
/**
* Set isFile
*
* #param boolean $isFile
*
* #return FileTree
*/
public function setIsFile($isFile)
{
$this->is_file = $isFile;
return $this;
}
/**
* Get isFile
*
* #return boolean
*/
public function getIsFile()
{
return $this->is_file;
}
/**
* Set lft
*
* #param integer $lft
*
* #return FileTree
*/
public function setLft($lft)
{
$this->lft = $lft;
return $this;
}
/**
* Get lft
*
* #return integer
*/
public function getLft()
{
return $this->lft;
}
/**
* Set lvl
*
* #param integer $lvl
*
* #return FileTree
*/
public function setLvl($lvl)
{
$this->lvl = $lvl;
return $this;
}
/**
* Get lvl
*
* #return integer
*/
public function getLvl()
{
return $this->lvl;
}
/**
* Set rgt
*
* #param integer $rgt
*
* #return FileTree
*/
public function setRgt($rgt)
{
$this->rgt = $rgt;
return $this;
}
/**
* Get rgt
*
* #return integer
*/
public function getRgt()
{
return $this->rgt;
}
/**
* Set root
*
* #param \AppBundle\Entity\FileTree $root
*
* #return FileTree
*/
public function setRoot(\AppBundle\Entity\FileTree $root = null)
{
$this->root = $root;
return $this;
}
/**
* Get root
*
* #return \AppBundle\Entity\FileTree
*/
public function getRoot()
{
return $this->root;
}
/**
* Set parent
*
* #param \AppBundle\Entity\FileTree $parent
*
* #return FileTree
*/
public function setParent(\AppBundle\Entity\FileTree $parent = null)
{
$this->parent = $parent;
return $this;
}
/**
* Get parent
*
* #return \AppBundle\Entity\FileTree
*/
public function getParent()
{
return $this->parent;
}
/**
* Add child
*
* #param \AppBundle\Entity\FileTree $child
*
* #return FileTree
*/
public function addChild(\AppBundle\Entity\FileTree $child)
{
$this->children[] = $child;
return $this;
}
/**
* Remove child
*
* #param \AppBundle\Entity\FileTree $child
*/
public function removeChild(\AppBundle\Entity\FileTree $child)
{
$this->children->removeElement($child);
}
/**
* Get children
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getChildren()
{
return $this->children;
}
/**
* Set project
*
* #param \AppBundle\Entity\Project $project
*
* #return FileTree
*/
public function setProject(\AppBundle\Entity\Project $project = null)
{
$this->project = $project;
return $this;
}
/**
* Get project
*
* #return \AppBundle\Entity\Project
*/
public function getProject()
{
return $this->project;
}
/**
* toString
*
* #return string
*/
public function __toString()
{
return $this->getItemName();
}
/**
* Set itemExtension
*
* #param string $itemExtension
*
* #return FileTree
*/
public function setItemExtension($itemExtension)
{
$this->item_extension = $itemExtension;
return $this;
}
/**
* Get itemExtension
*
* #return string
*/
public function getItemExtension()
{
return $this->item_extension;
}
}
Problem
I need to order files in the folders of the tree by file type - that is: by item_extension and then by item_name. At the moment Gedmo Nestedset Tree sorts by root and lft as is shown in next code block.
public function getFileTreeNodeArray($file_tree_root_id)
{
$em = $this->getEntityManager();
$query = $em
->createQueryBuilder()
->select('ft')
->from('AppBundle:FileTree', 'ft')
->where('ft.root = :root')
->setParameter('root', $file_tree_root_id)
->orderBy('ft.root, ft.lft', 'ASC')
->getQuery();
$query->setHint(\Doctrine\ORM\Query::HINT_INCLUDE_META_COLUMNS, true);
$build_my_tree = $query->getArrayResult();
return $build_my_tree;
}
Sadly adding additional ->orderBy('ft.item_extension', 'ASC') did not yield any results...
Then I learned [6] that there are 2 functions that may aide me in this endeavor reorderAll and reorder. I tried both of them, but sadly items did not change their order, they remained ordered by root and lft.
My code from Upload Listener:
$repo_file_tree = $this->entityManager->getRepository('AppBundle:FileTree');
$root_node_id = $repo_file_tree->getFileTreeRootNodeIdByProjectId($selected_node_parent_id);
$root_node = $repo_file_tree->findOneBy(array('id' => $root_node_id));
$repo_file_tree->reorder($root_node, 'item_extension, item_name', 'ASC');
$this->entityManager->flush();
or
$repo_file_tree = $this->entityManager->getRepository('AppBundle:FileTree');
$repo_file_tree->reorderAll('item_extension, item_name', 'ASC');
$this->entityManager->flush();
Question
How do I get an array with FileTree items that are ordered by item_extension, item_name?
I would be happy with ether correct Doctrine query (preferably) or with explanation what is wrong with code blocks that contain functions reorder and reorderAll.
Conclusion
What am I missing?
Please advise.
Thank you for your time and knowledge.
Just updated my project to Symfony v3.2.0
Now I get error
Invalid sort options specified: field - item_extension, item_name, direction - ASC
500 Internal Server Error - InvalidArgumentException
with above mentioned code when using reorder.
I am not sure is it occurring just now (after upgrade) or it was there also with Symfony v3.1.x.
Anyhow - it is clear that reorder does take only one field by which it orders tree branch. Not multiple fields as I tried earlier.
So the answer is: not to use several ordering fields when calling reorder function.
$repo_file_tree = $this->entityManager->getRepository('AppBundle:FileTree');
$root_node_id = $repo_file_tree->getFileTreeRootNodeIdByProjectId($selected_node_parent_id);
$root_node = $repo_file_tree->findOneBy(array('id' => $root_node_id));
$repo_file_tree->reorder($root_node, 'item_extension', 'ASC');
$this->entityManager->flush();
I have a table question, the field "valeurs default" has the answers to all the questions which's gonna be a multiple selection field my problem is to add (Action box) a small button to order the answers for example for the question: "age"--> the answers will be displayed after clicking on the order button: " 20->25 25->30 30->35 "
this is how it appears in my template
can you help me please?
this is my entity "Question"
class Question
{/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="Libelle", type="string", length=150)
*/
private $libelle;
/**
* #var string
*
* #ORM\Column(name="TypeQuestion", type="string", length=150)
*/
protected $TypeQuestion;
/**
* #ORM\ManyToMany(targetEntity="tuto\BackofficeBundle\Entity\Service")
*/
protected $Service;
/**
* #ORM\ManyToMany(targetEntity="tuto\BackofficeBundle\Entity\ValeursDefault")
*/
protected $ValeursDefault;
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set libelle
*
* #param string $libelle
*
* #return Question
*/
public function setLibelle($libelle)
{
$this->libelle = $libelle;
return $this;
}
/**
* Get libelle
*
* #return string
*/
public function getLibelle()
{
return $this->libelle;
}
/**
* Constructor
*/
public function __construct()
{
$this->Service = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Add Service
*
* #param \tuto\BackofficeBundle\Entity\Service $service
* #return Question
*/
public function addService(\tuto\BackofficeBundle\Entity\Service $service)
{
$this->Service[] = $service;
return $this;
}
/**
* Remove Service
*
* #param \tuto\BackofficeBundle\Entity\Service $service
*/
public function removeService(\tuto\BackofficeBundle\Entity\Service $service)
{
$this->Service->removeElement($service);
}
/**
* Get Service
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getService()
{
return $this->Service;
}
/**
* Add ValeursDefault
*
* #param \tuto\BackofficeBundle\Entity\ValeursDefault $valeursDefault
* #return Question
*/
public function addValeursDefault(\tuto\BackofficeBundle\Entity\ValeursDefault $valeursDefault)
{
$this->ValeursDefault[] = $valeursDefault;
return $this;
}
/**
* Remove ValeursDefault
*
* #param \tuto\BackofficeBundle\Entity\ValeursDefault $valeursDefault
*/
public function removeValeursDefault(\tuto\BackofficeBundle\Entity\ValeursDefault $valeursDefault)
{
$this->ValeursDefault->removeElement($valeursDefault);
}
/**
* Get ValeursDefault
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getValeursDefault()
{
return $this->ValeursDefault;
}
/**
* Set TypeQuestion
*
* #param string $typeQuestion
* #return Question
*/
public function setTypeQuestion($typeQuestion)
{
$this->TypeQuestion = $typeQuestion;
return $this;
}
/**
* Get TypeQuestion
*
* #return string
*/
public function getTypeQuestion()
{
return $this->TypeQuestion;
}
}
the html.twig file
Write a twig extension that sorts ValeursDefault in twig.It's usually what I do with nested objects.
for more details http://symfony.com/doc/current/cookbook/templating/twig_extension.html
I had a similar problem before wanting to order child objects of an entity based on an attribute called position, so I wrote something like this
public function orderPosition($arr) {
$size = count($arr);
for ($i = 0; $i < $size; $i++) {
for ($j = 0; $j < $size - 1 - $i; $j++) {
if ($arr[$j + 1]->getPosition() < $arr[$j]->getPosition()) {
$this->swap($arr, $j, $j + 1);
}
}
}
return $arr;
}
For your case, instead of getPosition() you'd be using whatever function you have in ValeursDefault that you want to sort by
I think you can sort your values using Doctrine :
http://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/tutorials/ordered-associations.html
/**
* #ORM\ManyToMany(targetEntity="tuto\BackofficeBundle\Entity\ValeursDefault")
* #ORM\OrderBy({"value" = "ASC"})
*/
protected $ValeursDefault;
I have a new problem related to Doctrine2 and Oracle...
I migrated an application from Symfony1 to symfony2. When I insert a new entry in the production database with Doctrine2, I get the error "ORA-00001: unique constraint violated". It tries to insert with the ID 1, if I try again it tries to insert with ID 2 etc...
Here is how I setup my entity :
<?php
namespace EspaceApprenti\UserBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* ApprenticeMark
*
* #ORM\Table(name="APPRENTICE_MARK", indexes={#ORM\Index(name="IDX_8582BCF7105754FC", columns={"FK_BRANCH"}), #ORM\Index(name="IDX_8582BCF7C9387C17", columns={"FK_YEAR"}), #ORM\Index(name="IDX_8582BCF73B451C64", columns={"FK_MARKTYPE"})})
* #ORM\Entity(repositoryClass="EspaceApprenti\UserBundle\Entity\ApprenticeMarkRepository")
*/
class ApprenticeMark
{
/**
* #var integer
*
* #ORM\Column(name="COEFFICIENT", type="bigint", nullable=false)
*/
private $coefficient;
/**
* #var integer
*
* #ORM\Column(name="ID", type="bigint", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="SEQUENCE")
*/
private $id;
/**
* #var integer
*
* #ORM\Column(name="RESULT", type="decimal", precision=2, scale=1, nullable=false)
*/
private $result;
/**
* #var \ApprenticeBranch
*
* #ORM\ManyToOne(targetEntity="ApprenticeBranch")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="FK_BRANCH", referencedColumnName="ID")
* })
*/
private $fkBranch;
/**
* #var \ApprenticeYear
*
* #ORM\ManyToOne(targetEntity="ApprenticeYear")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="FK_YEAR", referencedColumnName="ID", onDelete="CASCADE")
* })
*/
private $fkYear;
/**
* #var \ApprenticeMarktype
*
* #ORM\ManyToOne(targetEntity="ApprenticeMarktype")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="FK_MARKTYPE", referencedColumnName="ID")
* })
*/
private $fkMarktype;
/**
* Set coefficient
*
* #param integer $coefficient
* #return ApprenticeMark
*/
public function setCoefficient($coefficient)
{
$this->coefficient = $coefficient;
return $this;
}
/**
* Get coefficient
*
* #return integer
*/
public function getCoefficient()
{
return $this->coefficient;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set result
*
* #param integer $result
* #return ApprenticeMark
*/
public function setResult($result)
{
$this->result = $result;
return $this;
}
/**
* Get result
*
* #return integer
*/
public function getResult()
{
return $this->result;
}
/**
* Set fkBranch
*
* #param \EspaceApprenti\UserBundle\Entity\ApprenticeBranch $fkBranch
* #return ApprenticeMark
*/
public function setFkBranch(\EspaceApprenti\UserBundle\Entity\ApprenticeBranch $fkBranch = null)
{
$this->fkBranch = $fkBranch;
return $this;
}
/**
* Get fkBranch
*
* #return \EspaceApprenti\UserBundle\Entity\ApprenticeBranch
*/
public function getFkBranch()
{
return $this->fkBranch;
}
/**
* Set fkYear
*
* #param \EspaceApprenti\UserBundle\Entity\ApprenticeYear $fkYear
* #return ApprenticeMark
*/
public function setFkYear(\EspaceApprenti\UserBundle\Entity\ApprenticeYear $fkYear = null)
{
$this->fkYear = $fkYear;
return $this;
}
/**
* Get fkYear
*
* #return \EspaceApprenti\UserBundle\Entity\ApprenticeYear
*/
public function getFkYear()
{
return $this->fkYear;
}
/**
* Set fkMarktype
*
* #param \EspaceApprenti\UserBundle\Entity\ApprenticeMarktype $fkMarktype
* #return ApprenticeMark
*/
public function setFkMarktype(\EspaceApprenti\UserBundle\Entity\ApprenticeMarktype $fkMarktype = null)
{
$this->fkMarktype = $fkMarktype;
return $this;
}
/**
* Get fkMarktype
*
* #return \EspaceApprenti\UserBundle\Entity\ApprenticeMarktype
*/
public function getFkMarktype()
{
return $this->fkMarktype;
}
}
Here is the code of the controller :
public function newAction($idYear,$idYeartype)
{
$m = $this->getDoctrine()
->getManager();
// Get year
$year = $m->getRepository('EspaceApprentiUserBundle:ApprenticeYear')->find($idYear);
if (!$year) {
throw $this->createNotFoundException('Year not found');
}
// Get yeartype
$yeartype = $m->getRepository('EspaceApprentiUserBundle:ApprenticeYeartype')->find($idYeartype);
if (!$yeartype) {
throw $this->createNotFoundException('Year type not found');
}
// Get apprentice
$apprentice = $m->getRepository('EspaceApprentiUserBundle:ApprenticeApprentice')->find($year->getFkApprentice()->getId());
if (!$apprentice) {
throw $this->createNotFoundException('Apprentice type not found');
}
$mark = new ApprenticeMark();
$mark->setFkYear($year);
$form = $this->createForm(new ApprenticeMarkType($yeartype), $mark);
$request = $this->get('request');
if ($request->getMethod() == 'POST') {
$form->bind($request);
if ($form->isValid()) {
$m->persist($mark);
$m->flush();
return $this->redirect($this->generateUrl('grids_apprentice_index',array('idApprentice' => $apprentice->getId())));
}
}
return $this->render('EspaceApprentiGridsBundle:Grids_Mark:new.html.twig', array('apprentice' => $apprentice, 'form' => $form->createView()));
}
How do I configure Doctrine2 to get the last ID and not just increment from 1 ?
Or should I get and insert the last ID manually ?
Regards
I found the solution to my problem. Apparently my SEQUENCES in Oracle were not up to date, so I had to manually update them.