I extend feuser with custom fields. All work good. If I type integer value it was save good. But if I type string value I get error - 1332933658: "" is no integer. You can see this on the follow screenshots.
enter image description here
ext_tables.php
#
# Table structure for table 'fe_users'
#
CREATE TABLE fe_users (
aboutmyself varchar(255) DEFAULT '' NOT NULL,
aboutmypartner varchar(255) DEFAULT '' NOT NULL,
tx_extbase_type varchar(255) DEFAULT '0' NOT NULL,
);
Model:
<?php
namespace Fhk\Feusersplus\Domain\Model;
/***************************************************************
*
* Copyright notice
*
* (c) 2017
*
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
/**
* User
*/
class User extends \In2code\Femanager\Domain\Model\User
{
/**
* aboutmyself
*
* #var int
*/
protected $aboutmyself = '';
/**
* aboutmypartner
*
* #var int
*/
protected $aboutmypartner = '';
/**
* Returns the aboutmyself
*
* #return int $aboutmyself
*/
public function getAboutmyself()
{
return (string)$this->aboutmyself;
}
/**
* Returns the aboutmypartner
*
* #return int $aboutmypartner
*/
public function getAboutmypartner()
{
return (string)$this->aboutmypartner;
}
/**
* Sets the aboutmyself
*
* #return void
*/
public function setAboutmyself($aboutmyself)
{
$this->aboutmyself = (string)$aboutmyself;
}
/**
* Sets the aboutmypartner
*
* #return void
*/
public function setAboutmypartner($aboutmypartner)
{
$this->aboutmypartner = (string)$aboutmypartner;
}
/**
* __construct
*/
public function __construct()
{
//Do not remove the next line: It would break the functionality
$this->initStorageObjects();
}
/**
* Initializes all ObjectStorage properties
* Do not modify this method!
* It will be rewritten on each save in the extension builder
* You may modify the constructor of this class instead
*
* #return void
*/
protected function initStorageObjects()
{
}
}
The type hint for your fields aboutmyself and aboutmypartner is defined as
#var int
but you store a VARCHAR. Try changing the hint to
#var string
and clear all caches (also, emptying the typo3temp folder can't hurt).
Related
I'm new to PHP Swagger and using the Laravel package L5-Swagger to create documentation for my API. Now I'm trying to let one model contain an array of the other model, an Order can have several OrderItems.
Unfortuantly I cannot get the linking to work. See attached screen shot.
What am I doing wrong?
This is my Order model:
/**
* #SWG\Definition(
* required={"order_id","order_items"},
* type="object",
* #SWG\Xml(name="Order")
* )
*/
class Order
{
/**
* #SWG\Property(example="O-789456123")
* #var string
*/
public $order_id;
/**
* #SWG\Property(type="array", items="$ref:OrderItem")
* #var array
*/
public $order_items = [];
}
This is my OrderItem model:
/**
* #SWG\Definition(
* required={"sku","quantity", "price_including_tax"},
* type="object",
* #SWG\Xml(name="OrderItem")
* )
*/
class OrderItem
{
/**
* #SWG\Property(example="SKU-123")
* #var string
*/
public $sku;
/**
* #SWG\Property(example=2)
* #var integer
*/
public $quantity;
/**
* #SWG\Property(example=199.75)
* #var float
*/
public $price_including_tax;
}
I think items="$ref:OrderItem" should be #SWG\Items(ref="#/definitions/OrderItem")
Ps. Checking the intermediate format (the swagger.json) can provide insight into what going wrong.
My requirement is to implement a multiple fileupload field in TYPO3 Front-end Extension. Here is what I've used for a single file upload.
My Fields in Model
/**
* angebotuploaden
*
* #var \TYPO3\CMS\Extbase\Domain\Model\FileReference
*/
protected $angebotuploaden = NULL;
/**
* Returns the angebotuploaden
*
* #return \TYPO3\CMS\Extbase\Domain\Model\FileReference $angebotuploaden
*/
public function getAngebotuploaden() {
return $this->angebotuploaden;
}
/**
* Sets the angebotuploaden
*
* #param \TYPO3\CMS\Extbase\Domain\Model\FileReference $angebotuploaden
* #return void
*/
public function setAngebotuploaden(\TYPO3\CMS\Extbase\Domain\Model\FileReference $angebotuploaden) {
$this->angebotuploaden = $angebotuploaden;
}
Now I face issues in implementing multiple file-uploads for this field. Please help me to sort it out.
Use ObjectStorage to get an 1:n-Relation to the FileReference model. In your model that could look like this:
/**
* uploadFiles
*
* #var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\FileReference>
* #cascade remove
*/
protected $uploadFiles = NULL;
/**
* __construct
*/
public function __construct() {
//Do not remove the next line: It would break the functionality
$this->initStorageObjects();
}
/**
* Initializes all ObjectStorage properties
* Do not modify this method!
* It will be rewritten on each save in the extension builder
* You may modify the constructor of this class instead
*
* #return void
*/
protected function initStorageObjects() {
$this->uploadFiles = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
}
/**
* Adds a UploadFile
*
* #param \TYPO3\CMS\Extbase\Domain\Model\FileReference $uploadFile
* #return void
*/
public function addUploadFile(\TYPO3\CMS\Extbase\Domain\Model\FileReference $uploadFile) {
$this->uploadFiles->attach($uploadFile);
}
/**
* Removes a UploadFile
*
* #param \TYPO3\CMS\Extbase\Domain\Model\FileReference $uploadFileToRemove The UploadFile to be removed
* #return void
*/
public function removeUploadFile(\TYPO3\CMS\Extbase\Domain\Model\FileReference $uploadFileToRemove) {
$this->uploadFiles->detach($uploadFileToRemove);
}
/**
* Returns the uploadFiles
*
* #return \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\FileReference> $uploadFiles
*/
public function getUploadFiles() {
return $this->uploadFiles;
}
/**
* Sets the uploadFiles
*
* #param \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\FileReference> $uploadFiles
* #return void
*/
public function setUploadFiles(\TYPO3\CMS\Extbase\Persistence\ObjectStorage $uploadFiles) {
$this->uploadFiles = $uploadFiles;
}
There're still more things to do, especially in TCA, but I don't know them in detail because I didn't use that yet. See Hemult Hummels Upload Example an this question for more detailed information.
I need to put two objects in one form with fluid.
The background is: I have a userDomain and a ordering object. Both are not persistent. I want to send these two objects to an action without making one of them persistent. The userDomain object is handled by the form, the other is assigned to the view. If I add the ordering object to the arguments section in the Form, Typo3 throws me this error:
Oops, an error occurred!
Could not serialize Domain Object Whmcs\Registration\Domain\Model\Ordering. It is neither an Entity with identity properties set, nor a Value Object.
More information regarding this error might be available online.
This is because the object is non-persistent and does not have any ID.
So the question is, how I do pass these two objects to the next action?
In order to pass non persistent objects between multiple actions, I would suggest that you store the objects serialized in a TYPO3 session variable. Doing so, you can restore the objects in the target action.
Below you find a working example which can also be found here.
<?php
namespace derhansen\ValidationExamplesNew\Controller;
/***************************************************************
* Copyright notice
*
* (c) 2013 Torben Hansen <derhansen#gmail.com>
*
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
/**
* Multiple Steps Controller
*
* #package validation_examples_new
* #license http://www.gnu.org/licenses/gpl.html GNU General Public License, version 3 or later
*
*/
class MultipleStepsController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController {
/**
* addressdataRepository
*
* #var \derhansen\ValidationExamplesNew\Domain\Repository\AddressdataRepository
* #inject
*/
protected $addressdataRepository;
/**
* API Service
*
* #var \derhansen\ValidationExamplesNew\Service\ExternalApiService
* #inject
*/
protected $apiService;
/**
* Step1
*
* #param \derhansen\ValidationExamplesNew\Domain\Model\Step1Data $step1data
* #dontvalidate $step1data
*/
public function step1Action(\derhansen\ValidationExamplesNew\Domain\Model\Step1Data $step1data = NULL) {
/* Check if step1data is available in session */
if ($GLOBALS['TSFE']->fe_user->getKey('ses', 'step1data') && $step1data == NULL) {
$step1data = unserialize($GLOBALS['TSFE']->fe_user->getKey('ses', 'step1data'));
}
$this->view->assign('step1data', $step1data);
}
/**
* Step1 redirect action
*
* #param \derhansen\ValidationExamplesNew\Domain\Model\Step1Data $step1data
*/
public function step1redirectAction(\derhansen\ValidationExamplesNew\Domain\Model\Step1Data $step1data) {
$GLOBALS['TSFE']->fe_user->setKey('ses', 'step1data', serialize($step1data));
$GLOBALS['TSFE']->fe_user->storeSessionData();
$this->redirect('step2');
}
/**
* Step2
*
* #param \derhansen\ValidationExamplesNew\Domain\Model\Step2Data $step2data
* #dontvalidate $step2data
*/
public function step2Action(\derhansen\ValidationExamplesNew\Domain\Model\Step2Data $step2data = NULL) {
/* Check if step2data is available in session */
if ($GLOBALS['TSFE']->fe_user->getKey('ses', 'step2data') && $step2data == NULL) {
$step2data = unserialize($GLOBALS['TSFE']->fe_user->getKey('ses', 'step2data'));
}
/* Set external validations errors if available */
$this->setApiValidationErrors('step2');
$this->view->assign('step2data', $step2data);
}
/**
* Step2 redirect action
*
* #param \derhansen\ValidationExamplesNew\Domain\Model\Step2Data $step2data
*/
public function step2redirectAction(\derhansen\ValidationExamplesNew\Domain\Model\Step2Data $step2data) {
$GLOBALS['TSFE']->fe_user->setKey('ses', 'step2data', serialize($step2data));
$GLOBALS['TSFE']->fe_user->storeSessionData();
$this->redirect('step3');
}
/**
* Step3
*
* #param \derhansen\ValidationExamplesNew\Domain\Model\Step3Data $step3data
* #dontvalidate $step3data
*/
public function step3Action(\derhansen\ValidationExamplesNew\Domain\Model\Step3Data $step3data = NULL) {
/* Check if step3data is available in session */
if ($GLOBALS['TSFE']->fe_user->getKey('ses', 'step3data') && $step3data == NULL) {
$step3data = unserialize($GLOBALS['TSFE']->fe_user->getKey('ses', 'step3data'));
}
/* Set external validations errors if available */
$this->setApiValidationErrors('step3');
$this->view->assign('step3data', $step3data);
}
/**
* Step3 redirect action
*
* #param \derhansen\ValidationExamplesNew\Domain\Model\Step3Data $step3data
*/
public function step3redirectAction(\derhansen\ValidationExamplesNew\Domain\Model\Step3Data $step3data) {
$GLOBALS['TSFE']->fe_user->setKey('ses', 'step3data', serialize($step3data));
$GLOBALS['TSFE']->fe_user->storeSessionData();
$this->redirect('create');
}
/**
* Create Action
*
* #return void
*/
public function createAction() {
$addressdata = $this->getAddressdataFromSession();
/* get validation results from API */
$apiresults = $this->apiService->validateMultipleSteps($addressdata);
if (count($apiresults) > 0) {
/* Save results to a session variable */
$GLOBALS['TSFE']->fe_user->setKey('ses', 'apiresults', $apiresults);
$GLOBALS['TSFE']->fe_user->storeSessionData();
/* Redirect to step with validation errors */
if (array_key_exists('step2', $apiresults)) {
$this->redirect('step2');
}
if (array_key_exists('step3', $apiresults)) {
$this->redirect('step3');
}
}
$this->addressdataRepository->add($addressdata);
$this->cleanUpSessionData();
$this->view->assign('message', 'Addressdata has been created');
}
/**
* Collects the addressdata from the multiple steps form stored in session variables
* and returns an addressdata object.
*
* #return \derhansen\ValidationExamplesNew\Domain\Model\Addressdata
*/
protected function getAddressdataFromSession() {
/** #var \derhansen\ValidationExamplesNew\Domain\Model\Step1Data $step1data */
$step1data = unserialize($GLOBALS['TSFE']->fe_user->getKey('ses', 'step1data'));
/** #var \derhansen\ValidationExamplesNew\Domain\Model\Step2Data $step2data */
$step2data = unserialize($GLOBALS['TSFE']->fe_user->getKey('ses', 'step2data'));
/** #var \derhansen\ValidationExamplesNew\Domain\Model\Step3Data $step3data */
$step3data = unserialize($GLOBALS['TSFE']->fe_user->getKey('ses', 'step3data'));
/** #var \derhansen\ValidationExamplesNew\Domain\Model\Addressdata $addressData */
$addressData = $this->objectManager->get('derhansen\ValidationExamplesNew\Domain\Model\Addressdata');
$addressData->setFirstname($step1data->getFirstname());
$addressData->setLastname($step1data->getLastname());
$addressData->setStreet($step2data->getStreet());
$addressData->setStreetnr($step2data->getStreetnr());
$addressData->setZip($step3data->getZip());
$addressData->setCity($step3data->getCity());
return $addressData;
}
/**
* Removes all session variables from the multiple steps form
*
* #return void
*/
protected function cleanUpSessionData() {
$GLOBALS['TSFE']->fe_user->setKey('ses', 'step1data', '');
$GLOBALS['TSFE']->fe_user->setKey('ses', 'step2data', '');
$GLOBALS['TSFE']->fe_user->setKey('ses', 'step3data', '');
$GLOBALS['TSFE']->fe_user->setKey('ses', 'apiresults', '');
$GLOBALS['TSFE']->fe_user->storeSessionData();
}
/**
* Sets validation errors for fields in the given step
*
* #param string $step The step
* #return void
*/
protected function setApiValidationErrors($step) {
$apiresults = $GLOBALS['TSFE']->fe_user->getKey('ses', 'apiresults');
if (array_key_exists($step, $apiresults)) {
/* Set Form Errors manually - get results from property mapper and add new errors */
$result = $this->getControllerContext()->getRequest()->getOriginalRequestMappingResults();
/* Add validation errors */
foreach ($apiresults[$step] as $key => $value) {
$error = $this->objectManager->get('TYPO3\\CMS\\Extbase\\Validation\Error',
$apiresults[$step][$key], time());
$result->forProperty($step . 'data.' . $key)->addError($error);
}
$this->getControllerContext()->getRequest()->setOriginalRequestMappingResults($result);
}
}
}
?>
This example is part of a multiple step form validation example, but uses TYPO3 session variables in order to store the input of each form step.
I'm building an application using ZF2 and Doctrine2.
The ideia is to have a base app entity (lets call it UserEntity).
But in one Module A, I will have another UserEntity-like entity that will "upgrade" the base one, with new fields. And another Module B that will add more fields.
Ex:
BaseUserEntity {
protected $id;
// ...
}
ModuleAUserEntity extends BaseUserEntity {
protected moduleAId;
}
ModuleBUserEntity extends BaseUserEntity {
protected moduleBUserName;
}
Is it possible, somehow, to get a method so when I call UserEntity, it will return the full, upgraded-by-module, entity? Ex:
UserEntity {
protected $id;
// ...
protected moduleAId;
protected moduleBUserName;
}
Is there another way to achieve something like this? The possibility to "extension" of an entity?
I have 2 different approaches:
1.First one:
you should take a look at:
http://docs.doctrine-project.org/en/latest/reference/inheritance-mapping.html
thats the legitimate and recommend by doctrine way of doing this.
2. Second one
If you dont want doctrine to mess with the database, you can use a different aproach:
Create an interface that defines the common behavior of all classes
Write your base class, implementing that behavior.
write your child classes, implementing the interface, containing the new methods, and wrapping an instance of the base class
You implement the methods that are defined in the interface, but since they are already implemented in the parent class, you just bypass the call to the wrapped object.
So, you are using composition over inheritance to avoid doctrine (and probably you) to get crazy
In order to have a really clean behavior with doctrine, the database that i imagine is:
a table with the parent entity
a table with the child entity, containing
a foreign key with the id of the related parent entity (this is, the row in the parent table that contains the values asociated to this, since the child has to have the parent and the child fields)
all the extra columns
For instance:
Interface:
namespace DBAL\Entity;
interface IProfesional
{
public function setName($name);
public function getName();
public function getId();
}
Parent class:
namespace DBAL\Entity;
use Doctrine\ORM\Mapping as ORM;
use DBAL\Entity\User\IUserAware;
/**
* Profesional
*
* #ORM\Table(name="profesional")
* #ORM\Entity
*/
class Profesional implements IProfesional
{
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=45, nullable=true)
*/
private $name;
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* Set nombre
*
* #param string $nombre
* #return Profesional
*/
public function setName($nombre)
{
$this->name = $nombre;
return $this;
}
/**
* Get nombre
*
* #return string
*/
public function getNombre()
{
return $this->name;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
}
child class:
namespace DBAL\Entity;
use DBAL\Entity\User\IUserAware;
use Doctrine\ORM\Mapping as ORM;
/**
* Jugador
*
* #ORM\Table(name="jugador")
* #ORM\Entity(repositoryClass="DBAL\Repository\JugadorRepository")
*/
class Player implements IProfesional
{
/**
* #var integer
*
* #ORM\Column(name="profesional_id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var \Profesional
*
* #ORM\OneToOne(targetEntity="Profesional")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="profesional_id", referencedColumnName="id", unique=true)
* })
*/
private $profesional;
/**
* Constructor: you create an empty Profesional,
so you are sure you will never use a reference to an in-existent object.
But anyways, if this is an entity loaded from the database by doctrine,
doctrine will fill that field whith an actual professional from the parent table,
based in the foreign key id
*/
public function __construct()
{
if(!isset($id)){
$this->profesional=new Profesional();
}
}
/**
* Set profesional
*
* #param \Profesional $profesional
* #return Jugador
*/
public function setProfesional( Profesional $profesional = null)
{
$this->profesional = $profesional;
return $this;
}
/**
* Get profesional
*
* #return \Profesional
*/
public function getProfesional()
{
return $this->profesional;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->profesional->getId();
}
///New fields, for instance:
/**
* #var integer
*
* #ORM\Column(name="height", type="integer", nullable=true)
*/
private $height;
public function getHeight()
{
return $this->height;
}
public function setHeight($h)
{
$this->height=$h;
}
}
What are the possible causes of EntityNotFoundException while accessing the proxy class properties in doctrine 2? Anyway, the following is my entities' structure:
/**
* #ORM\Table(name="comments")
*
* #ORM\InheritanceType("JOINED")
* #ORM\DiscriminatorColumn(name="comment_type", type="smallint")
* #ORM\DiscriminatorMap({
* 1 = "VisitorComment",
* 2 = "MemberComment"
* })
*/
class Comment
{
//with common properties of its subclasses
}
subclasses are as follows:
/**
* #ORM\Table(name="member_comments")
*/
class MemberComment extends Comment
{
/**
* owning side
*
* #var Member $author
*
* #ORM\ManyToOne(targetEntity="Member")
* #ORM\JoinColumn(name="author_id", referencedColumnName="id", nullable=false)
*/
private $author;
/**
* Set author
*
* #param Member $author
*/
public function setAuthor($author)
{
$this->author = $author;
}
/**
* Get author
*
* #return Member
*/
public function getAuthor()
{
return $this->author;
}
}
/**
* #ORM\Table(name="visitor_comments")
*/
class VisitorComment extends Comment
{
/**
* owning side
*
* #var Visitor $author
*
* #ORM\ManyToOne(targetEntity="Visitor")
* #ORM\JoinColumn(name="author_id", referencedColumnName="id", nullable=false)
*/
private $author;
/**
* Set author
*
* #param string $author
*/
public function setAuthor($author)
{
$this->author = $author;
}
/**
* Get author
*
* #return Visitor
*/
public function getAuthor()
{
return $this->author;
}
}
The exception occurs when I call $comment->getAuthor()->getFirstName() <assuming that author which is either a Member or Visitor entity has firstName property>. The getAuthor() in this case returns a proxy class of either VisitorProxy or MemberProxy.
Kindly help me. I'm still new to doctrine.
As Floricel found out, this can be caused by an invalid foreign key in a column that's points to the table that the Proxy class references.
#Dave Lancea is right I changed a FK to not Null and then started getting this error, manually updated a broken record, making it point to an existing entity and problem gone.