I've created a Backend Extension and extended fe_user by 4 additional fields.
I am Using TYPO3 7.6.13.
The 4 custom fields are visible in backendlists, but not the fields are not available in frontend.
Is there any "special" list I need to extend with my fields? My TCA Configuration as follows.
ExtensionManagementUtility::addTCAcolumns('fe_users', $temporaryColumns);
ExtensionManagementUtility::addToAllTCAtypes('fe_users', 'field1', '', 'after:image');
ExtensionManagementUtility::addToAllTCAtypes('fe_users', 'field2', '', 'after:field1');
ExtensionManagementUtility::addToAllTCAtypes('fe_users', 'field3', '', 'after:field2');
ExtensionManagementUtility::addToAllTCAtypes('fe_users', 'field4', '', 'after:field3');
ExtensionManagementUtility::addToAllTCAtypes(
'fe_users',
'field1, field2, field3, field4'
);
Is there more todo or did I ran in some sort of bug?
To extend an existing extbase model the folllowing steps are needed:
Add the fields to your database in ext_tables.sql
Add the fields to TCA in Configuration/TCA/Overrides/table_name.php
This should be enough to use the fields inside the TYPO3 backend.
For frontend rendering your need two more steps:
Extend the Extbase model (Property, Getter and Setter)
Tell extbase to use your new model with TypoScript: config.tx_extbase.persistence.classes
As far as I understand your did the first 3 steps, but maybe missed the last one?
Full example (ext_typoscript_setup.txt, normal TypoScript file should also work):
config.tx_extbase {
persistence {
classes {
TYPO3\CMS\Extbase\Domain\Model\FrontendUser {
subclasses {
0 = YourVendor\YourextNamespace\Domain\Model\YourClass
}
}
}
}
}
This should be enough for many tables, but fe_users uses the recordType field. To configure this you need the following TypoScript snippet (same file as the config.tx_extbase config):
config.tx_extbase {
persistence {
classes {
YourVendor\YourextNamespace\Domain\Model\YourClass {
mapping {
tableName = fe_users
recordType = 0
}
}
}
}
This forces extbase to ignore the recordType and always use your model.
Documentation/Full example (including recordType explanation): https://docs.typo3.org/typo3cms/ExtbaseFluidBook/6-Persistence/5-modeling-the-class-hierarchy.html
You have to add the fields to the model. In your domain you will have a fe_user repository which will be mapped to the real fe_user table.
If you add fields to fe_user you have to add them also to your fe_user model.
Did you think about that?
Related
Couldn't find this in the docs.
Is there any standard way, without creating a custom widget, or overriding the view template, to show a Many to Many relationships in a CRUD's showOperation in Backpack for Laravel? If the answer is NO, what would be your approach to implement it?
Let's say I have a Course Model, and a User model, and there is a Many to Many between both
class Course extends Model
{
public function students()
{
return $this->belongsToMany(User::class, 'course_students');
}
}
class User extends Model
{
public function courses()
{
return $this->belongsToMany(Course::class, 'course_students');
}
}
In the Show Operation for the Course. How do I show a Table with all students?
Indeed, you can use the relationship column for this
Excerpt:
Output the related entries, no matter the relationship:
1-n relationships - outputs the name of its one connected entity;
n-n relationships - enumerates the names of all its connected entities;
Its name and definition is the same as for the relationship field
type:
[
// any type of relationship
'name' => 'tags', // name of relationship method in the model
'type' => 'relationship',
'label' => 'Tags', // Table column heading
// OPTIONAL
// 'entity' => 'tags', // the method that defines the relationship in your Model
// 'attribute' => 'name', // foreign key attribute that is shown to user
// 'model' => App\Models\Category::class, // foreign key model
],
Backpack tries to guess which attribute to show for the related item.
Something that the end-user will recognize as unique. If it's
something common like "name" or "title" it will guess it. If not, you
can manually specify the attribute inside the column definition, or
you can add public $identifiableAttribute = 'column_name'; to your
model, and Backpack will use that column as the one the user finds
identifiable. It will use it here, and it will use it everywhere you
haven't explicitly asked for a different attribute.
I'm creating an extbase extension to handle very simple product orders.
The model is:
Order --1:n--> OrderItem --1:1--> Product
To order a selection of products, the customer goes to checkout page and uses a Fluid based Order form. All selected products are available in the fluid template as {products}.
The OrderController->createAction processes new Orders by creating OrderItems from the given Products.
Writing the code I'd like to have would look like this:
class OrderController
{
public function create(Order $order, array $products)
{
foreach ($products as $product) {
$orderItem = new OrderItem()
->setProduct($product)
->setPrice($product->getPrice());
$order->addOrderItem($orderItem);
}
$this->orderRepository->add($order);
}
}
How to assign products to a Fluid form fields, in order to receive them as ControllerAction array argument?
How to trigger extbase to automagically provide an array of product objects to the ControllerAction?
I wonder if it is even possible to simplify the Controller createAction like shown below and assemble objects elsewhere:
public function create(Order $order) {
$this->orderRepository->add($order);
}
My suggestion for the fluid template would be:
// basic form with the order as main object
<f:form action="create" object="{order}">
// each order item with a product, using index to have no array with an empty index (Extbase does not like that)
<f:for each="{products}" key="index" as="product">
// Here you can set the product
<f:form.hidden prpoerty="orderItems.{index}.product" value="{product} />
</f:for>
</f:form>
This should be enough to use your single-line create action.
You can change the field type from select to whatever you want, but the __identity is mandatory to say Extbase which record it has to link.
When you want the orderItems to be new created, you need to remove the __identity field.
I have a postgres table in which I have some "defaulted" fields like date_created which automatically receives a current_timestamp as default.
or the ID field which gets it's value from a sequence defined in the database.
What would be (if possible) the syntax to tell the ORM module to not include these two fields when generating an INSERT statement ?
You can use a function as 2nd parameter to remove the fields:
$this->copyfrom('POST',function($val) {
unset($val['ID']);
unset($val['date_created']);
return $val
});
or to only copy allowed fields from the POST array:
$this->copyfrom('POST',function($val) {
return array_intersect_key($val, array_flip(array('name','age')));
});
Assuming you are using an HTML form to add new records into the tables, follow the steps below;
In the form, omit these 'defaulted' fields, i.e. add only the fields that you want to submit
Create a model with a function similar to below
public function add() {
$this->copyFrom ( 'POST' );
$this->save ();
}
Create a route that links the form to this function
I need to have a model called 'Package' which can have one or more children of several different types. For example, a package can contain guides, as well as forms and other content types (some of which will be added later). Each of these content items, from different tables, can be in multiple packages. So I have the following schema:
Package table
=============
id
name
....
PackageContent table
=============
id
packageId
contentType
contentId
Guide table
=============
id
name
...
Form table
=============
id
name
How can I define the 'content' association for my packages in my Package.js model file in sails.js? I have not been able to find any information on combination foreign keys in sails.js or Waterline. I would hope to find something along the lines of:
// models/Package.js
module.exports = {
attributes = {
name: 'text',
....
content: {
through: 'PackageContent',
collection: contentType,
via: 'contentId'
}
}
};
I have a similar problem recently. My solution is to create different foreign keys in the intermediary model and set attributes as 'required:false'. In your example, the PackageContent table could look like this:
//PackageContent.js
module.exports={
attributes={
package:{
model:'package',
},
guide:{
model:'guide'
require:false
},
form:{
model:'form'
require:false
}
//other attributes...
}
}
In order to avoid duplicated package+content combination, you may need to write a beforeValidate method to check the duplication. I am not sure if this is a 'good design', but it solves the probelm
How do I configure Sails.js / Waterline to default to pluralized relational database table names that correspond to singular models (same as Rails)?
(E.g. A model called 'Person' should default to a PostgreSQL table called 'people'.)
Just add the tableName: 'people' property to the model:
// Person.js
module.exports = {
tableName: 'people',
attributes: {
id: 'integer',
name: 'string'
}
};
There does not appear to be a global setting in Sails.js that pluralizes database table names automatically for models with singular names.
You can put this in your blueprints.js or local.js file:
blueprints: { // if in your local.js wrap in this object
pluralize: true
}
It won't get it right every time, so the tableName property is still useful for odd cases, but for most pluralized terms it will work.