I'm learning a bit of Laravel coming over from Symfony, and i'm a little confused with how joins work with eloquent. so that i have have the returned object as my model class rather than a stdClass.
Currently i am doing this:
$query = DB::table('caravan')
->join('type','caravan.type_id', '=', 'type.id')
->join('category','caravan.category_id', '=', 'category.id')
->where('type.name','=', 'New')
->where('category.name', '=', ucwords(strtolower($category)))
->orderBy($orderBy,$order);
This works, it brings through all the correct records with the joined columns, but i don't want it to be a stdClass.
My caravan model looks like this:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasOne;
/**
* Class Caravan
* #package App\Models
* #property int $stock
* #property int $branch_id
* #property int $category_id
* #property int $type_id
* #property string $reg
* #property string $make
* #property string $model
* #property string $specification
* #property string $derivative
* #property string $engine_size
* #property string $engine_type
* #property string $transmission
* #property string $colour
* #property int $year
* #property int $mileage
* #property boolean $commercial
* #property double $sales_siv
* #property double $retail
* #property double $web_price
* #property string $sub_heading;
* #property string $advertising_notes
* #property string $manager_comments
* #property double $previous_price
* #property double $guide_retail_price
* #property boolean $available_for_sale
* #property boolean $advertised_on_own_website
* #property int $berths
* #property int $axles
* #property string $layout_type
* #property double $width
* #property double $length
* #property double $height
* #property int $kimberley_unit_id
* #property \DateTime $kimberley_date_updated
*
*/
class Caravan extends Model
{
use HasFactory;
/**
* #var string
*/
public $table = 'caravan';
/**
* #var string[]
*/
protected $casts = [
'kimberley_date_updated' => 'datetime:Y-m-d H:i:s',
'created_at' => 'datetime:Y-m-d H:i:s',
'updated_at' => 'datetime:Y-m-d H:i:s',
'web_price' => 'decimal: 2',
'previous_price' => 'decimal: 2'
];
/**
* #return HasOne
*/
public function category() : HasOne
{
return $this->hasOne(Category::class, 'id', 'category_id');
}
/**
* #return HasOne
*/
public function type() : HasOne
{
die("DD");
return $this->hasOne(Type::class, 'id', 'type_id');
}
/**
* #return int
*/
public function getStock(): int
{
return $this->stock;
}
/**
* #param int $stock
* #return $this
*/
public function setStock(int $stock): self
{
$this->stock = $stock;
return $this;
}
/**
* #return int
*/
public function getBranchId(): int
{
return $this->branch_id;
}
/**
* #param int $branch_id
* #return $this
*/
public function setBranchId(int $branch_id): self
{
$this->branch_id = $branch_id;
return $this;
}
/**
* #param Branch $branch
* #return $this
*/
public function setBranch(Branch $branch) : self
{
$this->branch_id = $branch->id;
return $this;
}
/**
* #return int
*/
public function getCategoryId(): int
{
return $this->category_id;
}
/**
* #param int $category_id
* #return $this
*/
public function setCategoryId(int $category_id): self
{
$this->category_id = $category_id;
return $this;
}
/**
* #param Category $cat
* #return $this
*/
public function setCategory(Category $cat) : self
{
$this->category_id = $cat->id;
return $this;
}
/**
* #return int
*/
public function getTypeId(): int
{
return $this->type_id;
}
/**
* #param int $type_id
* #return $this
*/
public function setTypeId(int $type_id): self
{
$this->type_id = $type_id;
return $this;
}
/**
* #param Type $type
* #return $this
*/
public function setType(Type $type) : self
{
$this->type_id = $type->id;
return $this;
}
/**
* #return string
*/
public function getReg(): string
{
return $this->reg;
}
/**
* #param string $reg
* #return $this
*/
public function setReg(string $reg): self
{
$this->reg = $reg;
return $this;
}
/**
* #return string
*/
public function getMake(): string
{
return $this->make;
}
/**
* #param string $make
* #return $this
*/
public function setMake(string $make): self
{
$this->make = $make;
return $this;
}
/**
* #return string
*/
public function getModel(): string
{
return $this->model;
}
/**
* #param string $model
* #return $this
*/
public function setModel(string $model): self
{
$this->model = $model;
return $this;
}
/**
* #return string
*/
public function getSpecification(): string
{
return $this->specification;
}
/**
* #param string $specification
* #return $this
*/
public function setSpecification(string $specification): self
{
$this->specification = $specification;
return $this;
}
/**
* #return string
*/
public function getDerivative(): string
{
return $this->derivative;
}
/**
* #param string $derivative
* #return $this
*/
public function setDerivative(string $derivative): self
{
$this->derivative = $derivative;
return $this;
}
/**
* #return string
*/
public function getEngineSize(): string
{
return $this->engine_size;
}
/**
* #param string $engine_size
* #return $this
*/
public function setEngineSize(string $engine_size): self
{
$this->engine_size = $engine_size;
return $this;
}
/**
* #return string
*/
public function getEngineType(): string
{
return $this->engine_type;
}
/**
* #param string $engine_type
* #return $this
*/
public function setEngineType(string $engine_type): self
{
$this->engine_type = $engine_type;
return $this;
}
/**
* #return string
*/
public function getTransmission(): string
{
return $this->transmission;
}
/**
* #param string $transmission
* #return $this
*/
public function setTransmission(string $transmission): self
{
$this->transmission = $transmission;
return $this;
}
/**
* #return string
*/
public function getColour(): string
{
return $this->colour;
}
/**
* #param string $colour
* #return $this
*/
public function setColour(string $colour): self
{
$this->colour = $colour;
return $this;
}
/**
* #return int
*/
public function getYear(): int
{
return $this->year;
}
/**
* #param int $year
* #return $this
*/
public function setYear(int $year): self
{
$this->year = $year;
return $this;
}
/**
* #return int
*/
public function getMileage(): int
{
return $this->mileage;
}
/**
* #param int $mileage
* #return $this
*/
public function setMileage(int $mileage): self
{
$this->mileage = $mileage;
return $this;
}
/**
* #return bool
*/
public function isCommercial(): bool
{
return (bool)$this->commercial;
}
/**
* #param bool $commercial
* #return $this
*/
public function setCommercial(bool $commercial): self
{
$this->commercial = (int)$commercial;
return $this;
}
/**
* #return float
*/
public function getSalesSiv(): float
{
return $this->sales_siv;
}
/**
* #param float|int $sales_siv
* #return $this
*/
public function setSalesSiv(float $sales_siv = 0): self
{
$this->sales_siv = $sales_siv;
return $this;
}
/**
* #return float
*/
public function getRetail(): float
{
return $this->retail;
}
/**
* #param float|int $retail
* #return $this
*/
public function setRetail(float $retail = 0): self
{
$this->retail = $retail;
return $this;
}
/**
* #return float
*/
public function getWebPrice(): float
{
return $this->web_price;
}
/**
* #param float|int $web_price
* #return $this
*/
public function setWebPrice(float $web_price = 0): self
{
$this->web_price = $web_price;
return $this;
}
/**
* #return string
*/
public function getSubHeading(): string
{
return $this->sub_heading;
}
/**
* #param string $sub_heading
* #return $this
*/
public function setSubHeading(string $sub_heading): self
{
$this->sub_heading = $sub_heading;
return $this;
}
/**
* #return string
*/
public function getAdvertisingNotes(): string
{
return $this->advertising_notes;
}
/**
* #param string $advertising_notes
* #return $this
*/
public function setAdvertisingNotes(string $advertising_notes): self
{
$this->advertising_notes = $advertising_notes;
return $this;
}
/**
* #return string
*/
public function getManagerComments(): string
{
return $this->manager_comments;
}
/**
* #param string $managerComments
* #return $this
*/
public function setManagerComments(string $managerComments): self
{
$this->manager_comments = $managerComments;
return $this;
}
/**
* #return float
*/
public function getPreviousPrice(): float
{
return $this->previous_price;
}
/**
* #param float $previous_price
* #return $this
*/
public function setPreviousPrice(float $previous_price): self
{
$this->previous_price = $previous_price;
return $this;
}
/**
* #return float
*/
public function getGuideRetailPrice(): float
{
return $this->guide_retail_price;
}
/**
* #param float $guide_retail_price
* #return $this
*/
public function setGuideRetailPrice(float $guide_retail_price): self
{
$this->guide_retail_price = $guide_retail_price;
return $this;
}
/**
* #return bool
*/
public function isAvailableForSale(): bool
{
return $this->available_for_sale;
}
/**
* #param bool $available_for_sale
* #return $this
*/
public function setAvailableForSale(bool $available_for_sale): self
{
$this->available_for_sale = (int)$available_for_sale;
return $this;
}
/**
* #return bool
*/
public function isAdvertisedOnOwnWebsite(): bool
{
return $this->advertised_on_own_website;
}
/**
* #param bool $advertised_on_own_website
* #return $this
*/
public function setAdvertisedOnOwnWebsite(bool $advertised_on_own_website): self
{
$this->advertised_on_own_website = (int)$advertised_on_own_website;
return $this;
}
/**
* #return int
*/
public function getBerths(): int
{
return $this->berths;
}
/**
* #param int $berth
*/
public function setBerths(int $berths): self
{
$this->berths = $berths;
return $this;
}
/**
* #return int
*/
public function getAxles(): int
{
return $this->axles;
}
/**
* #param int $axles
* #return $this
*/
public function setAxles(int $axles): self
{
$this->axles = $axles;
return $this;
}
/**
* #return string
*/
public function getLayoutType(): string
{
return $this->layout_type;
}
/**
* #param string $layout_type
* #return $this
*/
public function setLayoutType(string $layout_type): self
{
$this->layout_type = $layout_type;
return $this;
}
/**
* #return float
*/
public function getWidth(): float
{
return $this->width;
}
/**
* #param float $width
* #return $this
*/
public function setWidth(float $width): self
{
$this->width = $width;
return $this;
}
/**
* #return float
*/
public function getLength(): float
{
return $this->length;
}
/**
* #param float $length
* #return $this
*/
public function setLength(float $length): self
{
$this->length = $length;
return $this;
}
/**
* #return float
*/
public function getHeight(): float
{
return $this->height;
}
/**
* #param float $height
* #return $this
*/
public function setHeight(float $height): self
{
$this->height = $height;
return $this;
}
/**
* #return int
*/
public function getKimberleyUnitId(): int
{
return $this->kimberley_unit_id;
}
/**
* #param int $kimberley_unit_id
* #return $this
*/
public function setKimberleyUnitId(int $kimberley_unit_id): self
{
$this->kimberley_unit_id = $kimberley_unit_id;
return $this;
}
/**
* #return \DateTime
*/
public function getKimberleyDateUpdated(): \DateTime
{
return $this->kimberley_date_updated;
}
/**
* #param \DateTime $kimberley_date_updated
* #return $this
*/
public function setKimberleyDateUpdated(\DateTime $kimberley_date_updated): self
{
$this->kimberley_date_updated = $kimberley_date_updated;
return $this;
}
}
So i have the HasOne parts at the top to be able to use the model to get the type and category, but how would i do this to replace my query above with the where clause?
I have tried something like:
Caravan::with(['type','category'])->where('type.name','New');
This doesn't work, just says type doesn't exist in so many words.
So what i want to get back, is the model like i would just running say Caravan::all() which i would then be able to loop and use something like $caravan->type->name
EDIT
Answer below from Wahyu:
Caravan::with(['type' => function ($query) {
$query->where('name', 'New');
}, 'category' => function($query) use ($category) {
$query->where('name',ucwords(strtolower($category)));
}])->orderBy($orderBy,$order);
This query runs fine however, it's bringing results back where type is Used as well as New so the query isn't working.
Also, looping the results, i still can't use the HasOne method in my model to do $caravan->type->name
However, Caravan::all() as a test allows me to use $caravan->type->name in the loop and that works ok, so the where query is still an issue
You can accomplish by passing an array of relationships to the with method where the array key is a relationship name and the array value is a closure that adds additional constraints to the eager loading query:
Caravan::with(['type' => function ($query) {
$query->where('name', 'New');
}, 'category'])->get();
Update (different question):
i still can't use the HasOne method in my model to do $caravan->type->name
public function type() : HasOne
{
return $this->hasOne(Type::class, 'id', 'type_id');
}
So, you can access the Type model from Caravan model. You can define the inverse of a hasOne relationship using the belongsTo method:
public function type()
{
return $this->belongsTo(Type::class);
}
When invoking the type method, Eloquent will attempt to find a Type model that has an id which matches the type_id column on the Caravan model.
If you are using a recent version of Laravel you can do something like:
Caravan::query()
->whereRelation('type', 'name', 'New')
->whereRelation('category', 'name', ucwords(strtolower($category)))
->orderBy($orderBy, $order)
->get();
Otherwise, you can use the eloquent whereHas() method to achieve the same result.
Caravan::query()
->whereHas('type', fn (Builder $query) => $query->where('name', 'New'))
->whereHas('category', fn (Builder $query) => $query->where('name', ucwords(strtolower($category))))
->orderBy($orderBy, $order)
->get();
Looking at your model relations I think your relations should be one to many instead of one to one. If so your relations should be:
public function type()
{
return $this->belongsTo(Type::class);
}
public function category()
{
return $this->belongsTo(Category::class);
}
Related
My Entity(MealSet) has a file association so I have created a custom operation to process the request. My custom operation(MealSetController::class) attempts to denormalize the entity and the returns it. However, because my entity has a relationship, the denormalization fails and throws an error Nested documents for attribute \u0022mealSetIncludes\u0022 are not allowed. Use IRIs instead..
How would one denormalize an entity that has relationships from within a custom operation?
// MealSet entity
namespace App\Entity;
use App\Entity\MealAudienceCategory;
use ApiPlatform\Core\Annotation\ApiResource;
use App\Controller\MealSetController;
use App\Repository\MealSetRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Symfony\Component\Serializer\Annotation\Groups;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\HttpFoundation\File\File;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
/**
* #ApiResource(
* itemOperations={
* "get",
* "put"={
* "method"="POST",
* "path" = "/meal-sets/{id}",
* "controller" = MealSetController::class,
* "deserialize" = false
* },
* collectionOperations = {
* "get",
* "post" = {
* "security"="is_granted('CREATE_MENUAUDIENCE')",
* "method"="POST",
* "controller" = MealSetController::class,
* "deserialize" = false,
* }
* }
*)
* #ORM\Entity(repositoryClass=MealSetRepository::class)
* #UniqueEntity(
* fields={"name", "mealAudienceCategory"},
* message="The Meal Set name {{ value }} is already in use."
*)
* #Vich\Uploadable
*/
class MealSet
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=45)
* #Groups({
* "mealset:read",
* "mealset:write",
* "mealaudiencecategory:read",
*})
* #Assert\NotBlank
* #Assert\Length(
* min = 2,
* max = 45,
* minMessage = "Name must be at least {{ limit }} characters long",
* maxMessage = "Name cannot be longer than {{ limit }} characters",
* )
*/
private $name;
/**
* #ORM\Column(type="string", length=255)
* #Groups({
* "mealset:read",
* "mealset:write",
* "mealaudiencecategory:read",
*})
* #Assert\NotBlank
* #Assert\Length(
* min = 2,
* max = 255,
* minMessage = "Description must be at least {{ limit }} characters long",
* maxMessage = "Description cannot be longer than {{ limit }} characters",
* )
*/
private $description;
/**
* #ORM\Column(type="boolean")
* #Groups({
* "mealset:read",
* "mealset:write",
* "mealaudiencecategory:read",
*})
* #Assert\Type(
* type="boolean",
* message="The value {{ value }} is not a valid {{ type }}."
* )
*/
private $published;
/**
* #ORM\Column(type="integer")
* #Groups({
* "mealset:read",
* "mealset:write"
*})
* #Assert\Type(
* type="integer",
* message="The value {{ value }} is not a valid {{ type }}."
* )
*/
private $displayOrder;
/**
* #var MealAudienceCategory
* #ORM\ManyToOne(targetEntity=MealAudienceCategory::class, inversedBy="mealSets")
* #ORM\JoinColumn(nullable=false)
* #Groups({
* "mealset:read",
* "mealset:write"
*})
*/
private $mealAudienceCategory;
/**
* #ORM\OneToMany(targetEntity=MealSetIncludes::class, mappedBy="mealSet", cascade={"persist", "remove"}, orphanRemoval=true)
* #Groups({
* "mealset:read",
* "mealset:write"
*})
*/
private $mealSetIncludes;
/**
* #ORM\OneToMany(targetEntity=MealSetGroup::class, mappedBy="mealSet", orphanRemoval=true)
* #Groups({
* "mealset:read",
* "mealset:write"
*})
*/
private $mealSetGroups;
/**
* #Groups({
* "menuaudience:read",
*})
*/
public $contentUrl;
/**
* #Vich\UploadableField(mapping="media_object", fileNameProperty="filePath")
* #Groups({
* "menuaudience:write",
*})
*/
public $file = null;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
private $filePath;
/**
* #ORM\Column(type="datetime_immutable")
*/
private $updatedAt;
public function __construct()
{
$this->mealSetSection = new ArrayCollection();
$this->mealSetIncludes = new ArrayCollection();
$this->mealSetGroups = new ArrayCollection();
$this->setUpdatedAt(new \DateTimeImmutable());
}
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getDescription(): ?string
{
return $this->description;
}
public function setDescription(string $description): self
{
$this->description = $description;
return $this;
}
public function getPublished(): ?bool
{
return $this->published;
}
public function setPublished(bool $published): self
{
$this->published = $published;
return $this;
}
public function getDisplayOrder(): ?int
{
return $this->displayOrder;
}
public function setDisplayOrder(int $displayOrder): self
{
$this->displayOrder = $displayOrder;
return $this;
}
public function getMealAudienceCategory(): ?MealAudienceCategory
{
return $this->mealAudienceCategory;
}
public function setMealAudienceCategory(?MealAudienceCategory $mealAudienceCategory): self
{
$this->mealAudienceCategory = $mealAudienceCategory;
return $this;
}
/**
* #return Collection|MealSetIncludes[]
* #Assert\Valid()
*/
public function getMealSetIncludes(): Collection
{
return $this->mealSetIncludes;
}
public function addMealSetInclude(MealSetIncludes $mealSetInclude): self
{
if (!$this->mealSetIncludes->contains($mealSetInclude)) {
$this->mealSetIncludes[] = $mealSetInclude;
$mealSetInclude->setMealSet($this);
}
return $this;
}
public function removeMealSetInclude(MealSetIncludes $mealSetInclude): self
{
if ($this->mealSetIncludes->contains($mealSetInclude)) {
$this->mealSetIncludes->removeElement($mealSetInclude);
// set the owning side to null (unless already changed)
if ($mealSetInclude->getMealSet() === $this) {
$mealSetInclude->setMealSet(null);
}
}
return $this;
}
/**
* #return Collection|MealSetGroup[]
*/
public function getMealSetGroups(): Collection
{
return $this->mealSetGroups;
}
public function addMealSetGroup(MealSetGroup $mealSetGroup): self
{
if (!$this->mealSetGroups->contains($mealSetGroup)) {
$this->mealSetGroups[] = $mealSetGroup;
$mealSetGroup->setMealSet($this);
}
return $this;
}
public function removeMealSetGroup(MealSetGroup $mealSetGroup): self
{
if ($this->mealSetGroups->removeElement($mealSetGroup)) {
// set the owning side to null (unless already changed)
if ($mealSetGroup->getMealSet() === $this) {
$mealSetGroup->setMealSet(null);
}
}
return $this;
}
public function getUpdatedAt(): ?\DateTimeImmutable
{
return $this->updatedAt;
}
public function setUpdatedAt(\DateTimeImmutable $updatedAt): self
{
$this->updatedAt = $updatedAt;
return $this;
}
public function getFilePath(): ?string
{
return $this->filePath;
}
public function getContentUrl(): ?string {
return $this->contentUrl;
}
public function setFilePath($filePath): self
{
$this->filePath = $filePath;
return $this;
}
}
class MealSetController extends AbstractController
{
public function __invoke($slug = '', RequestStack $requestStack, MealSetRepository $em): MealSet
{
/*
Determine if they are trying to edit an entity or create an entity.
If edit, find the entity and use that object.
*/
if($slug) {
$obj = $em->findOneBySlug($slug);
if(!$obj)
throw new BadRequestHttpException('Cannot find MealSet where SLUG ='.$slug);
} else {
$obj = new MealSet();
}
$serializer = $this->get("serializer");
$request = $requestStack->getCurrentRequest();
$data = array_filter($request->request->all(), function($x) { return ($x) ? true : false; }); //Grab the post data and filter out any empty strings.
$extractors = new PropertyInfoExtractor([], [new PhpDocExtractor(), new ReflectionExtractor()]);
(new ObjectNormalizer(null, null, null, $extractors))->denormalize($data, MenuAudience::class, 'json', [
AbstractNormalizer::OBJECT_TO_POPULATE => $obj,
AbstractObjectNormalizer::SKIP_NULL_VALUES => true,
ObjectNormalizer::DISABLE_TYPE_ENFORCEMENT => true
]);
$uploadedFile = $request->files->get('file');
if($uploadedFile)
$obj->setFile($uploadedFile);
return $obj;
}
}
Frontend Product images are serving from this path1 :
media/catalog/product/cache/1/image/9df78eab33525d08d6e5fb8d27136e95/i/m/img24.jpg
Backend Product images are serving from this path2
media/catalog/product/i/m/img24.jpg
why same images stored in different path.
I think Backend images are serving from proper path, I want frontend images also should serve from same path.
so we followed link & added following code in below file, but after that our site did't load any images.:
app/code/core/Mage/Catalog/Helper/Image.php
echo Mage::getModel('catalog/product_media_config')->getMediaUrl( $_product->getSmallImage());
full code :
<?php
class Mage_Catalog_Helper_Image extends Mage_Core_Helper_Abstract
{
/**
* Current model
*
* #var Mage_Catalog_Model_Product_Image
*/
protected $_model;
/**
* Scheduled for resize image
*
* #var bool
*/
protected $_scheduleResize = false;
/**
* Scheduled for rotate image
*
* #var bool
*/
protected $_scheduleRotate = false;
/**
* Angle
*
* #var int
*/
protected $_angle;
/**
* Watermark file name
*
* #var string
*/
protected $_watermark;
/**
* Watermark Position
*
* #var string
*/
protected $_watermarkPosition;
/**
* Watermark Size
*
* #var string
*/
protected $_watermarkSize;
/**
* Watermark Image opacity
*
* #var int
*/
protected $_watermarkImageOpacity;
/**
* Current Product
*
* #var Mage_Catalog_Model_Product
*/
protected $_product;
/**
* Image File
*
* #var string
*/
protected $_imageFile;
/**
* Image Placeholder
*
* #var string
*/
protected $_placeholder;
/**
* Reset all previous data
*
* #return Mage_Catalog_Helper_Image
*/
protected function _reset()
{
$this->_model = null;
$this->_scheduleResize = false;
$this->_scheduleRotate = false;
$this->_angle = null;
$this->_watermark = null;
$this->_watermarkPosition = null;
$this->_watermarkSize = null;
$this->_watermarkImageOpacity = null;
$this->_product = null;
$this->_imageFile = null;
return $this;
}
/**
* Initialize Helper to work with Image
*
* #param Mage_Catalog_Model_Product $product
* #param string $attributeName
* #param mixed $imageFile
* #return Mage_Catalog_Helper_Image
*/
public function init(Mage_Catalog_Model_Product $product, $attributeName, $imageFile=null)
{
$this->_reset();
$this->_setModel(Mage::getModel('catalog/product_image'));
$this->_getModel()->setDestinationSubdir($attributeName);
$this->setProduct($product);
$this->setWatermark(
Mage::getStoreConfig("design/watermark/{$this->_getModel()->getDestinationSubdir()}_image")
);
$this->setWatermarkImageOpacity(
Mage::getStoreConfig("design/watermark/{$this->_getModel()->getDestinationSubdir()}_imageOpacity")
);
$this->setWatermarkPosition(
Mage::getStoreConfig("design/watermark/{$this->_getModel()->getDestinationSubdir()}_position")
);
$this->setWatermarkSize(
Mage::getStoreConfig("design/watermark/{$this->_getModel()->getDestinationSubdir()}_size")
);
if ($imageFile) {
$this->setImageFile($imageFile);
} else {
// add for work original size
$this->_getModel()->setBaseFile($this->getProduct()->getData($this->_getModel()->getDestinationSubdir()));
}
return $this;
}
/**
* Schedule resize of the image
* $width *or* $height can be null - in this case, lacking dimension will be calculated.
*
* #see Mage_Catalog_Model_Product_Image
* #param int $width
* #param int $height
* #return Mage_Catalog_Helper_Image
*/
public function resize($width, $height = null)
{
$this->_getModel()->setWidth($width)->setHeight($height);
$this->_scheduleResize = true;
return $this;
}
/**
* Set image quality, values in percentage from 0 to 100
*
* #param int $quality
* #return Mage_Catalog_Helper_Image
*/
public function setQuality($quality)
{
$this->_getModel()->setQuality($quality);
return $this;
}
/**
* Guarantee, that image picture width/height will not be distorted.
* Applicable before calling resize()
* It is true by default.
*
* #see Mage_Catalog_Model_Product_Image
* #param bool $flag
* #return Mage_Catalog_Helper_Image
*/
public function keepAspectRatio($flag)
{
$this->_getModel()->setKeepAspectRatio($flag);
return $this;
}
/**
* Guarantee, that image will have dimensions, set in $width/$height
* Applicable before calling resize()
* Not applicable, if keepAspectRatio(false)
*
* $position - TODO, not used for now - picture position inside the frame.
*
* #see Mage_Catalog_Model_Product_Image
* #param bool $flag
* #param array $position
* #return Mage_Catalog_Helper_Image
*/
public function keepFrame($flag, $position = array('center', 'middle'))
{
$this->_getModel()->setKeepFrame($flag);
return $this;
}
/**
* Guarantee, that image will not lose transparency if any.
* Applicable before calling resize()
* It is true by default.
*
* $alphaOpacity - TODO, not used for now
*
* #see Mage_Catalog_Model_Product_Image
* #param bool $flag
* #param int $alphaOpacity
* #return Mage_Catalog_Helper_Image
*/
public function keepTransparency($flag, $alphaOpacity = null)
{
$this->_getModel()->setKeepTransparency($flag);
return $this;
}
/**
* Guarantee, that image picture will not be bigger, than it was.
* Applicable before calling resize()
* It is false by default
*
* #param bool $flag
* #return Mage_Catalog_Helper_Image
*/
public function constrainOnly($flag)
{
$this->_getModel()->setConstrainOnly($flag);
return $this;
}
/**
* Set color to fill image frame with.
* Applicable before calling resize()
* The keepTransparency(true) overrides this (if image has transparent color)
* It is white by default.
*
* #see Mage_Catalog_Model_Product_Image
* #param array $colorRGB
* #return Mage_Catalog_Helper_Image
*/
public function backgroundColor($colorRGB)
{
// assume that 3 params were given instead of array
if (!is_array($colorRGB)) {
$colorRGB = func_get_args();
}
$this->_getModel()->setBackgroundColor($colorRGB);
return $this;
}
/**
* Rotate image into specified angle
*
* #param int $angle
* #return Mage_Catalog_Helper_Image
*/
public function rotate($angle)
{
$this->setAngle($angle);
$this->_getModel()->setAngle($angle);
$this->_scheduleRotate = true;
return $this;
}
/**
* Add watermark to image
* size param in format 100x200
*
* #param string $fileName
* #param string $position
* #param string $size
* #param int $imageOpacity
* #return Mage_Catalog_Helper_Image
*/
public function watermark($fileName, $position, $size=null, $imageOpacity=null)
{
$this->setWatermark($fileName)
->setWatermarkPosition($position)
->setWatermarkSize($size)
->setWatermarkImageOpacity($imageOpacity);
return $this;
}
/**
* Set placeholder
*
* #param string $fileName
* #return void
*/
public function placeholder($fileName)
{
$this->_placeholder = $fileName;
}
/**
* Get Placeholder
*
* #return string
*/
public function getPlaceholder()
{
if (!$this->_placeholder) {
$attr = $this->_getModel()->getDestinationSubdir();
$this->_placeholder = 'images/catalog/product/placeholder/'.$attr.'.jpg';
}
return $this->_placeholder;
}
/**
* Return Image URL
*
* #return string
*/
public function __toString()
{
try {
$model = $this->_getModel();
if ($this->getImageFile()) {
$model->setBaseFile($this->getImageFile());
} else {
$model->setBaseFile($this->getProduct()->getData($model->getDestinationSubdir()));
}
if ($model->isCached()) {
return $model->getUrl();
} else {
if ($this->_scheduleRotate) {
$model->rotate($this->getAngle());
}
if ($this->_scheduleResize) {
$model->resize();
}
if ($this->getWatermark()) {
$model->setWatermark($this->getWatermark());
}
$url = $model->saveFile()->getUrl();
}
} catch (Exception $e) {
$url = Mage::getDesign()->getSkinUrl($this->getPlaceholder());
}
return $url;
}
/**
* Set current Image model
*
* #param Mage_Catalog_Model_Product_Image $model
* #return Mage_Catalog_Helper_Image
*/
protected function _setModel($model)
{
$this->_model = $model;
return $this;
}
/**
* Get current Image model
*
* #return Mage_Catalog_Model_Product_Image
*/
protected function _getModel()
{
return $this->_model;
}
/**
* Set Rotation Angle
*
* #param int $angle
* #return Mage_Catalog_Helper_Image
*/
protected function setAngle($angle)
{
$this->_angle = $angle;
return $this;
}
/**
* Get Rotation Angle
*
* #return int
*/
protected function getAngle()
{
return $this->_angle;
}
/**
* Set watermark file name
*
* #param string $watermark
* #return Mage_Catalog_Helper_Image
*/
protected function setWatermark($watermark)
{
$this->_watermark = $watermark;
$this->_getModel()->setWatermarkFile($watermark);
return $this;
}
/**
* Get watermark file name
*
* #return string
*/
protected function getWatermark()
{
return $this->_watermark;
}
/**
* Set watermark position
*
* #param string $position
* #return Mage_Catalog_Helper_Image
*/
protected function setWatermarkPosition($position)
{
$this->_watermarkPosition = $position;
$this->_getModel()->setWatermarkPosition($position);
return $this;
}
/**
* Get watermark position
*
* #return string
*/
protected function getWatermarkPosition()
{
return $this->_watermarkPosition;
}
/**
* Set watermark size
* param size in format 100x200
*
* #param string $size
* #return Mage_Catalog_Helper_Image
*/
public function setWatermarkSize($size)
{
$this->_watermarkSize = $size;
$this->_getModel()->setWatermarkSize($this->parseSize($size));
return $this;
}
/**
* Get watermark size
*
* #return string
*/
protected function getWatermarkSize()
{
return $this->_watermarkSize;
}
/**
* Set watermark image opacity
*
* #param int $imageOpacity
* #return Mage_Catalog_Helper_Image
*/
public function setWatermarkImageOpacity($imageOpacity)
{
$this->_watermarkImageOpacity = $imageOpacity;
$this->_getModel()->setWatermarkImageOpacity($imageOpacity);
return $this;
}
/**
* Get watermark image opacity
*
* #return int
*/
protected function getWatermarkImageOpacity()
{
if ($this->_watermarkImageOpacity) {
return $this->_watermarkImageOpacity;
}
return $this->_getModel()->getWatermarkImageOpacity();
}
/**
* Set current Product
*
* #param Mage_Catalog_Model_Product $product
* #return Mage_Catalog_Helper_Image
*/
protected function setProduct($product)
{
$this->_product = $product;
return $this;
}
/**
* Get current Product
*
* #return Mage_Catalog_Model_Product
*/
protected function getProduct()
{
return $this->_product;
}
/**
* Set Image file
*
* #param string $file
* #return Mage_Catalog_Helper_Image
*/
protected function setImageFile($file)
{
$this->_imageFile = $file;
return $this;
}
/**
* Get Image file
*
* #return string
*/
protected function getImageFile()
{
return $this->_imageFile;
}
/**
* Retrieve size from string
*
* #param string $string
* #return array|bool
*/
protected function parseSize($string)
{
$size = explode('x', strtolower($string));
if (sizeof($size) == 2) {
return array(
'width' => ($size[0] > 0) ? $size[0] : null,
'heigth' => ($size[1] > 0) ? $size[1] : null,
);
}
return false;
}
/**
* Retrieve original image width
*
* #return int|null
*/
public function getOriginalWidth()
{
return $this->_getModel()->getImageProcessor()->getOriginalWidth();
}
/**
* Retrieve original image height
*
* #deprecated
* #return int|null
*/
public function getOriginalHeigh()
{
return $this->getOriginalHeight();
}
/**
* Retrieve original image height
*
* #return int|null
*/
public function getOriginalHeight()
{
return $this->_getModel()->getImageProcessor()->getOriginalHeight();
}
/**
* Retrieve Original image size as array
* 0 - width, 1 - height
*
* #return array
*/
public function getOriginalSizeArray()
{
return array(
$this->getOriginalWidth(),
$this->getOriginalHeight()
);
}
/**
* Check - is this file an image
*
* #param string $filePath
* #return bool
* #throws Mage_Core_Exception
*/
public function validateUploadFile($filePath) {
if (!getimagesize($filePath)) {
Mage::throwException($this->__('Disallowed file type.'));
}
$_processor = new Varien_Image($filePath);
return $_processor->getMimeType() !== null;
}
echo Mage::getModel('catalog/product_media_config')->getMediaUrl( $_product->getSmallImage());
}
In frontend all product image come from cache due to increase speed.
In backend Magento not consider speed so it come from real image path.
You can not written any code out side of method because Magento is fully object oriented.
You can use below code for fetch image full url.
echo $imageUrl = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_MEDIA) . 'catalog/product' . $_product->getImage();
I have a contestEntry entity.
It has a number of properties (player Positions) all linking to a fantasyPlayer entity.
On submission of a form i need to check that the different player positions are unique (ie a player has not been put in 2 positions)
Is it possible to use validations for this, as far i can see i can only apply a validation to a property, is there a way to apply validations across the whole entity?
ContestEntry:
<?php
namespace FantasyPro\GameBundle\Entity;
use Doctrine\ORM\Mapping AS ORM;
use FantasyPro\DataBundle\Entity\DailyFantasyPlayer;
use FantasyPro\UserBundle\Entity\User;
/**
* #ORM\Entity(repositoryClass="FantasyPro\GameBundle\Entity\ContestEntryRepository")
* #ORM\Table(name="fp_contestEntry")
*/
class ContestEntry
{
/**
* #ORM\Id
* #ORM\Column(type="integer", name="id")
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="boolean", nullable=true, name="locked")
*/
private $locked;
/**
* #ORM\ManyToOne(targetEntity="FantasyPro\UserBundle\Entity\User", inversedBy="contestEntries")
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
private $user;
/**
* #ORM\ManyToOne(targetEntity="FantasyPro\DataBundle\Entity\DailyFantasyPlayer")
* #ORM\JoinColumn(name="qb", referencedColumnName="id")
*/
private $qb;
/**
* #ORM\ManyToOne(targetEntity="FantasyPro\DataBundle\Entity\DailyFantasyPlayer")
* #ORM\JoinColumn(name="wr1", referencedColumnName="id")
*/
private $wr1;
/**
* #ORM\ManyToOne(targetEntity="FantasyPro\DataBundle\Entity\DailyFantasyPlayer")
* #ORM\JoinColumn(name="wr2", referencedColumnName="id")
*/
private $wr2;
/**
* #ORM\ManyToOne(targetEntity="FantasyPro\DataBundle\Entity\DailyFantasyPlayer")
* #ORM\JoinColumn(name="rb1", referencedColumnName="id")
*/
private $rb1;
/**
* #ORM\ManyToOne(targetEntity="FantasyPro\DataBundle\Entity\DailyFantasyPlayer")
* #ORM\JoinColumn(name="rb2", referencedColumnName="id")
*/
private $rb2;
/**
* #ORM\ManyToOne(targetEntity="FantasyPro\DataBundle\Entity\DailyFantasyPlayer")
* #ORM\JoinColumn(name="te", referencedColumnName="id")
*/
private $te;
/**
* #ORM\ManyToOne(targetEntity="FantasyPro\DataBundle\Entity\DailyFantasyPlayer")
* #ORM\JoinColumn(name="k", referencedColumnName="id")
*/
private $k;
/**
* #ORM\ManyToOne(targetEntity="FantasyPro\DataBundle\Entity\DailyFantasyPlayer")
* #ORM\JoinColumn(name="flex", referencedColumnName="id")
*/
private $flex;
/**
* #ORM\ManyToOne(targetEntity="FantasyPro\DataBundle\Entity\DailyFantasyPlayer")
* #ORM\JoinColumn(name="def", referencedColumnName="id")
*/
private $def;
/**
* #ORM\ManyToOne(targetEntity="FantasyPro\GameBundle\Entity\Contest", inversedBy="contestEntries")
* #ORM\JoinColumn(name="contest", referencedColumnName="id")
*/
private $contest;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set locked
*
* #param boolean $locked
*
* #return ContestEntry
*/
public function setLocked($locked)
{
$this->locked = $locked;
return $this;
}
/**
* Get locked
*
* #return boolean
*/
public function getLocked()
{
return $this->locked;
}
/**
* Set user
*
* #param \FantasyPro\UserBundle\Entity\User $user
*
* #return ContestEntry
*/
public function setUser(User $user = null)
{
$this->user = $user;
return $this;
}
/**
* Get user
*
* #return \FantasyPro\UserBundle\Entity\User
*/
public function getUser()
{
return $this->user;
}
/**
* Set qb
*
* #param \FantasyPro\DataBundle\Entity\DailyFantasyPlayer $qb
*
* #return ContestEntry
*/
public function setQb(DailyFantasyPlayer $qb = null)
{
$this->qb = $qb;
return $this;
}
/**
* Get qb
*
* #return \FantasyPro\DataBundle\Entity\DailyFantasyPlayer
*/
public function getQb()
{
return $this->qb;
}
/**
* Set wr1
*
* #param \FantasyPro\DataBundle\Entity\DailyFantasyPlayer $wr1
*
* #return ContestEntry
*/
public function setWr1(DailyFantasyPlayer $wr1 = null)
{
$this->wr1 = $wr1;
return $this;
}
/**
* Get wr1
*
* #return \FantasyPro\DataBundle\Entity\DailyFantasyPlayer
*/
public function getWr1()
{
return $this->wr1;
}
/**
* Set wr2
*
* #param \FantasyPro\DataBundle\Entity\DailyFantasyPlayer $wr2
*
* #return ContestEntry
*/
public function setWr2(DailyFantasyPlayer $wr2 = null)
{
$this->wr2 = $wr2;
return $this;
}
/**
* Get wr2
*
* #return \FantasyPro\DataBundle\Entity\DailyFantasyPlayer
*/
public function getWr2()
{
return $this->wr2;
}
/**
* Set rb1
*
* #param \FantasyPro\DataBundle\Entity\DailyFantasyPlayer $rb1
*
* #return ContestEntry
*/
public function setRb1(DailyFantasyPlayer $rb1 = null)
{
$this->rb1 = $rb1;
return $this;
}
/**
* Get rb1
*
* #return \FantasyPro\DataBundle\Entity\DailyFantasyPlayer
*/
public function getRb1()
{
return $this->rb1;
}
/**
* Set rb2
*
* #param \FantasyPro\DataBundle\Entity\DailyFantasyPlayer $rb2
*
* #return ContestEntry
*/
public function setRb2(DailyFantasyPlayer $rb2 = null)
{
$this->rb2 = $rb2;
return $this;
}
/**
* Get rb2
*
* #return \FantasyPro\DataBundle\Entity\DailyFantasyPlayer
*/
public function getRb2()
{
return $this->rb2;
}
/**
* Set te
*
* #param \FantasyPro\DataBundle\Entity\DailyFantasyPlayer $te
*
* #return ContestEntry
*/
public function setTe(DailyFantasyPlayer $te = null)
{
$this->te = $te;
return $this;
}
/**
* Get te
*
* #return \FantasyPro\DataBundle\Entity\DailyFantasyPlayer
*/
public function getTe()
{
return $this->te;
}
/**
* Set k
*
* #param \FantasyPro\DataBundle\Entity\DailyFantasyPlayer $k
*
* #return ContestEntry
*/
public function setK(DailyFantasyPlayer $k = null)
{
$this->k = $k;
return $this;
}
/**
* Get k
*
* #return \FantasyPro\DataBundle\Entity\DailyFantasyPlayer
*/
public function getK()
{
return $this->k;
}
/**
* Set flex
*
* #param \FantasyPro\DataBundle\Entity\DailyFantasyPlayer $flex
*
* #return ContestEntry
*/
public function setFlex(DailyFantasyPlayer $flex = null)
{
$this->flex = $flex;
return $this;
}
/**
* Get flex
*
* #return \FantasyPro\DataBundle\Entity\DailyFantasyPlayer
*/
public function getFlex()
{
return $this->flex;
}
/**
* Set def
*
* #param DailyFantasyPlayer $def
*
* #return ContestEntry
*/
public function setDef(DailyFantasyPlayer $def = null)
{
$this->def = $def;
return $this;
}
/**
* Get def
*
* #return \FantasyPro\DataBundle\Entity\DailyFantasyPlayer
*/
public function getDef()
{
return $this->def;
}
/**
* Set contest
*
* #param \FantasyPro\GameBundle\Entity\Contest $contest
*
* #return ContestEntry
*/
public function setContest(Contest $contest = null)
{
$this->contest = $contest;
return $this;
}
/**
* Get contest
*
* #return \FantasyPro\GameBundle\Entity\Contest
*/
public function getContest()
{
return $this->contest;
}
}
I have a contestHelper class containing various methods, one of them is to check that the selected fantasyPlayers are unique
/**
* Checks to see that the players selected for the squad are unique
* i.e no player/team has been selected twice
*
* #param ContestEntry $contestEntry
*
* #return bool
*/
public function squadPlayersAreUnique( ContestEntry $contestEntry )
{
//checks to see there are no duplicate players in the squad
$playerArray = array(
$contestEntry->getWr1()->getPlayer()->getId(),
$contestEntry->getWr2()->getPlayer()->getId(),
$contestEntry->getRb1()->getPlayer()->getId(),
$contestEntry->getRb2()->getPlayer()->getId(),
$contestEntry->getTe()->getPlayer()->getId(),
$contestEntry->getK()->getPlayer()->getId(),
$contestEntry->getFlex()->getPlayer()->getId(),
$contestEntry->getDef()->getTeam()->getPlayerID()
);
return count( $playerArray ) == count( array_unique( $playerArray ) );
}
My controller is very wrong as i have a call to squadPlayersAreUnique within my validation controller, and no way to redirect properly back to the page.
Is there a way to add this validation to the entire entity itself?
heres my controller in its current state:
/**
* Shows a form for Updating a contestEntry.
*
* #Route("/manageentry/{id}", name="update_contestentry")
* #Template("GameBundle:ContestEntry:update.html.twig")
* #param ContestEntry $contestEntry
* #ParamConverter("contestEntry", class="GameBundle:ContestEntry", options={"id" = "id"})
* #return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
*/
public function updateEntryAction( ContestEntry $contestEntry = null )
{
$session = new Session();
$session->start();
// add flash messages
if ( empty( $contestEntry)) {
//$session->getFlashBag()->add('error', 'Sorry, We could not find your contest entry!');
throw $this->createNotFoundException(
'Sorry, We could not find your contest entry!'
);
}
$request = Request::createFromGlobals();
$contestHelper = $this->get( 'contest_helper' );
$contest = $contestEntry->getContest();
$availablePlayers = $contestHelper->getPlayersforContestResult( $contest );
$form = $this->createForm( 'contestEntry', $contestEntry );
$form->handleRequest( $request );
if ($form->isValid()) {
//check there are no duplicate players
if( !$contestHelper->squadPlayersAreUnique( $contestEntry ) ){
//throw new HttpException(500, 'Duplicate players found in your squad!');
$session->getFlashBag()->add('error', 'Duplicate players found in your squad, Please check your entry and try again!');
}
if( !$contestHelper->entryNotOverBudget( $contestEntry) ){
// throw new HttpException(500, 'Not Enough funds to draft selected players!');
$session->getFlashBag()->add('error', 'Not Enough funds to draft selected players, Please check your entry and try again!');
};
$em = $this->getDoctrine()->getManager();
$em->persist( $contestEntry );
$em->flush();
$this->addFlash(
'success',
'Contest Entry Updated!!'
);
return $this->redirect( $this->generateUrl( 'list_contestentries' ) );
}
return array(
'contestEntry' => $contestEntry,
'contestForm' => $form->createView(),
'contest' => $contest,
'playerList' => $availablePlayers
);
}
you can add the callback validator on entity level:
http://symfony.com/doc/current/reference/constraints/Callback.html
I had installed an custom extension. Its running successfully and had all files at its place. But I am getting this error on my listing page
Fatal error: Call to a member function setFinalPrice() on a non-object in /var/zpanel/hostdata/zadmin/public_html/unisport_com/app/code/core/Mage/Sales/Model/Quote/Item/Abstract.php on line 89.
I google this error but did'nt found any proper solution. One solution is to copy the original Abstract.php file may be because extension had overwrite this file. But I checked the code from the backup its the same and also copied original file but nothing worked for me.
What is wrong with this file? Can anybody help?
below is the code of Abstract.php file:
<?php
/**
* Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license#magentocommerce.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade Magento to newer
* versions in the future. If you wish to customize Magento for your
* needs please refer to http://www.magentocommerce.com for more information.
*
* #category Mage
* #package Mage_Sales
* #copyright Copyright (c) 2013 Magento Inc. (http://www.magentocommerce.com)
* #license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
/**
* Quote item abstract model
*
* Price attributes:
* - price - initial item price, declared during product association
* - original_price - product price before any calculations
* - calculation_price - prices for item totals calculation
* - custom_price - new price that can be declared by user and recalculated during calculation process
* - original_custom_price - original defined value of custom price without any convertion
*
* #category Mage
* #package Mage_Sales
* #author Magento Core Team <core#magentocommerce.com>
*/
abstract class Mage_Sales_Model_Quote_Item_Abstract extends Mage_Core_Model_Abstract
implements Mage_Catalog_Model_Product_Configuration_Item_Interface
{
/**
* Parent item for sub items for bundle product, configurable product, etc.
*
* #var Mage_Sales_Model_Quote_Item_Abstract
*/
protected $_parentItem = null;
/**
* Children items in bundle product, configurable product, etc.
*
* #var array
*/
protected $_children = array();
/**
*
* #var array
*/
protected $_messages = array();
/**
* Retrieve Quote instance
*
* #return Mage_Sales_Model_Quote
*/
abstract function getQuote();
/**
* Retrieve product model object associated with item
*
* #return Mage_Catalog_Model_Product
*/
public function getProduct()
{
$product = $this->_getData('product');
if ($product === null && $this->getProductId()) {
$product = Mage::getModel('catalog/product')
->setStoreId($this->getQuote()->getStoreId())
->load($this->getProductId());
$this->setProduct($product);
}
/**
* Reset product final price because it related to custom options
*/
$product->setFinalPrice(null);
if (is_array($this->_optionsByCode)) {
$product->setCustomOptions($this->_optionsByCode);
}
return $product;
}
/**
* Returns special download params (if needed) for custom option with type = 'file'
* Needed to implement Mage_Catalog_Model_Product_Configuration_Item_Interface.
* Return null, as quote item needs no additional configuration.
*
* #return null|Varien_Object
*/
public function getFileDownloadParams()
{
return null;
}
/**
* Specify parent item id before saving data
*
* #return Mage_Sales_Model_Quote_Item_Abstract
*/
protected function _beforeSave()
{
parent::_beforeSave();
if ($this->getParentItem()) {
$this->setParentItemId($this->getParentItem()->getId());
}
return $this;
}
/**
* Set parent item
*
* #param Mage_Sales_Model_Quote_Item $parentItem
* #return Mage_Sales_Model_Quote_Item
*/
public function setParentItem($parentItem)
{
if ($parentItem) {
$this->_parentItem = $parentItem;
$parentItem->addChild($this);
}
return $this;
}
/**
* Get parent item
*
* #return Mage_Sales_Model_Quote_Item
*/
public function getParentItem()
{
return $this->_parentItem;
}
/**
* Get chil items
*
* #return array
*/
public function getChildren()
{
return $this->_children;
}
/**
* Add child item
*
* #param Mage_Sales_Model_Quote_Item_Abstract $child
* #return Mage_Sales_Model_Quote_Item_Abstract
*/
public function addChild($child)
{
$this->setHasChildren(true);
$this->_children[] = $child;
return $this;
}
/**
* Adds message(s) for quote item. Duplicated messages are not added.
*
* #param mixed $messages
* #return Mage_Sales_Model_Quote_Item_Abstract
*/
public function setMessage($messages)
{
$messagesExists = $this->getMessage(false);
if (!is_array($messages)) {
$messages = array($messages);
}
foreach ($messages as $message) {
if (!in_array($message, $messagesExists)) {
$this->addMessage($message);
}
}
return $this;
}
/**
* Add message of quote item to array of messages
*
* #param string $message
* #return Mage_Sales_Model_Quote_Item_Abstract
*/
public function addMessage($message)
{
$this->_messages[] = $message;
return $this;
}
/**
* Get messages array of quote item
*
* #param bool $string flag for converting messages to string
* #return array|string
*/
public function getMessage($string = true)
{
if ($string) {
return join("\n", $this->_messages);
}
return $this->_messages;
}
/**
* Removes message by text
*
* #param string $text
* #return Mage_Sales_Model_Quote_Item_Abstract
*/
public function removeMessageByText($text)
{
foreach ($this->_messages as $key => $message) {
if ($message == $text) {
unset($this->_messages[$key]);
}
}
return $this;
}
/**
* Clears all messages
*
* #return Mage_Sales_Model_Quote_Item_Abstract
*/
public function clearMessage()
{
$this->unsMessage(); // For older compatibility, when we kept message inside data array
$this->_messages = array();
return $this;
}
/**
* Retrieve store model object
*
* #return Mage_Core_Model_Store
*/
public function getStore()
{
return $this->getQuote()->getStore();
}
/**
* Checking item data
*
* #return Mage_Sales_Model_Quote_Item_Abstract
*/
public function checkData()
{
$this->setHasError(false);
$this->clearMessage();
$qty = $this->_getData('qty');
try {
$this->setQty($qty);
} catch (Mage_Core_Exception $e) {
$this->setHasError(true);
$this->setMessage($e->getMessage());
} catch (Exception $e) {
$this->setHasError(true);
$this->setMessage(Mage::helper('sales')->__('Item qty declaration error.'));
}
try {
$this->getProduct()->getTypeInstance(true)->checkProductBuyState($this->getProduct());
} catch (Mage_Core_Exception $e) {
$this->setHasError(true)
->setMessage($e->getMessage());
$this->getQuote()->setHasError(true)
->addMessage(Mage::helper('sales')->__('Some of the products below do not have all the required options.'));
} catch (Exception $e) {
$this->setHasError(true)
->setMessage(Mage::helper('sales')->__('Item options declaration error.'));
$this->getQuote()->setHasError(true)
->addMessage(Mage::helper('sales')->__('Items options declaration error.'));
}
if ($this->getProduct()->getHasError()) {
$this->setHasError(true)
->setMessage(Mage::helper('sales')->__('Some of the selected options are not currently available.'));
$this->getQuote()->setHasError(true)
->addMessage($this->getProduct()->getMessage(), 'options');
}
if ($this->getHasConfigurationUnavailableError()) {
$this->setHasError(true)
->setMessage(Mage::helper('sales')->__('Selected option(s) or their combination is not currently available.'));
$this->getQuote()->setHasError(true)
->addMessage(Mage::helper('sales')->__('Some item options or their combination are not currently available.'), 'unavailable-configuration');
$this->unsHasConfigurationUnavailableError();
}
return $this;
}
/**
* Get original (not related with parent item) item quantity
*
* #return int|float
*/
public function getQty()
{
return $this->_getData('qty');
}
/**
* Get total item quantity (include parent item relation)
*
* #return int|float
*/
public function getTotalQty()
{
if ($this->getParentItem()) {
return $this->getQty()*$this->getParentItem()->getQty();
}
return $this->getQty();
}
/**
* Calculate item row total price
*
* #return Mage_Sales_Model_Quote_Item
*/
public function calcRowTotal()
{
$qty = $this->getTotalQty();
// Round unit price before multiplying to prevent losing 1 cent on subtotal
$total = $this->getStore()->roundPrice($this->getCalculationPriceOriginal()) * $qty;
$baseTotal = $this->getStore()->roundPrice($this->getBaseCalculationPriceOriginal()) * $qty;
$this->setRowTotal($this->getStore()->roundPrice($total));
$this->setBaseRowTotal($this->getStore()->roundPrice($baseTotal));
return $this;
}
/**
* Get item price used for quote calculation process.
* This method get custom price (if it is defined) or original product final price
*
* #return float
*/
public function getCalculationPrice()
{
$price = $this->_getData('calculation_price');
if (is_null($price)) {
if ($this->hasCustomPrice()) {
$price = $this->getCustomPrice();
} else {
$price = $this->getConvertedPrice();
}
$this->setData('calculation_price', $price);
}
return $price;
}
/**
* Get item price used for quote calculation process.
* This method get original custom price applied before tax calculation
*
* #return float
*/
public function getCalculationPriceOriginal()
{
$price = $this->_getData('calculation_price');
if (is_null($price)) {
if ($this->hasOriginalCustomPrice()) {
$price = $this->getOriginalCustomPrice();
} else {
$price = $this->getConvertedPrice();
}
$this->setData('calculation_price', $price);
}
return $price;
}
/**
* Get calculation price used for quote calculation in base currency.
*
* #return float
*/
public function getBaseCalculationPrice()
{
if (!$this->hasBaseCalculationPrice()) {
if ($this->hasCustomPrice()) {
$price = (float) $this->getCustomPrice();
if ($price) {
$rate = $this->getStore()->convertPrice($price) / $price;
$price = $price / $rate;
}
} else {
$price = $this->getPrice();
}
$this->setBaseCalculationPrice($price);
}
return $this->_getData('base_calculation_price');
}
/**
* Get original calculation price used for quote calculation in base currency.
*
* #return float
*/
public function getBaseCalculationPriceOriginal()
{
if (!$this->hasBaseCalculationPrice()) {
if ($this->hasOriginalCustomPrice()) {
$price = (float) $this->getOriginalCustomPrice();
if ($price) {
$rate = $this->getStore()->convertPrice($price) / $price;
$price = $price / $rate;
}
} else {
$price = $this->getPrice();
}
$this->setBaseCalculationPrice($price);
}
return $this->_getData('base_calculation_price');
}
/**
* Get whether the item is nominal
* TODO: fix for multishipping checkout
*
* #return bool
*/
public function isNominal()
{
if (!$this->hasData('is_nominal')) {
$this->setData('is_nominal', $this->getProduct() ? '1' == $this->getProduct()->getIsRecurring() : false);
}
return $this->_getData('is_nominal');
}
/**
* Data getter for 'is_nominal'
* Used for converting item to order item
*
* #return int
*/
public function getIsNominal()
{
return (int)$this->isNominal();
}
/**
* Get original price (retrieved from product) for item.
* Original price value is in quote selected currency
*
* #return float
*/
public function getOriginalPrice()
{
$price = $this->_getData('original_price');
if (is_null($price)) {
$price = $this->getStore()->convertPrice($this->getBaseOriginalPrice());
$this->setData('original_price', $price);
}
return $price;
}
/**
* Set original price to item (calculation price will be refreshed too)
*
* #param float $price
* #return Mage_Sales_Model_Quote_Item_Abstract
*/
public function setOriginalPrice($price)
{
return $this->setData('original_price', $price);
}
/**
* Get Original item price (got from product) in base website currency
*
* #return float
*/
public function getBaseOriginalPrice()
{
return $this->_getData('base_original_price');
}
/**
* Specify custom item price (used in case whe we have apply not product price to item)
*
* #param float $value
* #return Mage_Sales_Model_Quote_Item_Abstract
*/
public function setCustomPrice($value)
{
$this->setCalculationPrice($value);
$this->setBaseCalculationPrice(null);
return $this->setData('custom_price', $value);
}
/**
* Get item price. Item price currency is website base currency.
*
* #return decimal
*/
public function getPrice()
{
return $this->_getData('price');
}
/**
* Specify item price (base calculation price and converted price will be refreshed too)
*
* #param float $value
* #return Mage_Sales_Model_Quote_Item_Abstract
*/
public function setPrice($value)
{
$this->setBaseCalculationPrice(null);
$this->setConvertedPrice(null);
return $this->setData('price', $value);
}
/**
* Get item price converted to quote currency
* #return float
*/
public function getConvertedPrice()
{
$price = $this->_getData('converted_price');
if (is_null($price)) {
$price = $this->getStore()->convertPrice($this->getPrice());
$this->setData('converted_price', $price);
}
return $price;
}
/**
* Set new value for converted price
* #param float $value
* #return Mage_Sales_Model_Quote_Item_Abstract
*/
public function setConvertedPrice($value)
{
$this->setCalculationPrice(null);
$this->setData('converted_price', $value);
return $this;
}
/**
* Clone quote item
*
* #return Mage_Sales_Model_Quote_Item
*/
public function __clone()
{
$this->setId(null);
$this->_parentItem = null;
$this->_children = array();
$this->_messages = array();
return $this;
}
/**
* Checking if there children calculated or parent item
* when we have parent quote item and its children
*
* #return bool
*/
public function isChildrenCalculated()
{
if ($this->getParentItem()) {
$calculate = $this->getParentItem()->getProduct()->getPriceType();
} else {
$calculate = $this->getProduct()->getPriceType();
}
if ((null !== $calculate) && (int)$calculate === Mage_Catalog_Model_Product_Type_Abstract::CALCULATE_CHILD) {
return true;
}
return false;
}
/**
* Checking can we ship product separatelly (each child separately)
* or each parent product item can be shipped only like one item
*
* #return bool
*/
public function isShipSeparately()
{
if ($this->getParentItem()) {
$shipmentType = $this->getParentItem()->getProduct()->getShipmentType();
} else {
$shipmentType = $this->getProduct()->getShipmentType();
}
if ((null !== $shipmentType) &&
(int)$shipmentType === Mage_Catalog_Model_Product_Type_Abstract::SHIPMENT_SEPARATELY) {
return true;
}
return false;
}
/**
* Calculate item tax amount
*
* #deprecated logic moved to tax totals calculation model
* #return Mage_Sales_Model_Quote_Item
*/
public function calcTaxAmount()
{
$store = $this->getStore();
if (!Mage::helper('tax')->priceIncludesTax($store)) {
if (Mage::helper('tax')->applyTaxAfterDiscount($store)) {
$rowTotal = $this->getRowTotalWithDiscount();
$rowBaseTotal = $this->getBaseRowTotalWithDiscount();
} else {
$rowTotal = $this->getRowTotal();
$rowBaseTotal = $this->getBaseRowTotal();
}
$taxPercent = $this->getTaxPercent()/100;
$this->setTaxAmount($store->roundPrice($rowTotal * $taxPercent));
$this->setBaseTaxAmount($store->roundPrice($rowBaseTotal * $taxPercent));
$rowTotal = $this->getRowTotal();
$rowBaseTotal = $this->getBaseRowTotal();
$this->setTaxBeforeDiscount($store->roundPrice($rowTotal * $taxPercent));
$this->setBaseTaxBeforeDiscount($store->roundPrice($rowBaseTotal * $taxPercent));
} else {
if (Mage::helper('tax')->applyTaxAfterDiscount($store)) {
$totalBaseTax = $this->getBaseTaxAmount();
$totalTax = $this->getTaxAmount();
if ($totalTax && $totalBaseTax) {
$totalTax -= $this->getDiscountAmount() * ($this->getTaxPercent() / 100);
$totalBaseTax -= $this->getBaseDiscountAmount() * ($this->getTaxPercent() / 100);
$this->setBaseTaxAmount($store->roundPrice($totalBaseTax));
$this->setTaxAmount($store->roundPrice($totalTax));
}
}
}
if (Mage::helper('tax')->discountTax($store) && !Mage::helper('tax')->applyTaxAfterDiscount($store)) {
if ($this->getDiscountPercent()) {
$baseTaxAmount = $this->getBaseTaxBeforeDiscount();
$taxAmount = $this->getTaxBeforeDiscount();
$baseDiscountDisposition = $baseTaxAmount/100*$this->getDiscountPercent();
$discountDisposition = $taxAmount/100*$this->getDiscountPercent();
$this->setDiscountAmount($this->getDiscountAmount()+$discountDisposition);
$this->setBaseDiscountAmount($this->getBaseDiscountAmount()+$baseDiscountDisposition);
}
}
return $this;
}
/**
* Get item tax amount
*
* #deprecated
* #return decimal
*/
public function getTaxAmount()
{
return $this->_getData('tax_amount');
}
/**
* Get item base tax amount
*
* #deprecated
* #return decimal
*/
public function getBaseTaxAmount()
{
return $this->_getData('base_tax_amount');
}
/**
* Get item price (item price always exclude price)
*
* #deprecated
* #return decimal
*/
protected function _calculatePrice($value, $saveTaxes = true)
{
$store = $this->getQuote()->getStore();
if (Mage::helper('tax')->priceIncludesTax($store)) {
$bAddress = $this->getQuote()->getBillingAddress();
$sAddress = $this->getQuote()->getShippingAddress();
$address = $this->getAddress();
if ($address) {
switch ($address->getAddressType()) {
case Mage_Sales_Model_Quote_Address::TYPE_BILLING:
$bAddress = $address;
break;
case Mage_Sales_Model_Quote_Address::TYPE_SHIPPING:
$sAddress = $address;
break;
}
}
if ($this->getProduct()->getIsVirtual()) {
$sAddress = $bAddress;
}
$priceExcludingTax = Mage::helper('tax')->getPrice(
$this->getProduct()->setTaxPercent(null),
$value,
false,
$sAddress,
$bAddress,
$this->getQuote()->getCustomerTaxClassId(),
$store
);
$priceIncludingTax = Mage::helper('tax')->getPrice(
$this->getProduct()->setTaxPercent(null),
$value,
true,
$sAddress,
$bAddress,
$this->getQuote()->getCustomerTaxClassId(),
$store
);
if ($saveTaxes) {
$qty = $this->getQty();
if ($this->getParentItem()) {
$qty = $qty*$this->getParentItem()->getQty();
}
if (Mage::helper('tax')->displayCartPriceInclTax($store)) {
$rowTotal = $value*$qty;
$rowTotalExcTax = Mage::helper('tax')->getPrice(
$this->getProduct()->setTaxPercent(null),
$rowTotal,
false,
$sAddress,
$bAddress,
$this->getQuote()->getCustomerTaxClassId(),
$store
);
$rowTotalIncTax = Mage::helper('tax')->getPrice(
$this->getProduct()->setTaxPercent(null),
$rowTotal,
true,
$sAddress,
$bAddress,
$this->getQuote()->getCustomerTaxClassId(),
$store
);
$totalBaseTax = $rowTotalIncTax-$rowTotalExcTax;
$this->setRowTotalExcTax($rowTotalExcTax);
}
else {
$taxAmount = $priceIncludingTax - $priceExcludingTax;
$this->setTaxPercent($this->getProduct()->getTaxPercent());
$totalBaseTax = $taxAmount*$qty;
}
$totalTax = $this->getStore()->convertPrice($totalBaseTax);
$this->setTaxBeforeDiscount($totalTax);
$this->setBaseTaxBeforeDiscount($totalBaseTax);
$this->setTaxAmount($totalTax);
$this->setBaseTaxAmount($totalBaseTax);
}
$value = $priceExcludingTax;
}
return $value;
}
}
I have an entity that can have another entity of the same type as parent (self-referencing?).
So I have a container named Sweden, then another Container named Stockholm, and the $parent property of Stockholm is Sweden (these two are the same type of entity).
I have a validation constraint that makes sure no two entities can have the same name, but here arises a problem when I choose a parent for an entity, because the way the validations work seem to be that it then goes on to check not only the name of the entity Stockholm, but also goes to check the entire entity that I chose for parent, and obviously the name Stockholm is already in the DB (otherwise I couldn't have picked it for parent) there is a validation error, seems like a catch22 issue...
some code to illustrate... Any thoughts?
The entity
namespace BizTV\ContainerManagementBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use BizTV\ContainerManagementBundle\Validator\Constraints as BizTVAssert;
use BizTV\UserBundle\Entity\User as user;
use BizTV\ContainerManagementBundle\Entity\Container as Container;
/**
* BizTV\ContainerManagementBundle\Entity\Container
* #BizTVAssert\ContainerExists
* #ORM\Table(name="container")
* #ORM\Entity
*/
class Container
{
/**
* #var integer $id
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var string $name
* #Assert\NotBlank(message = "Du måste ange ett namn")
* #ORM\Column(name="name", type="string", length=255, nullable=true)
*/
private $name;
/**
* #var object BizTV\BackendBundle\Entity\company
*
* #ORM\ManyToOne(targetEntity="BizTV\BackendBundle\Entity\company")
* #ORM\JoinColumn(name="company", referencedColumnName="id", nullable=false)
*/
protected $company;
/**
* #var object BizTV\ContainerManagementBundle\Entity\ContainerType
*
* #ORM\ManyToOne(targetEntity="BizTV\ContainerManagementBundle\Entity\ContainerType")
* #ORM\JoinColumn(name="container_type", referencedColumnName="id", nullable=false)
*/
protected $containerType;
/**
* #var object BizTV\ContainerManagementBundle\Entity\ContainerSize
*
* #ORM\ManyToOne(targetEntity="BizTV\ContainerManagementBundle\Entity\ContainerSize")
* #ORM\JoinColumn(name="container_size", referencedColumnName="id", nullable=false)
*/
protected $containerSize;
/**
* #ORM\OneToMany(targetEntity="Container", mappedBy="parent")
*/
private $children;
/**
* #ORM\OneToMany(targetEntity="BizTV\ContentManagementBundle\Entity\Content", mappedBy="container")
* #ORM\OrderBy({"sortOrder" = "ASC"})
* above code does nothing, thought to use that instead of the current jQuery tinySort but aparently not...
*/
private $content;
/**
* #var object BizTV\ContainerManagementBundle\Entity\Container
*
* #ORM\ManyToOne(targetEntity="Container", inversedBy="children")
* #ORM\JoinColumn(name="parent", referencedColumnName="id", nullable=true)
*/
protected $parent;
/**
* #var object BizTV\LayoutManagementBundle\Entity\Layout
*
* #ORM\ManyToOne(targetEntity="BizTV\LayoutManagementBundle\Entity\Layout")
* #ORM\JoinColumn(name="screen_layout", referencedColumnName="id", nullable=true)
*/
protected $screen_layout;
/**
* #ORM\Column(type="boolean", nullable=true)
*
* This only applies to the monitor containerType, others will always have false here.
* The purpose of this bool is the option of never rendering this monitor with a layout (handy for ex. BrfTV servers with lower resolution)
*/
protected $prohibitLayout;
/**
* #ORM\ManyToMany(targetEntity="BizTV\UserBundle\Entity\User", mappedBy="access")
*/
private $users;
public function __construct() {
$this->users = new \Doctrine\Common\Collections\ArrayCollection();
$this->children = new \Doctrine\Common\Collections\ArrayCollection();
$this->content = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
*/
public function setName($name)
{
$this->name = $name;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set company
*
* #param BizTV\BackendBundle\Entity\company $company
*/
public function setCompany(\BizTV\BackendBundle\Entity\company $company)
{
$this->company = $company;
}
/**
* Get company
*
* #return BizTV\BackendBundle\Entity\company
*/
public function getCompany()
{
return $this->company;
}
/**
* Set containerType
*
* #param BizTV\ContainerManagementBundle\Entity\ContainerType $containerType
*/
public function setContainerType(\BizTV\ContainerManagementBundle\Entity\ContainerType $containerType)
{
$this->containerType = $containerType;
}
/**
* Get containerType
*
* #return BizTV\ContainerManagementBundle\Entity\ContainerType
*/
public function getContainerType()
{
return $this->containerType;
}
/**
* Set parent
*
* #param BizTV\ContainerManagementBundle\Entity\Container $parent
*/
public function setParent(\BizTV\ContainerManagementBundle\Entity\Container $parent = NULL)
{
$this->parent = $parent;
}
/**
* Get parent
*
* #return BizTV\ContainerManagementBundle\Entity\Container
*/
public function getParent()
{
return $this->parent;
}
/**
* Set screen_layout
*
* #param BizTV\LayoutManagementBundle\Entity\Layout $screenLayout
*/
public function setScreenLayout(\BizTV\LayoutManagementBundle\Entity\Layout $screenLayout = NULL)
{
$this->screen_layout = $screenLayout;
}
/**
* Get screen_layout
*
* #return BizTV\LayoutManagementBundle\Entity\Layout
*/
public function getScreenLayout()
{
return $this->screen_layout;
}
public function getSelectLabel()
{
if (isset($this->parent)) {
return $this->name . ' (' . $this->parent->getName() . ')';
}
else {
return $this->name;
}
}
/**
* Add users
*
* #param BizTV\UserBundle\Entity\User $users
*/
public function addUser(\BizTV\UserBundle\Entity\User $users)
{
$this->users[] = $users;
}
/**
* Get users
*
* #return Doctrine\Common\Collections\Collection
*/
public function getUsers()
{
return $this->users;
}
/**
* Add children
*
* #param BizTV\ContainerManagementBundle\Entity\Container $children
*/
public function addContainer(\BizTV\ContainerManagementBundle\Entity\Container $children)
{
$this->children[] = $children;
}
/**
* Get children
*
* #return Doctrine\Common\Collections\Collection
*/
public function getChildren()
{
return $this->children;
}
/**
* Add content
*
* #param BizTV\ContentManagementBundle\Entity\Content $content
*/
public function addContent(\BizTV\ContentManagementBundle\Entity\Content $content)
{
$this->content[] = $content;
}
/**
* Get content
*
* #return Doctrine\Common\Collections\Collection
*/
public function getContent()
{
return $this->content;
}
/**
* Set containerSize
*
* #param BizTV\ContainerManagementBundle\Entity\ContainerSize $containerSize
*/
public function setContainerSize(\BizTV\ContainerManagementBundle\Entity\ContainerSize $containerSize)
{
$this->containerSize = $containerSize;
}
/**
* Get containerSize
*
* #return BizTV\ContainerManagementBundle\Entity\ContainerSize
*/
public function getContainerSize()
{
return $this->containerSize;
}
/**
* Set prohibitLayout
*
* #param boolean $prohibitLayout
*/
public function setProhibitLayout($prohibitLayout)
{
$this->prohibitLayout = $prohibitLayout;
}
/**
* Get prohibitLayout
*
* #return boolean
*/
public function getProhibitLayout()
{
return $this->prohibitLayout;
}
}
Form
namespace BizTV\ContainerManagementBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
use Doctrine\ORM\EntityRepository;
class ContainerBuildingType extends AbstractType
{
function __construct(\BizTV\BackendBundle\Entity\company $company, \BizTV\ContainerManagementBundle\Entity\ContainerType $parentType) {
$this->parentType = $parentType;
$this->company = $company;
}
public function buildForm(FormBuilder $builder, array $options)
{
$builder->add('name', 'text', array('label' => 'Namn på fastighet '));
$parentType = $this->parentType;
$company = $this->company;
$builder->add('parent', 'entity', array(
'label' => 'Välj ett geografiskt område för fastigheten ',
'class' => 'BizTVContainerManagementBundle:Container','property'=>'name',
'query_builder' => function(EntityRepository $er) use ($parentType, $company) {
return $er->createQueryBuilder('u')
->where('u.containerType = :type', 'u.company = :company')
->setParameters( array('type' => $parentType, 'company' => $company) )
->orderBy('u.name', 'ASC');
},
));
}
public function getName()
{
return 'biztv_containermanagementbundle_containerbuildingtype';
}
}
Constraint
use Symfony\Component\Validator\Constraint;
/**
* #Annotation
*/
class ContainerExists extends Constraint
{
public $message = 'Namnet är upptaget, vänligen välj ett annat.';
public function validatedBy()
{
return 'containerExists';
}
public function getTargets()
{
return self::CLASS_CONSTRAINT;
}
}
Validator
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\DependencyInjection\ContainerInterface as Container;
use Doctrine\ORM\EntityManager as EntityManager;
class ContainerExistsValidator extends ConstraintValidator
{
private $container;
private $em;
public function __construct(Container $container, EntityManager $em) {
$this->container = $container;
$this->em = $em;
}
public function isValid($object, Constraint $constraint)
{
$em = $this->em;
$container = $this->container;
$company = $this->container->get('security.context')->getToken()->getUser()->getCompany();
$parent = $object->getParent();
//Fetch entities with same name in the same container
$repository = $em->getRepository('BizTVContainerManagementBundle:Container');
$query = $repository->createQueryBuilder('c')
->where('c.company = :company and c.parent = :parent')
->setParameters(array('company' => $company, 'parent' => $parent))
->orderBy('c.name', 'ASC')
->getQuery();
$containers = $query->getResult();
foreach ($containers as $g) {
echo "testing ".$g->getName()." against ".$object->getName()."<br/>";
if ( $g->getName() == $object->getName() ) {
$this->setMessage('Namnet '.$object->getName().' är upptaget, vänligen välj ett annat');
return false;
}
}
return true;
}
}
I believe you have your relationships backwards;
Your parent should be OneToMany and your child should be ManyToOne
Unless you intended to have many parents only have 1 child and that child belong to many parents.
The answer to a similar question solved this issue as well:
symfony2 validation of child entity prevents editing of parent entity