Value of field "..." does not exist on referenced table
Trying to use phalcon model relationships to save related models but get an error:
Value of field "db_file_id" does not exist on referenced table
Saving and processing services:
FilesService.php:
<?php
namespace Modules\Upload\Files;
use Core\Framework\Injectable;
use Modules\Upload\Files\Exceptions\FileNotSavedException;
use Utils\Files\File;
class FilesService extends Injectable {
/**
* #param File $file
* #throws FileNotSavedException
* #return DbFile
*/
public function upload(
File $file,
string $subStoragePath = ''
): DbFile {
$storage = $this->getStorage();
$newSubStoragePath = $file->getName();
if (!empty($subStoragePath)) {
$newSubStoragePath = $subStoragePath;
}
$storage->save($file, $newSubStoragePath);
$dbFile = DbFile::fromFile($file);
$dbFile->create();
return $dbFile;
}
}
ImagesService.php
<?php
namespace Modules\Upload\Images;
use Core\Framework\Injectable;
use DateTime;
use Modules\Upload\Files\Exceptions\FileNotSavedException;
use Modules\Upload\Files\FilesService;
use Phalcon\Encryption\Security\Random;
use Phalcon\Image\Adapter\Imagick;
use Phalcon\Image\Enum;
use Utils\Files\File;
use Utils\Text\Paths;
class ImagesService extends Injectable {
public const IMAGES_FORMAT = 'webp';
public const IMAGES_QUALITY = 100;
public const MAIN_IMAGE_SIZE = 1280;
public const THUMBNAIL_SIZES = [200, 480, 720];
public const IMAGES_DIR_NAME = 'images';
/**
* #param File $file
* #throws FileNotSavedException
* #return Image
*/
public function upload(File $file): Image {
$mainImageFile = $this->buildMainImage($file);
$filesService = new FilesService();
$image = new Image();
$generatedPath = $this->generatePath($mainImageFile);
$image->setDbFile($filesService->upload(
$mainImageFile,
$generatedPath
));
$thumbnails = [];
$directory = pathinfo($generatedPath, PATHINFO_DIRNAME);
foreach (self::THUMBNAIL_SIZES as $size) {
$filename = $mainImageFile->getShortName() .
'_' . $size .
'.' . self::IMAGES_FORMAT;
$path = Paths::join([$directory, $filename]);
$thumbnails = [
...$thumbnails,
(new Thumbnail())->setImage($image)
->setDbFile($filesService->upload(
$this->buildThumbnailFile(
$mainImageFile,
$size
),
$path
))->setSize($size)
];
}
$image->setThumbnails($thumbnails);
$image->create();
return $image;
}
/**
* #param File $file
* #return File
*/
private function buildMainImage(File $file): File {
$imagick = new Imagick($file->getPath());
if ($imagick->getWidth() > $imagick->getHeight()) {
$imagick->resize(self::MAIN_IMAGE_SIZE, null, Enum::WIDTH);
} else {
$imagick->resize(null, self::MAIN_IMAGE_SIZE, Enum::HEIGHT);
}
$binary = $imagick->render(
self::IMAGES_FORMAT,
self::IMAGES_QUALITY
);
return File::fromBinary($binary);
}
/**
* #param File $imageFile
* #param integer $size
* #return File
*/
private function buildThumbnailFile(
File $imageFile,
int $size
): File {
$imagick = new Imagick($imageFile->getPath());
if ($imagick->getWidth() > $imagick->getHeight()) {
$imagick->resize($size, null, Enum::WIDTH);
} else {
$imagick->resize(null, $size, Enum::HEIGHT);
}
$binary = $imagick->render(
self::IMAGES_FORMAT,
self::IMAGES_QUALITY
);
return File::fromBinary($binary);
}
/**
* #return string
*/
private function generatePath(File $file): string {
$date = new DateTime();
$year = $date->format('Y');
$month = $date->format('m');
$uuid = (new Random())->uuid();
return self::IMAGES_DIR_NAME .
'/' . $year .
'/' . $month .
'/' . $uuid .
'.' . $file->getExtension();
}
}
Base classes for models:
BaseModel.php
<?php
namespace Core\Models;
use Core\Services\Storage;
use Phalcon\Cache\Adapter\AdapterInterface as CacheAdapterInterface;
use Phalcon\Db\Adapter\AdapterInterface as DbAdapterInterface;
use Phalcon\Mvc\Model;
use ReflectionClass;
use ReflectionProperty;
use Utils\Text\Strings;
abstract class BaseModel extends Model {
/**
* #var string[]
*/
protected array $modelProperties;
/**
* #var integer|null
*/
protected ?int $id = null;
/**
* #return integer|null
*/
public function getId(): int|null {
return $this->id;
}
/**
* #param integer|null $id
* #return static
*/
public function setId($id): static {
$this->id = $id;
return $this;
}
/**
* #return string[]
*/
public function getModelProperties() {
if (!isset($this->modelProperties)) {
$this->modelProperties = $this->scanProperties();
}
return $this->modelProperties;
}
/**
* #return boolean
*/
public function isSaved(): bool {
return !empty($this->id);
}
/**
* #return boolean
*/
public function isNew(): bool {
return !$this->isSaved();
}
/**
* #return void
*/
public function initialize(): void {
$this->useDynamicUpdate(true);
$class = new \ReflectionClass($this);
$className = $class->getShortName();
$namespaceName = $class->getNamespaceName();
$moduleName = explode("\\", $namespaceName)[1];
$tableName = Strings::camelCaseToSnakeCase($className);
$this->setSchema(strtolower($moduleName));
$this->setSource($tableName);
$this->addBehavior(new ErrorLogBehavior([
'notSaved' => [],
'notDeleted' => []
]));
}
/**
* #return array
*/
public function columnMap(): array {
return $this->buildColumnMap();
}
/**
* #return string[]
*/
protected function scanProperties(): array {
$properties = [];
$class = new ReflectionClass($this);
$reflectProperties = $class->getProperties();
foreach ($reflectProperties as $reflectProperty) {
$name = $reflectProperty->getName();
if (
$reflectProperty->isStatic()
|| $this->isFrameworkProperty($name)
|| $name === 'modelProperties'
|| !$this->isAccessableProperty($class, $reflectProperty)
) {
continue;
}
$properties[] = $name;
}
return $properties;
}
/**
* #return Storage
*/
protected function getStorage(): Storage {
return $this->container->get('storage');
}
/**
* #return CacheAdapterInterface
*/
protected function getCache(): CacheAdapterInterface {
return $this->container->get('cache');
}
/**
* #return DbAdapterInterface
*/
protected function getDatabase(): DbAdapterInterface {
return $this->container->get('db');
}
/**
* #param string $propertyName
* #return boolean
*/
private function isFrameworkProperty(string $propertyName): bool {
return in_array($propertyName, [
'dirtyState',
'dirtyRelated',
'errorMessages',
'modelsManager',
'modelsMetaData',
'related',
'operationMade',
'oldSnapshot',
'skipped',
'snapshot',
'transaction',
'uniqueKey',
'uniqueParams',
'uniqueTypes',
'container',
'belongsTo'
]);
}
/**
* #param ReflectionProperty $property
* #return boolean
*/
private function isAccessableProperty(
ReflectionClass $class,
ReflectionProperty $property
): bool {
if ($property->isPublic()) {
return true;
}
$name = $property->getName();
$getterName = Strings::getterName($name);
return $class->hasMethod($getterName)
&& $class->getMethod($getterName)->isPublic();
}
/**
* #return array
*/
private function buildColumnMap(): array {
$properties = $this->getModelProperties();
$map = [];
foreach ($properties as $property) {
$map[Strings::camelCaseToSnakeCase($property)] = $property;
}
return $map;
}
}
TraceableModel.php
<?php
namespace Core\Models;
use DateTime;
use Phalcon\Mvc\Model\Behavior\Timestampable;
use Utils\Time\Time;
abstract class TraceableModel extends BaseModel {
/**
* #var int|null
*/
protected ?string $createdAt = null;
/**
* #var string|null
*/
protected ?string $updatedAt = null;
/**
* #return DateTime|null
*/
public function getCreatedAt(): ?DateTime {
if (empty($this->createdAt)) {
return null;
}
return new DateTime($this->createdAt);
}
/**
* #param int $createdAt
* #return static
*/
public function setCreatedAt(string $createdAt): static {
$this->createdAt = $createdAt;
return $this;
}
/**
* #return DateTime|null
*/
public function getUpdatedAt(): ?DateTime {
if (empty($this->updatedAt)) {
return null;
}
return new DateTime($this->updatedAt);
}
/**
* #param int $updatedAt
* #return static
*/
public function setUpdatedAt(string $updatedAt): static {
// $this->updatedAt = $updatedAt->format(Time::DATETIME_FORMAT);
$this->updatedAt = $updatedAt;
return $this;
}
/**
* #return void
*/
public function initialize(): void {
parent::initialize();
$this->addBehavior(new Timestampable([
'beforeValidationOnCreate' => [
'field' => 'created_at',
'format' => Time::DATETIME_FORMAT,
],
]));
$this->addBehavior(new Timestampable([
'beforeValidationOnUpdate' => [
'field' => 'updated_at',
'format' => Time::DATETIME_FORMAT,
],
'beforeValidationOnCreate' => [
'field' => 'updated_at',
'format' => Time::DATETIME_FORMAT,
],
]));
}
}
Models:
DbFile.php
<?php
namespace Modules\Upload\Files;
use Core\Models\TraceableModel;
use Modules\Upload\Files\Exceptions\FileNotSavedException;
use Utils\Files\File;
use Utils\Serialize\HiddenFields;
class DbFile extends TraceableModel implements HiddenFields {
/**
* #var string
*/
protected string $link;
/**
* #var string
*/
protected string $mimeType;
/**
* #var integer
*/
protected int $size;
/**
* #var File
*/
protected File $file;
/**
* #param File $file
* #throws FileNotSavedException
* #return static
*/
public static function fromFile(File $file): static {
$dbFile = new static();
$dbFile->file = $file;
$dbFile->size = $file->getSize();
$dbFile->mimeType = $file->getMime();
$storage = $dbFile->getStorage();
$link = $storage->getLinkFromFile($file);
if (empty($link)) {
throw new FileNotSavedException($file->getPath());
}
$dbFile->link = $link;
return $dbFile;
}
public function initialize(): void {
parent::initialize();
$this->hasMany(
'id',
DbFileDependency::class,
'db_file_id',
[
'alias' => 'dependencies',
'reusable' => true
]
);
}
/**
* #return string
*/
public function getLink(): string {
return $this->link;
}
/**
* #return string
*/
public function getMimeType(): string {
return $this->mimeType;
}
/**
* #return integer
*/
public function getSize(): int {
return $this->size;
}
/**
* #return DbFileDependency[]
*/
public function getDependencies(): array {
return $this->dependencies;
}
/**
* #param DbFileDependency[] $dependencies
* #return static
*/
public function setDependencies(array $dependencies): static {
$this->dependencies = $dependencies;
return $this;
}
/**
* #return File
*/
public function getFile(): File {
if (!isset($this->file)) {
$this->file = $this->getStorage()->openLink($this->link);
}
return $this->file;
}
/**
* #return string[]
*/
public function getHiddenFields(): array {
return [
'file',
'dependencies'
];
}
}
Image.php
<?php
namespace Modules\Upload\Images;
use Core\Models\BaseModel;
use Modules\Upload\Files\DbFile;
class Image extends BaseModel {
public const IMAGES_DIR_NAME = 'images';
/**
* #var boolean
*/
protected bool $isVector;
/**
* #var integer
*/
protected int $dbFileId;
public function initialize(): void {
parent::initialize();
$this->belongsTo(
'db_file_id',
DbFile::class,
'id',
[
'alias' => 'dbFile',
'foreignKey' => true,
'reusable' => true
]
);
$this->hasMany(
'id',
Thumbnail::class,
'image_id',
[
'alias' => 'Thumbnails',
'reusable' => true
]
);
}
/**
* #return boolean
*/
public function getIsVector() {
return $this->isVector;
}
/**
* #param boolean $isVector
* #return static
*/
public function setIsVector(bool $isVector): static {
$this->isVector = $isVector;
return $this;
}
/**
* #return integer
*/
public function getDbFileId(): int {
return $this->dbFileId;
}
/**
* #param integer $dbFileId
* #return static
*/
public function setDbFileId(int $dbFileId): static {
$this->dbFileId = $dbFileId;
return $this;
}
/**
* #return DbFile
*/
public function getDbFile(): DbFile {
return $this->dbFile;
}
/**
* #param DbFile $dbFile
* #return static
*/
public function setDbFile(DbFile $dbFile): static {
$this->dbFile = $dbFile;
if ($dbFile->getMimeType() === 'image/svg+xml') {
$this->isVector = true;
} else {
$this->isVector = false;
}
return $this;
}
/**
* #return Thumbnail[]
*/
public function getThumbnails(): array {
return $this->thumbnails;
}
/**
* #param Thumbnail[] $thumbnails
* #return static
*/
public function setThumbnails(iterable $thumbnails): static {
$this->thumbnails = [...$thumbnails];
return $this;
}
/**
* #param Thumbnail $thumbnail
* #return static
*/
public function addThumbnail(Thumbnail $thumbnail): static {
$this->thumbnails = [
...$this->thumbnails,
$thumbnail
];
return $this;
}
}
Errors and logs:
SQL logs
[2023-01-11T14:43:50+02:00][DEBUG] NULL
[2023-01-11T14:43:50+02:00][DEBUG] SELECT CASE WHEN COUNT(*) > 0 THEN 1 ELSE 0 END FROM information_schema.tables WHERE table_schema = 'security' AND table_name='user'
[2023-01-11T14:43:50+02:00][DEBUG] SELECT DISTINCT c.column_name AS Field, c.data_type AS Type, c.character_maximum_length AS Size, c.numeric_precision AS NumericSize, c.numeric_scale AS NumericScale, c.is_nullable AS Null, CASE WHEN pkc.column_name NOTNULL THEN 'PRI' ELSE '' END AS Key, CASE WHEN c.data_type LIKE '%int%' AND c.column_default LIKE '%nextval%' THEN 'auto_increment' ELSE '' END AS Extra, c.ordinal_position AS Position, c.column_default, des.description FROM information_schema.columns c LEFT JOIN ( SELECT kcu.column_name, kcu.table_name, kcu.table_schema FROM information_schema.table_constraints tc INNER JOIN information_schema.key_column_usage kcu on (kcu.constraint_name = tc.constraint_name and kcu.table_name=tc.table_name and kcu.table_schema=tc.table_schema) WHERE tc.constraint_type='PRIMARY KEY') pkc ON (c.column_name=pkc.column_name AND c.table_schema = pkc.table_schema AND c.table_name=pkc.table_name) LEFT JOIN ( SELECT objsubid, description, relname, nspname FROM pg_description JOIN pg_class ON pg_description.objoid = pg_class.oid JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid ) des ON ( des.objsubid = C.ordinal_position AND C.table_schema = des.nspname AND C.TABLE_NAME = des.relname ) WHERE c.table_schema='security' AND c.table_name='user' ORDER BY c.ordinal_position
[2023-01-11T14:43:50+02:00][DEBUG] SELECT "user"."id", "user"."firstname", "user"."lastname", "user"."email", "user"."phone", "user"."role", "user"."password_hash", "user"."created_at", "user"."updated_at", "user"."last_signed_in" FROM "security"."user" LIMIT 1
[2023-01-11T14:43:55+02:00][DEBUG] NULL
[2023-01-11T14:43:55+02:00][DEBUG] SELECT CASE WHEN COUNT(*) > 0 THEN 1 ELSE 0 END FROM information_schema.tables WHERE table_schema = 'upload' AND table_name='db_file'
[2023-01-11T14:43:55+02:00][DEBUG] SELECT DISTINCT c.column_name AS Field, c.data_type AS Type, c.character_maximum_length AS Size, c.numeric_precision AS NumericSize, c.numeric_scale AS NumericScale, c.is_nullable AS Null, CASE WHEN pkc.column_name NOTNULL THEN 'PRI' ELSE '' END AS Key, CASE WHEN c.data_type LIKE '%int%' AND c.column_default LIKE '%nextval%' THEN 'auto_increment' ELSE '' END AS Extra, c.ordinal_position AS Position, c.column_default, des.description FROM information_schema.columns c LEFT JOIN ( SELECT kcu.column_name, kcu.table_name, kcu.table_schema FROM information_schema.table_constraints tc INNER JOIN information_schema.key_column_usage kcu on (kcu.constraint_name = tc.constraint_name and kcu.table_name=tc.table_name and kcu.table_schema=tc.table_schema) WHERE tc.constraint_type='PRIMARY KEY') pkc ON (c.column_name=pkc.column_name AND c.table_schema = pkc.table_schema AND c.table_name=pkc.table_name) LEFT JOIN ( SELECT objsubid, description, relname, nspname FROM pg_description JOIN pg_class ON pg_description.objoid = pg_class.oid JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid ) des ON ( des.objsubid = C.ordinal_position AND C.table_schema = des.nspname AND C.TABLE_NAME = des.relname ) WHERE c.table_schema='upload' AND c.table_name='db_file' ORDER BY c.ordinal_position
[2023-01-11T14:43:55+02:00][DEBUG] INSERT INTO "upload"."db_file" ("link", "mime_type", "size", "created_at", "updated_at", "id") VALUES ('/storage/images/2023/01/68909d66-4ea0-4e88-b268-a5b61a424ecc.webp', 'image/webp', 136710, '2023-01-11 14:43:55.000000+02:00', '2023-01-11 14:43:55.000000+02:00', DEFAULT)
[2023-01-11T14:43:55+02:00][DEBUG] INSERT INTO "upload"."db_file" ("link", "mime_type", "size", "created_at", "updated_at", "id") VALUES ('/storage/images/2023/01/68909d66-4ea0-4e88-b268-a5b61a424ecc_200.webp', 'image/webp', 6924, '2023-01-11 14:43:55.000000+02:00', '2023-01-11 14:43:55.000000+02:00', DEFAULT)
[2023-01-11T14:43:55+02:00][DEBUG] INSERT INTO "upload"."db_file" ("link", "mime_type", "size", "created_at", "updated_at", "id") VALUES ('/storage/images/2023/01/68909d66-4ea0-4e88-b268-a5b61a424ecc_480.webp', 'image/webp', 23806, '2023-01-11 14:43:55.000000+02:00', '2023-01-11 14:43:55.000000+02:00', DEFAULT)
[2023-01-11T14:43:55+02:00][DEBUG] INSERT INTO "upload"."db_file" ("link", "mime_type", "size", "created_at", "updated_at", "id") VALUES ('/storage/images/2023/01/68909d66-4ea0-4e88-b268-a5b61a424ecc_720.webp', 'image/webp', 35346, '2023-01-11 14:43:55.000000+02:00', '2023-01-11 14:43:55.000000+02:00', DEFAULT)
[2023-01-11T14:43:55+02:00][DEBUG] SELECT CASE WHEN COUNT(*) > 0 THEN 1 ELSE 0 END FROM information_schema.tables WHERE table_schema = 'upload' AND table_name='image'
[2023-01-11T14:43:55+02:00][DEBUG] SELECT DISTINCT c.column_name AS Field, c.data_type AS Type, c.character_maximum_length AS Size, c.numeric_precision AS NumericSize, c.numeric_scale AS NumericScale, c.is_nullable AS Null, CASE WHEN pkc.column_name NOTNULL THEN 'PRI' ELSE '' END AS Key, CASE WHEN c.data_type LIKE '%int%' AND c.column_default LIKE '%nextval%' THEN 'auto_increment' ELSE '' END AS Extra, c.ordinal_position AS Position, c.column_default, des.description FROM information_schema.columns c LEFT JOIN ( SELECT kcu.column_name, kcu.table_name, kcu.table_schema FROM information_schema.table_constraints tc INNER JOIN information_schema.key_column_usage kcu on (kcu.constraint_name = tc.constraint_name and kcu.table_name=tc.table_name and kcu.table_schema=tc.table_schema) WHERE tc.constraint_type='PRIMARY KEY') pkc ON (c.column_name=pkc.column_name AND c.table_schema = pkc.table_schema AND c.table_name=pkc.table_name) LEFT JOIN ( SELECT objsubid, description, relname, nspname FROM pg_description JOIN pg_class ON pg_description.objoid = pg_class.oid JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid ) des ON ( des.objsubid = C.ordinal_position AND C.table_schema = des.nspname AND C.TABLE_NAME = des.relname ) WHERE c.table_schema='upload' AND c.table_name='image' ORDER BY c.ordinal_position
[2023-01-11T14:43:55+02:00][DEBUG] NULL
[2023-01-11T14:43:55+02:00][DEBUG] SELECT CASE WHEN COUNT(*) > 0 THEN 1 ELSE 0 END FROM information_schema.tables WHERE table_schema = 'upload' AND table_name='db_file'
[2023-01-11T14:43:55+02:00][DEBUG] SELECT DISTINCT c.column_name AS Field, c.data_type AS Type, c.character_maximum_length AS Size, c.numeric_precision AS NumericSize, c.numeric_scale AS NumericScale, c.is_nullable AS Null, CASE WHEN pkc.column_name NOTNULL THEN 'PRI' ELSE '' END AS Key, CASE WHEN c.data_type LIKE '%int%' AND c.column_default LIKE '%nextval%' THEN 'auto_increment' ELSE '' END AS Extra, c.ordinal_position AS Position, c.column_default, des.description FROM information_schema.columns c LEFT JOIN ( SELECT kcu.column_name, kcu.table_name, kcu.table_schema FROM information_schema.table_constraints tc INNER JOIN information_schema.key_column_usage kcu on (kcu.constraint_name = tc.constraint_name and kcu.table_name=tc.table_name and kcu.table_schema=tc.table_schema) WHERE tc.constraint_type='PRIMARY KEY') pkc ON (c.column_name=pkc.column_name AND c.table_schema = pkc.table_schema AND c.table_name=pkc.table_name) LEFT JOIN ( SELECT objsubid, description, relname, nspname FROM pg_description JOIN pg_class ON pg_description.objoid = pg_class.oid JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid ) des ON ( des.objsubid = C.ordinal_position AND C.table_schema = des.nspname AND C.TABLE_NAME = des.relname ) WHERE c.table_schema='upload' AND c.table_name='db_file' ORDER BY c.ordinal_position
Error log
[2023-01-11T14:43:55+02:00][ERROR] Failed to save model 'Modules\Upload\Images\Image': array (
0 =>
Phalcon\Messages\Message::__set_state(array(
'code' => 0,
'field' => 'db_file_id',
'message' => 'Value of field "db_file_id" does not exist on referenced table',
'type' => 'ConstraintViolation',
'metaData' =>
array (
),
)),
)
Checked posts on phalcon forum with similar issue, but I don't have mistakes that was in their case.
Checked resources:
#1
#2
I found where was a problem. In relationships declarations I specified column names instead of property names like $this->belongsTo('db_file_id... instead of $this->belongsTo('dbFileId... . After I changed it to property names, all works.
Related
I'm facing what I think is a really easy task (or it should be at least), I've seen a lot of related questions and try to resolve my own problem with them with no luck at all, this is why I'm writing my own question here.
I want to be able to gather the average temperature from my table within the last 7 rows, i.e the average temperature for the last 7 days.
If I query my database using this simple query I obtain a result that matches my requirements:
select avg(m.temperatura) as temperature from (SELECT temperatura from database.meteodata order by indice desc limit 7) m
But, the problem is trying to move that query into doctrine with PHP.
I'm new to doctrine. I'm building a API using slim framework (version 3). I have a database with a table following this schema:
CREATE TABLE `meteodata` (
'indice' int(11) NOT NULL AUTO_INCREMENT,
'timestamp' timestamp NULL DEFAULT NULL,
'temperatura' float DEFAULT NULL,
'humedad' float DEFAULT NULL,
'viento' float NOT NULL,
'direccion_viento' int(11) NOT NULL,
'lluvia' float NOT NULL,
'summary' varchar(100) DEFAULT NULL,
'icon' varchar(45) DEFAULT NULL,
PRIMARY KEY ('indice')
) ENGINE=InnoDB AUTO_INCREMENT=562 DEFAULT CHARSET=latin1;
I also have an entity class to match that table into my PHP classes like following:
use Doctrine\ORM\Mapping as ORM;
/** #ORM\Entity()
* #ORM\Table(name="meteodata")
*/
class MeteoStation implements JsonSerializable
{
/** #ORM\Id()
* #ORM\Column(name="indice", type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $indice;
/** #ORM\Column(type="datetime", nullable=false) */
protected $timestamp;
/** #ORM\Column(name="viento", type="float") */
protected $wind;
/** #ORM\Column(name="temperatura", type="float") */
protected $temperature;
/** #ORM\Column(name="humedad", type="float") */
protected $humidity;
/** #ORM\Column(name="lluvia", type="float") */
protected $rain;
/** #ORM\Column(name="direccion_viento", type="integer") */
protected $dirViento;
/** #ORM\Column(length=100) */
protected $summary;
/** #ORM\Column(length=20) */
protected $icon;
/**
* #return mixed
*/
public function getIndice()
{
return $this->indice;
}
/**
* #param mixed $indice
*/
public function setIndice($indice)
{
$this->indice = $indice;
}
/**
* #return mixed
*/
public function getTimestamp()
{
return $this->timestamp;
}
/**
* #param mixed $timestamp
*/
public function setTimestamp($timestamp)
{
$this->timestamp = $timestamp;
}
/**
* #return mixed
*/
public function getWind()
{
return $this->wind;
}
/**
* #param mixed $wind
*/
public function setWind($wind)
{
$this->wind = $wind;
}
/**
* #return mixed
*/
public function getTemperature()
{
return $this->temperature;
}
/**
* #param mixed $temperature
*/
public function setTemperature($temperature)
{
$this->temperature = $temperature;
}
/**
* #return mixed
*/
public function getHumidity()
{
return $this->humidity;
}
/**
* #param mixed $humidity
*/
public function setHumidity($humidity)
{
$this->humidity = $humidity;
}
/**
* #return mixed
*/
public function getRain()
{
return $this->rain;
}
/**
* #param mixed $rain
*/
public function setRain($rain)
{
$this->rain = $rain;
}
/**
* #return mixed
*/
public function getDirViento()
{
return $this->dirViento;
}
/**
* #param mixed $dirViento
*/
public function setDirViento($dirViento)
{
$this->dirViento = $dirViento;
}
/**
* #return mixed
*/
public function getSummary()
{
return $this->summary;
}
/**
* #param mixed $summary
*/
public function setSummary($summary)
{
$this->summary = $summary;
}
/**
* #return mixed
*/
public function getIcon()
{
return $this->icon;
}
/**
* #param mixed $icon
*/
public function setIcon($icon)
{
$this->icon = $icon;
}
public function jsonSerialize()
{
return [
"index" => $this->getIndice(),
"timestamp" => $this->getTimestamp(),
"wind" => $this->getWind(),
"temperature" => $this->getTemperature(),
"humidity" => $this->getHumidity(),
"wind_direction" => $this->getDirViento(),
"rain" => $this->getRain(),
"summary" => $this->getSummary(),
"icon" => $this->getIcon()
];
}
}
The problem here is that the return result is always null.
I have a repository field with this method:
public function getLastAvgTemp()
{
$rsm = new ResultSetMappingBuilder($this->entityManager);
$rsm->addRootEntityFromClassMetadata('MeteoStation', 'm');
$rsm->addFieldResult('m', 'temperatura', 'temperature');
$query = $this->entityManager->createNativeQuery("select avg(m.temperatura) as temperatura from (SELECT temperatura from vinesens.meteodata order by indice desc limit 7) m", $rsm);
$data = $query->getResult();
var_dump($data);
//return $data;
}
The result is
nullarray(1) {
[
0
]=>
NULL
}
I know it has to be something easy, because if I change the query to this one (just retrieving the last 7 data) (I know it would be done differently it's just for the sake of the question)
$rsm = new ResultSetMappingBuilder($this->entityManager);
$rsm->addRootEntityFromClassMetadata('MeteoStation', 'm');
$rsm->addFieldResult('m', 'temperatura', 'temperature');
$query = $this->entityManager->createNativeQuery("select * from (SELECT * from vinesens.meteodata order by indice desc limit 7) m", $rsm);
$data = $query->getResult();
var_dump($data);
Then it returns all my values with the appropriate data.
So I think it has something to do with selecting only one particular column from the table and I don't know how to fix it because if I change the query to this:
$rsm = new ResultSetMappingBuilder($this->entityManager);
$rsm->addRootEntityFromClassMetadata('MeteoStation', 'm');
$rsm->addFieldResult('m', 'temperatura', 'temperature');
$query = $this->entityManager->createNativeQuery("select m.temperatura as temperatura from (SELECT temperatura from vinesens.meteodata order by indice desc limit 7) m", $rsm);
$data = $query->getResult();
var_dump($data);
It returns 7 null objects like so:
array(7) {
[
0
]=>
NULL
[
1
]=>
NULL
[
2
]=>
NULL
[
3
]=>
NULL
[
4
]=>
NULL
[
5
]=>
NULL
[
6
]=>
NULL
}
Please, if you need more information don't hesitate to ask me.
Thank you so much.
I have a custom Symfony 4 deserializer
class CardImageDecoder implements EncoderInterface, DecoderInterface
{
public function encode($data, $format, array $context = [])
{
if($format !== 'json') {
throw new EncodingFormatNotSupportedException(sprintf('Format %s is not supported by encoder %s', $format, __CLASS__));
}
$result = json_encode($data);
if(json_last_error() !== JSON_ERROR_NONE) {
// don't bother with a custom error message
throw new \Exception(sprintf('Unable to encode data, got error message: %s', json_last_error_msg()));
}
return $result;
}
public function supportsEncoding($format)
{
return 'json' === $format;
}
public function decode($data, $format, array $context = [])
{
if($format !== 'array') {
throw new DecodingFormatNotSupportedException(sprintf('Format %s is not supported by encoder %s', $format, __CLASS__));
}
if(!is_array($data)) {
throw new \UnexpectedValueException(sprintf('Expected array got %s', gettype($data)));
}
$cardInstance = new CardImages();
$cardInstance->setHeight($data['h'] ?? 0);
$cardInstance->setPath($data['url'] ?? '');
$cardInstance->setWidth($data['w'] ?? 0);
return $cardInstance;
}
public function supportsDecoding($format)
{
return 'array' === $format;
}
}
The way I'm deserializing is pretty straight forward:
$json = '
{
"url": "some url",
"h": 1004,
"w": 768
}';
$encoders = [new CardImageDecoder()];
$normalizers = [new ObjectNormalizer()];
$serializer = new Serializer($normalizers, $encoders);
$cardImage = $serializer->deserialize(json_decode($json, true), CardImages::class, 'array');
/** #var $cardImage CardImages */
var_dump($cardImage);
However, I get this result returned:
object(App\Entity\CardImages)#158 (5) {
["id":"App\Entity\CardImages":private]=>
NULL
["path":"App\Entity\CardImages":private]=>
NULL
["height":"App\Entity\CardImages":private]=>
NULL
["width":"App\Entity\CardImages":private]=>
NULL
["movie":"App\Entity\CardImages":private]=>
NULL
}
Now, if I were to do a dump, just before the return in the decode part of the decoder, I'd get this:
...
$cardInstance->setWidth($data['w'] ?? 0);
var_dump($cardInstance);
object(App\Entity\CardImages)#153 (5) {
["id":"App\Entity\CardImages":private]=>
NULL
["path":"App\Entity\CardImages":private]=>
string(8) "some url"
["height":"App\Entity\CardImages":private]=>
int(1004)
["width":"App\Entity\CardImages":private]=>
int(768)
["movie":"App\Entity\CardImages":private]=>
NULL
}
Ignoring the not set properties(which I'm fine with), it should work quite nicely, but it doesn't.
For the life of me I can't figure out what's wrong.
Any help is appreciated.
You are thinking way to complicated.
Tested, working example:
Your entity - take a closer look at the end - we need setters with the names of your array keys:
namespace App\Domain;
class CardImages
{
/** #var int|null */
private $id;
/** #var int|null */
private $height;
/** #var string|null */
private $path;
/** #var int|null */
private $width;
/** #var mixed */
private $movie;
/**
* #return int|null
*/
public function getId(): ?int
{
return $this->id;
}
/**
* #param int|null $id
* #return CardImages
*/
public function setId(?int $id): CardImages
{
$this->id = $id;
return $this;
}
/**
* #return int|null
*/
public function getHeight(): ?int
{
return $this->height;
}
/**
* #param int|null $height
* #return CardImages
*/
public function setHeight(?int $height): CardImages
{
$this->height = $height;
return $this;
}
/**
* #return string|null
*/
public function getPath(): ?string
{
return $this->path;
}
/**
* #param string|null $path
* #return CardImages
*/
public function setPath(?string $path): CardImages
{
$this->path = $path;
return $this;
}
/**
* #return int|null
*/
public function getWidth(): ?int
{
return $this->width;
}
/**
* #param int|null $width
* #return CardImages
*/
public function setWidth(?int $width): CardImages
{
$this->width = $width;
return $this;
}
/**
* #return mixed
*/
public function getMovie()
{
return $this->movie;
}
/**
* #param mixed $movie
* #return CardImages
*/
public function setMovie($movie)
{
$this->movie = $movie;
return $this;
}
public function setH(?int $height): CardImages
{
$this->setHeight($height);
return $this;
}
public function setUrl(?string $url): CardImages
{
$this->setPath($url);
return $this;
}
public function setW(?int $width): CardImages
{
$this->setWidth($width);
return $this;
}
}
Simple Controller to test the Output:
<?php
namespace App\Infrastructure\Web\Controller;
use App\Domain\CardImages;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\SerializerInterface;
/**
* Class IndexController.
*
* #Route("/test")
*/
class TestController extends AbstractController
{
private $serializer;
public function __construct(SerializerInterface $serializer)
{
$this->serializer = $serializer;
}
/**
* #Route("")
*
* #return Response
*/
public function indexAction(): Response
{
$data = [
[
'h' => 100,
'w' => 100,
'path' => '/asdf/asdf.png',
],
[
'h' => 50,
'w' => 150,
'path' => '/asdf/foo.png',
],
[
'h' => 100,
'w' => 200,
'path' => '/asdf/bar.png',
],
[
'h' => 300,
'w' => 400,
'path' => '/asdf/baz.png',
],
];
foreach ($data as $row) {
$cardImage = $this->serializer->denormalize($row, CardImages::class, null, [
ObjectNormalizer::DISABLE_TYPE_ENFORCEMENT => false
]);
$json = $this->serializer->serialize($cardImage, 'json');
dump($cardImage, $json);
}
return new Response('<html><head></head></html></body></html>');
}
}
Output:
I am using webvimark module in Yii2. I have created a My Account page, where a user can update his/her information. I am unable to update user updated info, although I am able to fetch user info and display in a form on my-account page.
Below is my updated webvimark User class:
/**
* This is the model class for table "user".
*
* #property string $name
* #property string $country
* #property string $card_number
* #property string $payment_type
* #property string $expiring_month
* #property string $expiring_year
* #property string $expiry_date
* #property string $csc
* #property string $card_address
* #property string $city
* #property string $state
* #property string $zip_code
* #property string $user_type
* #property string $fax
* #property string $address
* #property string $phone
* #property string $user_type
* #property string $company_name
* #property integer $id
* #property string $username
* #property string $email
* #property integer $email_confirmed
* #property string $auth_key
* #property string $password_hash
* #property string $confirmation_token
* #property string $bind_to_ip
* #property string $registration_ip
* #property integer $status
* #property integer $superadmin
* #property integer $created_at
* #property integer $updated_at
*/
class User extends UserIdentity
{
const STATUS_ACTIVE = 1;
const STATUS_INACTIVE = 0;
const STATUS_BANNED = -1;
/**
* #var string
*/
public $gridRoleSearch;
/**
* #var string
*/
public $password;
/**
* #var string
*/
public $repeat_password;
/**
* Store result in singleton to prevent multiple db requests with multiple calls
*
* #param bool $fromSingleton
*
* #return static
*/
public static function getCurrentUser($fromSingleton = true)
{
if ( !$fromSingleton )
{
return static::findOne(Yii::$app->user->id);
}
$user = Singleton::getData('__currentUser');
if ( !$user )
{
$user = static::findOne(Yii::$app->user->id);
Singleton::setData('__currentUser', $user);
}
return $user;
}
/**
* Assign role to user
*
* #param int $userId
* #param string $roleName
*
* #return bool
*/
public static function assignRole($userId, $roleName)
{
try
{
Yii::$app->db->createCommand()
->insert(Yii::$app->getModule('user-management')->auth_assignment_table, [
'user_id' => $userId,
'item_name' => $roleName,
'created_at' => time(),
])->execute();
AuthHelper::invalidatePermissions();
return true;
}
catch (\Exception $e)
{
return false;
}
}
/**
* Revoke role from user
*
* #param int $userId
* #param string $roleName
*
* #return bool
*/
public static function revokeRole($userId, $roleName)
{
$result = Yii::$app->db->createCommand()
->delete(Yii::$app->getModule('user-management')->auth_assignment_table, ['user_id' => $userId, 'item_name' => $roleName])
->execute() > 0;
if ( $result )
{
AuthHelper::invalidatePermissions();
}
return $result;
}
/**
* #param string|array $roles
* #param bool $superAdminAllowed
*
* #return bool
*/
public static function hasRole($roles, $superAdminAllowed = true)
{
if ( $superAdminAllowed AND Yii::$app->user->isSuperadmin )
{
return true;
}
$roles = (array)$roles;
AuthHelper::ensurePermissionsUpToDate();
return array_intersect($roles, Yii::$app->session->get(AuthHelper::SESSION_PREFIX_ROLES,[])) !== [];
}
/**
* #param string $permission
* #param bool $superAdminAllowed
*
* #return bool
*/
public static function hasPermission($permission, $superAdminAllowed = true)
{
if ( $superAdminAllowed AND Yii::$app->user->isSuperadmin )
{
return true;
}
AuthHelper::ensurePermissionsUpToDate();
return in_array($permission, Yii::$app->session->get(AuthHelper::SESSION_PREFIX_PERMISSIONS,[]));
}
/**
* Useful for Menu widget
*
* <example>
* ...
* [ 'label'=>'Some label', 'url'=>['/site/index'], 'visible'=>User::canRoute(['/site/index']) ]
* ...
* </example>
*
* #param string|array $route
* #param bool $superAdminAllowed
*
* #return bool
*/
public static function canRoute($route, $superAdminAllowed = true)
{
if ( $superAdminAllowed AND Yii::$app->user->isSuperadmin )
{
return true;
}
$baseRoute = AuthHelper::unifyRoute($route);
if ( Route::isFreeAccess($baseRoute) )
{
return true;
}
AuthHelper::ensurePermissionsUpToDate();
return Route::isRouteAllowed($baseRoute, Yii::$app->session->get(AuthHelper::SESSION_PREFIX_ROUTES,[]));
}
/**
* getStatusList
* #return array
*/
public static function getStatusList()
{
return array(
self::STATUS_ACTIVE => UserManagementModule::t('back', 'Active'),
self::STATUS_INACTIVE => UserManagementModule::t('back', 'Inactive'),
self::STATUS_BANNED => UserManagementModule::t('back', 'Banned'),
);
}
/**
* getStatusValue
*
* #param string $val
*
* #return string
*/
public static function getStatusValue($val)
{
$ar = self::getStatusList();
return isset( $ar[$val] ) ? $ar[$val] : $val;
}
/**
* #inheritdoc
*/
public static function tableName()
{
return Yii::$app->getModule('user-management')->user_table;
}
/**
* #inheritdoc
*/
public function behaviors()
{
return [
TimestampBehavior::className(),
];
}
/**
* #inheritdoc
*/
public function rules()
{
return [
['username', 'required'],
[['name','phone','user_type'], 'required'],
['username', 'unique'],
['username', 'trim'],
[['company_name', 'name', 'phone','fax','address','payment_type','card_number','expiry_date','csc','card_address','country','city','state','zip_code'], 'trim'],
[['status', 'email_confirmed'], 'integer'],
['email', 'email'],
['email', 'validateEmailConfirmedUnique'],
['bind_to_ip', 'validateBindToIp'],
['bind_to_ip', 'trim'],
['bind_to_ip', 'string', 'max' => 255],
['password', 'required', 'on'=>['newUser', 'changePassword']],
['password', 'string', 'max' => 255, 'on'=>['newUser', 'changePassword']],
['password', 'trim', 'on'=>['newUser', 'changePassword']],
['repeat_password', 'required', 'on'=>['newUser', 'changePassword']],
['repeat_password', 'compare', 'compareAttribute'=>'password'],
];
}
/**
* Check that there is no such confirmed E-mail in the system
*/
public function validateEmailConfirmedUnique()
{
if ( $this->email )
{
$exists = User::findOne([
'email' => $this->email,
'email_confirmed' => 1,
]);
if ( $exists AND $exists->id != $this->id )
{
$this->addError('email', UserManagementModule::t('front', 'This E-mail already exists'));
}
}
}
/**
* Validate bind_to_ip attr to be in correct format
*/
public function validateBindToIp()
{
if ( $this->bind_to_ip )
{
$ips = explode(',', $this->bind_to_ip);
foreach ($ips as $ip)
{
if ( !filter_var(trim($ip), FILTER_VALIDATE_IP) )
{
$this->addError('bind_to_ip', UserManagementModule::t('back', "Wrong format. Enter valid IPs separated by comma"));
}
}
}
}
/**
* #return array
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'username' => UserManagementModule::t('back', 'Login'),
'superadmin' => UserManagementModule::t('back', 'Superadmin'),
'confirmation_token' => 'Confirmation Token',
'registration_ip' => UserManagementModule::t('back', 'Registration IP'),
'bind_to_ip' => UserManagementModule::t('back', 'Bind to IP'),
'status' => UserManagementModule::t('back', 'Status'),
'gridRoleSearch' => UserManagementModule::t('back', 'Roles'),
'created_at' => UserManagementModule::t('back', 'Created'),
'updated_at' => UserManagementModule::t('back', 'Updated'),
'password' => UserManagementModule::t('back', 'Password'),
'repeat_password' => UserManagementModule::t('back', 'Repeat password'),
'email_confirmed' => UserManagementModule::t('back', 'E-mail confirmed'),
'email' => 'E-mail',
//'user_type' => 'E-mail',
];
}
/**
* #return \yii\db\ActiveQuery
*/
public function getRoles()
{
return $this->hasMany(Role::className(), ['name' => 'item_name'])
->viaTable(Yii::$app->getModule('user-management')->auth_assignment_table, ['user_id'=>'id']);
}
/**
* Make sure user will not deactivate himself and superadmin could not demote himself
* Also don't let non-superadmin edit superadmin
*
* #inheritdoc
*/
public function beforeSave($insert)
{
if ( $insert )
{
if ( php_sapi_name() != 'cli' )
{
$this->registration_ip = LittleBigHelper::getRealIp();
}
$this->generateAuthKey();
}
else
{
// Console doesn't have Yii::$app->user, so we skip it for console
if ( php_sapi_name() != 'cli' )
{
if ( Yii::$app->user->id == $this->id )
{
// Make sure user will not deactivate himself
$this->status = static::STATUS_ACTIVE;
// Superadmin could not demote himself
if ( Yii::$app->user->isSuperadmin AND $this->superadmin != 1 )
{
$this->superadmin = 1;
}
}
// Don't let non-superadmin edit superadmin
if ( isset($this->oldAttributes['superadmin']) && !Yii::$app->user->isSuperadmin && $this->oldAttributes['superadmin'] == 1 )
{
return false;
}
}
}
// If password has been set, than create password hash
if ( $this->password )
{
$this->setPassword($this->password);
}
return parent::beforeSave($insert);
}
/**
* Don't let delete yourself and don't let non-superadmin delete superadmin
*
* #inheritdoc
*/
public function beforeDelete()
{
// Console doesn't have Yii::$app->user, so we skip it for console
if ( php_sapi_name() != 'cli' )
{
// Don't let delete yourself
if ( Yii::$app->user->id == $this->id )
{
return false;
}
// Don't let non-superadmin delete superadmin
if ( !Yii::$app->user->isSuperadmin AND $this->superadmin == 1 )
{
return false;
}
}
return parent::beforeDelete();
}
}
and the AuthController class because I have created my view file (my-account.php inside auth folder of webvimark). My AuthController action function is as under:
public function actionMyAccount()
{
$model = new User();
if ( Yii::$app->user->isGuest )
{
return $this->goHome();
}
//if ( Yii::$app->request->post() AND $model->validate())
if ( Yii::$app->request->post())
{
if($model->load(Yii::$app->request->post()) )
{
$model->save();
Yii::$app->session->setFlash('message', "Account has been updated!");
}
}
else
{
$model = User::getCurrentUser();
}
return $this->render('my-account', ['model' => $model,]);
}
Could be you must declare the field you don't validate by the safe attribute
[['company_name', 'name', 'phone','fax','address','payment_type',
'card_number','expiry_date','csc','card_address','country',
'city','state','zip_code'], 'safe'],
or could be is a validation problem
try using (just for debug) save(false)
//if ( Yii::$app->request->post() AND $model->validate())
if ( Yii::$app->request->post())
{
if($model->load(Yii::$app->request->post()) )
{
$model->save(false);
Yii::$app->session->setFlash('message', "Account has been updated!");
} else {
var_dump('model not loaded');
}
}
if in this way the values are saved in db the is a validation rule problem .
You can get the validation error this way
if ($model->validate()) {
// all inputs are valid
} else {
// validation failed: $errors is an array containing error messages
$errors = $model->errors;
var_dump($errors);
}
Hi everyone this is my first question!
I would like to have an Entity, with a field that indicates order, say EntityInstance1 with order 1, EntityInstance2 with order 2, EntityInstance3 with order 3... etc. Then for example I want to create a new instance, and give it order 2. So the result would be EntityInstance1 with order 1, EntityInstance4 with order 2, EntityInstance2 with order 3 and Entity Instance3 with order 4. An then let's say that I delete EntityInstance1, so I'll have EntityInstance4 with order 1, EntityInstance2 with order 2, EntityInstance3 with order 3. How could be this achieved??
Thanks!!!
Well... I really don't know why anybody would do something like that, but ok, it's realizeable. Let's think logical.
1) You have multiple instances of the same object => means you have a collection of object
2) A Collection has some kind of iterator
3) You can use the iterator to iterate over the list and update the instances orders.
So the easiest, but most expensive way to realize your vision is:
$objectCollection = $this -> get('doctrine.orm.entity_manager') -> getRepository('YOUR_ENTITY') -> findBy(array(),array('order','asc'));
$iterator = $objectCollection -> getArrayIterator();
$i = 1;
while($object = $iterator -> next()){
$object -> setOrder($i);
$i++;
}
$this -> get('doctrine.orm.entity_manager') -> flush();
Note: order can not be used as a property name. So you need another name and change it in the code sample, too.
Got it working! Using lifecycle events and bulk updates!
Here's my entity:
namespace LuchoNat\Icna\Website\BackendBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Meeting
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="LuchoNat\Icna\Website\BackendBundle\Entity\MeetingRepository")
*/
class Meeting {
/* ***************************************************************************************/
/* Properties ****************************************************************************/
/* ***************************************************************************************/
// Mapped
/**
*
* #var integer #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
*
* #var string #ORM\Column(name="name", type="string", length=255, nullable=false)
* #Assert\NotBlank(message="El campo nombre es obligatorio")
*/
private $name;
/**
*
* #var integer #ORM\Column(name="production_order", type="integer", nullable=true)
*/
private $productionOrder;
/**
*
* #var integer #ORM\Column(name="staging_order", type="integer", nullable=true)
*/
private $stagingOrder;
/**
*
* #var boolean #ORM\Column(name="production_enabled", type="boolean", nullable=false)
*/
private $productionEnabled;
/**
*
* #var boolean #ORM\Column(name="staging_enabled", type="boolean", nullable=false)
*/
private $stagingEnabled;
/* ***************************************************************************************/
/* Getters & Setters *********************************************************************/
/* ***************************************************************************************/
/**
* Get id
*
* #return integer
*/
public function getId() {
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return Meeting
*/
public function setName($name) {
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName() {
return $this->name;
}
/**
* Set productionOrder
*
* #param integer $productionOrder
* #return Meeting
*/
public function setProductionOrder($productionOrder) {
$this->productionOrder = $productionOrder;
return $this;
}
/**
* Get productionOrder
*
* #return integer
*/
public function getProductionOrder() {
return $this->productionOrder;
}
/**
* Set stagingOrder
*
* #param integer $stagingOrder
* #return Meeting
*/
public function setStagingOrder($stagingOrder) {
$this->stagingOrder = $stagingOrder;
return $this;
}
/**
* Get stagingOrder
*
* #return integer
*/
public function getStagingOrder() {
return $this->stagingOrder;
}
/**
* Set productionEnabled
*
* #param boolean $productionEnabled
* #return Meeting
*/
public function setProductionEnabled($productionEnabled) {
$this->productionEnabled = $productionEnabled;
return $this;
}
/**
* Get productionEnabled
*
* #return boolean
*/
public function getProductionEnabled() {
return $this->productionEnabled;
}
/**
* Set stagingEnabled
*
* #param boolean $stagingEnabled
* #return Meeting
*/
public function setStagingEnabled($stagingEnabled) {
$this->stagingEnabled = $stagingEnabled;
return $this;
}
/**
* Get stagingEnabled
*
* #return boolean
*/
public function getStagingEnabled() {
return $this->stagingEnabled;
}
/* ***************************************************************************************/
/* Other Methods *************************************************************************/
/* ***************************************************************************************/
}
Then, here is the EventListener
namespace LuchoNat\Icna\Website\BackendBundle\EventListener;
use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\LifecycleEventArgs;
use LuchoNat\Icna\Website\BackendBundle\Entity\Meeting;
class MeetingIndexerSubscriber implements EventSubscriber
{
public function getSubscribedEvents() {
return array(
'prePersist',
'preUpdate',
'postRemove'
);
}
public function prePersist(LifecycleEventArgs $args) {
$entity = $args->getEntity();
$entityManager = $args->getEntityManager();
if($entity instanceof Meeting) {
$stagingOrder = $entity->getStagingOrder();
if(isset($stagingOrder)) {
$dql = "UPDATE LuchoNat\Icna\Website\BackendBundle\Entity\Meeting
m set m.stagingOrder = m.stagingOrder + 1
WHERE m.stagingOrder >= $stagingOrder";
$entityManager->createQuery($dql)->execute();
}
$productionOrder = $entity->getProductionOrder();
if(isset($productionOrder)) {
$dql = "UPDATE LuchoNat\Icna\Website\BackendBundle\Entity\Meeting
m set m.productionOrder = m.productionOrder + 1
WHERE m.productionOrder >= $productionOrder";
$entityManager->createQuery($dql)->execute();
}
}
}
public function preUpdate(LifecycleEventArgs $args) {
$entity = $args->getEntity();
$entityManager = $args->getEntityManager();
if($entity instanceof Meeting) {
if($args->hasChangedField('stagingOrder')) {
if($args->getNewValue('stagingOrder') > $args->getOldValue('stagingOrder')) {
$dql = 'UPDATE LuchoNat\Icna\Website\BackendBundle\Entity\Meeting
m set m.stagingOrder = m.stagingOrder - 1
WHERE m.stagingOrder > ' . $args->getOldValue('stagingOrder') .
' AND m.stagingOrder <= ' . $args->getNewValue('stagingOrder');
$entityManager->createQuery($dql)->execute();
}
if($args->getNewValue('stagingOrder') < $args->getOldValue('stagingOrder')) {
$dql = 'UPDATE LuchoNat\Icna\Website\BackendBundle\Entity\Meeting
m set m.stagingOrder = m.stagingOrder + 1
WHERE m.stagingOrder >= ' . $args->getNewValue('stagingOrder') .
' AND m.stagingOrder < ' . $args->getOldValue('stagingOrder');
$entityManager->createQuery($dql)->execute();
}
}
if($args->hasChangedField('productionOrder')) {
if($args->getNewValue('productionOrder') > $args->getOldValue('productionOrder')) {
$dql = 'UPDATE LuchoNat\Icna\Website\BackendBundle\Entity\Meeting
m set m.productionOrder = m.productionOrder - 1
WHERE m.productionOrder > ' . $args->getOldValue('productionOrder') .
' AND m.productionOrder <= ' . $args->getNewValue('productionOrder');
$entityManager->createQuery($dql)->execute();
}
if($args->getNewValue('productionOrder') < $args->getOldValue('productionOrder')) {
$dql = 'UPDATE LuchoNat\Icna\Website\BackendBundle\Entity\Meeting
m set m.productionOrder = m.productionOrder + 1
WHERE m.productionOrder >= ' . $args->getNewValue('productionOrder') .
' AND m.productionOrder < ' . $args->getOldValue('productionOrder');
$entityManager->createQuery($dql)->execute();
}
}
}
}
public function postRemove(LifecycleEventArgs $args) {
$entity = $args->getEntity();
$entityManager = $args->getEntityManager();
if($entity instanceof Meeting) {
$stagingOrder = $entity->getStagingOrder();
if(isset($stagingOrder)) {
$dql = "UPDATE LuchoNat\Icna\Website\BackendBundle\Entity\Meeting
m set m.stagingOrder = m.stagingOrder - 1
WHERE m.stagingOrder > $stagingOrder";
$entityManager->createQuery($dql)->execute();
}
$productionOrder = $entity->getProductionOrder();
if(isset($productionOrder)) {
$dql = "UPDATE LuchoNat\Icna\Website\BackendBundle\Entity\Meeting
m set m.productionOrder = m.productionOrder - 1
WHERE m.productionOrder > $productionOrder";
$entityManager->createQuery($dql)->execute();
}
}
}
}
And finally, in the config file:
services:
meeting.indexer_suscriber:
class: LuchoNat\Icna\Website\BackendBundle\EventListener\MeetingIndexerSubscriber
tags:
- { name: doctrine.event_subscriber, connection: default }
It works!!!
I used Symfony 2: How to Register Event Listeners and Subscribers and Doctrine 2: Events documentation!
I am getting an warning message in my website :
Warning: Creating default object from empty value in /homepages/16/d381040813/htdocs/components/com_events_booking/models/event.php on line 169
I have opened 169 th line in event.php , the code is:
$row->event->BeforeDisplay = trim(implode("\n", $results));
My event.php file is :
<?php
// no direct access
defined('_JEXEC') or die('Restricted access');
jimport('joomla.application.component.model');
/**
* Event_Booking Component - Event Model
* #package Event_Booking
* #subpackage Model
*/
class Events_BookingModelEvent extends JModel {
/** #var int Total of documents */
var $_total = null;
/** #var object Pagination object */
var $_pagination = null;
/** #var string */
var $nullDate = null;
/** #var string */
var $now = null;
/** #var int */
var $_id = null;
/** #var array realty data */
var $_data = null;
/**
* Constructor.
*/
function __construct() {
global $mainframe, $option;
parent::__construct();
$this->nullDate = $this->_db->getNullDate();
$jdate = JFactory::getDate();
$this->now = $jdate->toMySQL();
$id = JRequest::getInt('id', 0);
if( !$id ){
$session = &JFactory::getSession();
$user = JFactory::getUser();
$joinevent = $session->get('joinevent');
if( #count( $joinevent[$user->get('id')] ) ){
$id = $joinevent[$user->get('id')]['id'];
}
}
$this->setId($id);
}
/**
* Method to set the identifier
*
* #access public
* #param int $id realty identifier
*/
function setId($id) {
$this->_id = $id;
$this->_data = null;
}
/**
* Method to get event item data.
* #access public
* #return object
*/
function getData($id = null) {
// Lets load the data if it doesn't already exist
if (empty($this->_data)) {
$id = $id ? $id : $this->_id;
$query = 'SELECT a.*, b.id AS bid , b.title AS btitle , c.id AS cid , c.title AS ctitle, c.street, c.city, c.state, c.zip, ct.name AS `country`, c.website, c.latitude, c.longitude'
. ' FROM #__events_events AS a'
. ' INNER JOIN #__events_categories AS b ON a.category_id = b.id'
. ' INNER JOIN #__events_venues AS c ON a.venue_id = c.id'
. ' LEFT JOIN #__events_countries AS ct ON ct.code LIKE c.country'
. ' WHERE a.published = 1 AND a.id = '. (int) $id
;
$this->_db->setQuery($query);
$this->_data = $this->_db->loadObject();
}
if (!$this->_data->id) {
JError::raiseError( 404, JText::_('COM_EVENTS_BOOKING_EVENT_NOT_FOUND'));
}
return $this->_data;
}
/**
* Method to get group item data.
* #access public
* #return array
*/
function getGroup($id = null) {
$query = 'SELECT g.* FROM #__events_groups as g'
. ' WHERE g.published = 1 AND a.id = '. (int) $id
;
$this->_db->setQuery($query);
$row = $this->_db->loadObject();
return $row;
}
/**
* Method to get Expired item data.
* #access public
* #return array
*/
function getExpired() {
$date = new JDate();
$id = $this->_id;
$query = 'SELECT COUNT(*) FROM #__events_events AS a WHERE a.id = '.(int)$id.' AND a.published = 1 AND a.expired > '.$this->_db->Quote($date->toMySQL());
$this->_db->setQuery($query);
$row = $this->_db->loadResult();
return $row;
}
/**
* Method to get Expired Capacity.
* #access public
* #return array
*/
function getCapacity() {
$data = $this->getData();
$id = $this->_id;
$result = $this->getMemberCapacity($data->capacity);
return $result;
}
/**
* Method to get Member Capacity COM_EVENTS_BOOKING_JOIN_EVENT.
* #access public
* #return array
*/
function getMemberCapacity($capacity=0) {
$id = $this->_id;
// $query = 'SELECT COUNT(*) FROM #__events_members AS a WHERE a.event_id = '.(int)$id;
$query = 'SELECT COUNT(*)'
. ' FROM #__events_members AS a'
. ' INNER JOIN #__events_bookings AS b ON b.id = a.booking_id'
. ' WHERE a.event_id = '.(int)$id
. ' AND b.approved = 1'
. ' AND a.approved = 1'
;
$this->_db->setQuery($query);
$row = $this->_db->loadResult();
$result = array();
$result['m_capacity'] = $row;
$result['e_capacity'] = (int)($capacity-(int)$row);
return $result;
}
function execPlugins(&$row, $view, $task){
$params = &JComponentHelper::getParams('com_events_booking');
$limitstart = JRequest::getInt('limitstart');
//Import plugins
$dispatcher = &JDispatcher::getInstance();
JPluginHelper::importPlugin ('content');
$row->text = $row->description;
$results = $dispatcher->trigger('onBeforeDisplay', array ( 'com_events_booking.event', &$row, &$params, $limitstart));
$row->event->BeforeDisplay = trim(implode("\n", $results));
$results = $dispatcher->trigger('onAfterDisplay', array ( 'com_events_booking.event', &$row, &$params, $limitstart));
$row->event->AfterDisplay = trim(implode("\n", $results));
$results = $dispatcher->trigger('onAfterDisplayTitle', array ( 'com_events_booking.event', &$row, &$params, $limitstart));
$row->event->AfterDisplayTitle = trim(implode("\n", $results));
$results = $dispatcher->trigger('onBeforeDisplayContent', array ( 'com_events_booking.event', &$row, &$params, $limitstart));
$row->event->BeforeDisplayContent = trim(implode("\n", $results));
$results = $dispatcher->trigger('onAfterDisplayContent', array ( 'com_events_booking.event', &$row, &$params, $limitstart));
$row->event->AfterDisplayContent = trim(implode("\n", $results));
$dispatcher->trigger('onContentPrepare', array ( 'com_events_booking.event', &$row, &$params, $limitstart));
return $row;
}
/**
* Method to store the booking
*
* #access public
* #param $data
* #return boolean True on success
*/
function store($data) {
//$row = JTable::getInstance('form', 'Table');
$row =& $this->getTable('event');
// bind the form fields to the version table
if (!$row->bind($data)) {
$this->setError($this->_db->getErrorMsg());
return false;
}
// make sure the category is valid
if (!$row->check()) {
$this->setError($this->_db->getErrorMsg());
return false;
}
// store the category table to the database
if (!$row->store()) {
$this->setError($this->_db->getErrorMsg());
return false;
}
return $row;
}
I googled a day, but no result. Please help me to hide this warning or solving this.
the page url in which error shown:
http://www.lefoodist.biz/calendar-gb/calendar-hosted-gastronomic-dinners?view=event&id=478#box-details
Nowhere have you created a $row->event object. So when you set $row->event->BeforeDisplay, the BeforeDisplay object is being created against something that hasn't been set. If you do something like $row->event = new stdClass(); before your events start to run, this should clear it up.