In my service class I have
/**
* #var \TYPO3\CMS\Extbase\Domain\Repository\FrontendUserRepository
* #inject
*/
protected $frontendUserRepository;
/**
* #var \TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager
* #inject
*/
protected $persistenceManager;
And in a function:
$objectManager = GeneralUtility::makeInstance('TYPO3\CMS\Extbase\Object\ObjectManager');
$this->frontendUserRepository = $objectManager->get('TYPO3\\CMS\\Extbase\\Domain\\Repository\\FrontendUserRepository');
$frontendUser = new FrontendUser();
$frontendUser->setUsername($bla);
$frontendUser->setPassword($bliep);
$this->frontendUserRepository->add($frontendUser);
$this->persistenceManager = $objectManager->get('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\PersistenceManager');
$this->persistenceManager->persistAll();
Then I get error
Table 'dbname.tx_extbase_domain_model_frontenduser' doesn't exist
How can I store the new user in the 'fe_users' table?
Make a table mapping in your TypoScript setup extbase configuration:
config.tx_extbase {
persistence {
classes {
TYPO3\CMS\Extbase\Domain\Model\FrontendUser {
mapping {
tableName = fe_users
}
}
}
}
}
Related
I'm trying to implement a plugin to add sales representative data to my shop and associate this data to users.
On this context (users and sales representative) I have:
sales_rep - Sales representative table
sales_rep_user - Relation between User and Sales Representative
1st For the swg_sales_rep and swg_sales_rep_user relation (OneToMany) I could create that without problems
SwgSalesRepresentative.php
...
**
* #ORM\Entity
* #ORM\Table(name="swg_sales_rep")
*/
class SwgSalesRepresentative extends ModelEntity
{
...
/**
* INVERSE SIDE
*
* #var \Doctrine\Common\Collections\ArrayCollection
*
* #ORM\OneToMany(
* targetEntity="Shopware\CustomModels\SwagUserSalesRepresentative\SwgSalesRepresentative",
* mappedBy="salesRepresentative",
* orphanRemoval=true
* )
*/
protected $salesRepresentativeUsers;
...
SwgSalesRepresentativeUsers.php
/**
* #ORM\Entity
* #ORM\Table(name="swg_sales_rep_users")
*/
class SwgSalesRepresentativeUsers extends ModelEntity
{
...
/**
*
* #ORM\ManyToOne(targetEntity="Shopware\CustomModels\SwagUserSalesRepresentative\SwgSalesRepresentative")
* #ORM\JoinColumn(name="sales_rep_id", referencedColumnName="id")
*/
protected $salesRepresentative;
/**
* #return mixed
*/
public function getSalesRepresentative()
{
return $this->salesRepresentative;
}
/**
* #param $salesRepresentative
* #return ModelEntity
*/
public function setSalesRepresentative($salesRepresentative)
{
return $this->setManyToOne(
$salesRepresentative,
'\Shopware\CustomModels\SwagUserSalesRepresentative\SwgSalesRepresentative',
'salesRepresentativeUsers'
);
}
And after install I get my tables with foreign key ok.
For the relation between swg_sales_rep_user and s_user (OneToOne) I have problems. My first idea was extend the User model and add the additional logic we need. But this implies to overwrite my users table, take the risk to lose data.
What I did was create a SwgUser model that extends User model, like
SwgSalesRepresentativeUsers.php
/**
* #ORM\Entity
* #ORM\Table(name="swg_sales_rep_users")
*/
class SwgSalesRepresentativeUsers extends ModelEntity
{
...
/**
* #var \Shopware\CustomModels\SwagUserSalesRepresentative\SwgUser $user
*
* #ORM\OneToOne(targetEntity="Shopware\CustomModels\SwagUserSalesRepresentative\SwgUser", inversedBy="salesRepresentative")
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
protected $user;
/**
* #return mixed
*/
public function getUser()
{
return $this->user;
}
/**
* #param $user
* #return ModelEntity
*/
public function setUser($user)
{
return $this->setOneToOne(
$user,
'\Shopware\CustomModels\SwagUserSalesRepresentative\SwgUser',
'user',
'salesRepresentative'
);
}
...
SwgUser.php
/**
* #ORM\Entity
* #ORM\Table(name="s_user")
*/
class SwgUser extends User
{
/**
*
* #ORM\OneToOne(targetEntity="Shopware\CustomModels\SwagUserSalesRepresentative\SwgSalesRepresentativeUsers", mappedBy="user")
*/
protected $salesRepresentative;
...
And bootstrap.php install/uninstall looks like
/**
* Install method
*
* #return bool
*/
public function install()
{
$this->updateSchema();
return true;
}
/**
* Uninstall method
*
* #return bool
*/
public function uninstall()
{
$this->registerCustomModels();
$em = $this->Application()->Models();
$tool = new \Doctrine\ORM\Tools\SchemaTool($em);
$classes = array(
$em->getClassMetadata('Shopware\CustomModels\SwagUserSalesRepresentative\SwgSalesRepresentative'),
$em->getClassMetadata('Shopware\CustomModels\SwagUserSalesRepresentative\SwgUser'),
$em->getClassMetadata('Shopware\CustomModels\SwagUserSalesRepresentative\SwgSalesRepresentativeUsers')
);
$tool->dropSchema($classes);
return true;
}
/**
* Creates the database scheme from existing doctrine models.
*
* Will remove the table first, so handle with care.
*/
protected function updateSchema()
{
$this->registerCustomModels();
$em = $this->Application()->Models();
$tool = new \Doctrine\ORM\Tools\SchemaTool($em);
$classes = array(
$em->getClassMetadata('Shopware\CustomModels\SwagUserSalesRepresentative\SwgSalesRepresentative'),
$em->getClassMetadata('Shopware\CustomModels\SwagUserSalesRepresentative\SwgUser'),
$em->getClassMetadata('Shopware\CustomModels\SwagUserSalesRepresentative\SwgSalesRepresentativeUsers')
);
try {
$tool->dropSchema($classes);
} catch (Exception $e) {
//ignore
}
$tool->createSchema($classes);
}
I tried to use the unidirectional association mapping and it creates the field but not the relation with s_user table (Foreign key).
So question is, how can I create relations with core tables on shopware without have to recreate (drop/create) the core tables?
Is it possible to alter tables programmatically? what is the best approach for these needs. Do you have an example that demonstrate this?
Thanks for helping.
there is no way to create bidirectional associations with shopware core tables yet. You can have unidirectional associations for sure, but you will not be able to add relational properties to core entities so far.
Except you intend to modify the shopware core itself which should be avoided at any time.
The only - and very tiny - possibility would be by trying to create a relation over a core entities attribute table which is quite "magic stuff" in shopware.
I have 3 tables:
Category ( id, name)
Category_Tournament (category_id, tournament_id) --> pivot table
Category_Tournament_User (category_id, tournament_id, user_id, confirmed)
Category is the list of available categories
Category_Tournament is the list of categories the admin configured
Category_tournament_User is the categories the user has registred
To get all categories in the tournament, I can do it easily with:
tournament->categories
defining a belongsToMany relationship in tournament model
What I don't know how to define relationship with the last table.
What I need is the user click on several categories, and I can run something like:
tournament->user_categories->sync($userCategories)
where I should sync table Category_Tournament_User ( with category_id, tournament_id, user_id)
What is the best way to achieve it???
EDIT:
Model Tournament:
class Tournament extends Model
{
protected $table = 'tournament';
public $timestamps = true;
protected $fillable = [
'name',
'date',
'type',
];
/**
* A tournament is owned by a user
*
* #return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function owner()
{
return $this->belongsTo('App\User', 'user_id','id');
}
/**
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function categories()
{
return $this->belongsToMany('App\Category')
->withTimestamps();
}
}
Model Category
class Category extends Model
{
protected $table = 'category';
public $timestamps = true;
protected $fillable = [
'id',
'name',
];
public function tournaments()
{
return $this->belongsToMany('App\Tournament');
}
}
Model User:
class User extends Model implements AuthenticatableContract, CanResetPasswordContract
{
use Authenticatable, Authorizable, CanResetPassword, HasRole;
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'users';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = ['name','firstname','lastname','email', 'password','avatar',country_id','role_id',,'provider','provider_id','verified'];
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = ['password', 'remember_token'];
/**
* Boot the model.
*
* #return void
*/
public static function boot()
{
parent::boot();
static::creating(function ($user) {
$user->token = str_random(30);
});
}
public function role()
{
return $this->belongsTo('App\Role');
}
public function settings()
{
return $this->hasOne('App\Settings');
}
public function invites()
{
return $this->hasMany('App\Invite', 'email','email');
}
public function country()
{
return $this->belongsTo('Webpatser\Countries\Countries');
}
/**
* A user can have many tournaments
*
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function tournaments()
{
return $this->hasMany('App\Tournament');
}
}
You have many to many relationship here between User and Category_Tournament and you should take a look in documentation exactly at Many To Many.
I think you don't need to to have Category_Tournament_User table. and you can't make a Model for it in Laravel. you only need to a table user_tournament. and you should define relation(foreign key) on migration, like this:
Schema::create('user_tournament', function(Blueprint $table){
$table->engine = 'InnoDB';
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->integer('tournament_id')->unsigned();
$table->unique(['tournament_id', 'user_id']);//You can omit this
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade')->onUpdate('cascade');
$table->foreign('tournament_id')->references('id')->on('tournaments')->onDelete('cascade')->onUpdate('cascade');
$table->nullableTimestamps();
});
then you can use this code:
user->tournaments->sync($userCategories);
I have integrated zend with doctrine, and everything works but when I start to genereate entities using doctrine cli: doctrine orm:generate-entities
I get php Entities class without #ORM, #Entity in comments.
Example:
<?php
use Doctrine\ORM\Mapping as ORM;
/**
* Tag
*/
class Tag
{
/**
* #var string $tagName
*/
private $tagName;
/**
* #var \Doctrine\Common\Collections\ArrayCollection
*/
private $eventevent;
/**
* Constructor
*/
public function __construct()
{
$this->eventevent = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Get tagName
*
* #return string
*/
public function getTagName()
{
return $this->tagName;
}
/**
* Add eventevent
*
* #param Event $eventevent
* #return Tag
*/
public function addEventevent(\Event $eventevent)
{
$this->eventevent[] = $eventevent;
return $this;
}
/**
* Remove eventevent
*
* #param Event $eventevent
*/
public function removeEventevent(\Event $eventevent)
{
$this->eventevent->removeElement($eventevent);
}
/**
* Get eventevent
*
* #return Doctrine\Common\Collections\Collection
*/
public function getEventevent()
{
return $this->eventevent;
}
}
I've loaded up the Doctrine MongoODM Module for zf2. I have got the document manager inside my controller, and all was going well until I tried to persist a document. It fails with this error:
"[Semantical Error] The annotation "#Document" in class SdsCore\Document\User was never imported."
It seems to fail on this line of DocParser.php
if ('\\' !== $name[0] && !$this->classExists($name)) {
It fails because $name = 'Document', and the imported annotation class is 'Doctrine\ODM\MongoDB\Mapping\Annotations\Doctrine'
Here is my document class:
namespace SdsCore\Document;
/** #Document */
class User
{
/**
* #Id(strategy="UUID")
*/
private $id;
/**
* #Field(type="string")
*/
private $name;
/**
* #Field(type="string")
*/
private $firstname;
public function get($property)
{
$method = 'get'.ucfirst($property);
if (method_exists($this, $method))
{
return $this->$method();
} else {
$propertyName = $property;
return $this->$propertyName;
}
}
public function set($property, $value)
{
$method = 'set'.ucfirst($property);
if (method_exists($this, $method))
{
$this->$method($value);
} else {
$propertyName = $property;
$this->$propertyName = $value;
}
}
}
Here is my action controller:
public function indexAction()
{
$dm = $this->documentManager;
$user = new User();
$user->set('name', 'testname');
$user->set('firstname', 'testfirstname');
$dm->persist($user);
$dm->flush;
return new ViewModel();
}
I didn't yet work on the DoctrineMongoODMModule, but I'll get to it next week. Anyway, you are still using the "old way" of loading annotations. Most of the doctrine projects are now using Doctrine\Common\Annotations\AnnotationReader, while your #AnnotationName tells me that you were using the Doctrine\Common\Annotations\SimpeAnnotationReader. You can read more about it at the Doctrine\Common documentation
So here's how to fix your document:
<?php
namespace SdsCore\Document;
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
/** #ODM\Document */
class User
{
/**
* #ODM\Id(strategy="UUID")
*/
private $id;
/**
* #ODM\Field(type="string")
*/
private $name;
/**
* #ODM\Field(type="string")
*/
private $firstname;
/* etc */
}
I am starting my first Zend Framework + Doctrine 2 project and I have a question. I use PostgreSQL 9 and Apache 2.2
I have the following entities (the names of the entities and attributes are just for this example):
<?php
namespace Xproject\Entities;
/**
* Entity1
* #Table()
* #Entity
*/
class Entity1
{
/***
* #var integer $ent1Code
* #Column(name="ent1Code", type="integer", length=4)
* #Id
* #GeneratedValue(strategy="IDENTITY")
*/
private $ent1Code;
/**
* #var decimal $att1
* #Column(name="att1", type="decimal")
*/
private $att1;
/**
* OWNING SIDE
* #var \Doctrine\Common\Collections\ArrayCollection
* #ManyToOne(targetEntity="Entity2", inversedBy="entity1")
* #JoinColumn(name="ent2Code", referencedColumnName="ent2Code")
*/
private $entity2;
/**
* UNIDIRECTIONAL
* #var \Doctrine\Common\Collections\ArrayCollection
* #ManyToOne(targetEntity="Entity3")
* #JoinColumn(name="ent3Code", referencedColumnName="ent3Code")
*/
private $entity3;
/**
* UNIDIRECTIONAL
* #var \Doctrine\Common\Collections\ArrayCollection
* #ManyToOne(targetEntity="Entity4")
* #JoinColumn(name="ent4Code", referencedColumnName="ent4Code")
*/
private $entity4;
public function __construct() {
$this->entity2 = new \Doctrine\Common\Collections\ArrayCollection();
$this->entity3 = new \Doctrine\Common\Collections\ArrayCollection();
$this->entity4 = new \Doctrine\Common\Collections\ArrayCollection();
}
public function getEnt1Code(){
return $this->ent1Code;
}
public function getAtt1(){
return $this->att1;
}
public function setAtt1($value){
$this->att1=$value;
}
public function addEntity2(Entity2 $value){
$value->addEntity1($this);
$this->entity2->add($value);
}
public function addEntity3(Entity3 $value){
$this->entity3->add($value);
}
public function addEntity4(Entity4 $value){
$this->entity4->add($value);
}
}
<?php
namespace Xproject\Entities;
/**
* Entity2
* #Table()
* #Entity
*/
class Entity2
{
/**
* #var integer $ent2Code
* #Column(name="ent2Code", type="integer", length=4)
* #Id
* #GeneratedValue(strategy="IDENTITY")
*/
private $ent2Code;
/**
* INVERSE SIDE
* #var entity1
* #OneToMany(targetEntity="Entity1", mappedBy="entity2")
*/
private $entity1;
public function __construct() {
$this->entity1 = new \Doctrine\Common\Collections\ArrayCollection();
}
public function getEnt2Code(){
return $this->ent2Code;
}
public function addEntity1(Entity1 $value){
$this->entity1->add($value);
}
}
<?php
namespace Xproject\Entities;
/**
* Entity3
* #Table()
* #Entity
*/
class Entity3
{
/**
* #var integer $ent3Code
* #Column(name="ent3Code", type="integer", length=4)
* #Id
* #GeneratedValue(strategy="IDENTITY")
*/
private $ent3Code;
/**
* #var string $att1
* #Column(name="att1", type="string", length=150)
*/
private $att1;
public function getEnt3Code(){
return $this->ent3Code;
}
public function getAtt1(){
return $this->att1;
}
public function setAtt1($value){
$this->att1=$value;
}
}
<?php
namespace Xproject\Entities;
/**
* Entity4
* #Table()
* #Entity
*/
class Entity4
{
/**
* #var integer $ent4Code
* #Column(name="ent4Code", type="integer", length=4)
* #Id
* #GeneratedValue(strategy="IDENTITY")
*/
private $ent4Code;
/**
* #var string $att1
* #Column(name="att1", type="string", length=150)
*/
private $att1;
public function getEnt4Code(){
return $this->ent4Code;
}
public function getAtt1(){
return $this->att1;
}
public function setAtt1($value){
$this->att1=$value;
}
}
Just to try if everything is working I use the following code in Xproject's indexController:
<?php
class IndexController extends Zend_Controller_Action
{
public function init()
{
$this->doctrine = Zend_Registry::get('doctrine');
$this->em = $this->doctrine->getEntityManager();
}
public function indexAction()
{
$ent2 = new Xproject\Entities\Entity2();
$this->em->persist($ent2);
$ent3 = new Xproject\Entities\Entity3();
$ent3->setAtt1('xyz');
$this->em->persist($ent3);
$ent4= new Xproject\Entities\Entity4();
$ent4->setAtt1('abc');
$this->em->persist($ent4);
//1st flush
$this->em->flush();
$ent1= new Xproject\Entities\Entity1();
$ent1->setAtt1(350.00);
$ent1->addEntity2(ent2);
$ent1->addEntity3(ent3);
$ent1->addEntity4(ent4);
$this->em->persist($ent1);
//2nd flush
//$this->em->flush();
}
}
The first flush works OK and everything is saved OK into the database, but if I use both the first and the second flush, the browser indicates an Application Error and $ent1 is not saved at all into the database.
Using a var_dump($ent1) I can see that the object $ent1 state is correct (att1 and all the collections are loaded OK).
Apache error log doesn't show any error or warning during the loading of this script.
I definitely think I am missing some important thing here related to the ArrayCollections and how they work when you flush them.
Am I missing something crucial?
Your relationships are all ManyToOne, so there should be no ArrayCollections involved.
Since there are no collections, you don't want to add stuff, you want to set stuff:
In Entity1:
public function setEntity2(Entity2 $entity2){
$this->entity2 = $entity2
return $this;
}
In your controller:
$entity1->setEntity2($entity2);
And that's it. Your calls like $this->entity2->add() are working, because you're initializing those properties as ArrayCollections. But doctrine is just ignoring them.
In other words, for a *ToOne relationship, the object properties are just the foreign entity type. Treat them like simple values, and set them via typical set*() mutator.