In a Silverstripe (version 3) model admin, how can I get the collection of fields from a different model so as to add them to this model's admin?
I have tried this using FieldList::addFieldsToTab:
$loremIpsumTab = Tab::create('LoremIpsum');
$fields->fieldByName('Root')->insertAfter('Main', $loremIpsumTab);
$loremIpsumFields = (
$this->LoremIpsum()->getCMSFields()
->fieldByName('Root.Main')->Fields());
$fields->addFieldsToTab('Root.LoremIpsum', $loremIpsumFields);
That creates the tab correctly, but moves the fields incorrectly: all the fields from 'Root.Main' are moved, not only those for the LoremIpsum model.
I had assumed this would interrogate the related LoremIpsum model for its CMS fields:
$this->LoremIpsum()->getCMSFields()
->fieldByName('Root.Main')->Fields()
So how can I move only those fields for the LoremIpsum model?
Hello and welcome to StackOverflow. What do you want to acchieve?
It seems you want to edit a has_one relation dataobject from your other dataobject. There are ready-to-use and tested modules for this scenario, e.g. https://github.com/stevie-mayhew/hasoneedit/tree/3.x , cause even if you manage to display the fields, SilverStripe assumes those values belong to the current model and not to a relation. Then you'll have extra work to save it back etc...
Some fields in your current model and in the LoremIpsum model have the same name, e.g. ID, Title, Created. This causes problems in your code above, cause you can only have one Field for e.g. ID in a Form.
The "hasoneedit" module overcomes this by prefixing the relation's fields.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I need to develop a custom form generator using Laravel.
That means there will be a GUI to select and customise the forms like Registration Form or Booking Form.User should be able to add/edit/delete different form controls, define it as mandatory, etc.
Here I am little confused to handle this in back-end. What is the better way to achieve this?
Or how can I implement a database architecture to use some metadata table which can be used to handle multiple items like Wordpress and is there any built-in Laravel functionalities to handle these meta objects?
And how the insert/update/delete handled in this metadata approach?
Here an insert should have only one row in the meta table. Suppose at the time of user registration, without saving the firstname and lastname in separate rows in the meta table, it should use some objects like this in a single row.
a:3:{s:9:"firstname";s:10:"irshad.far";s:8:"lastname";s:0:"";s:5:"_meta";a:7:{s:2:"ip";s:10:"14.99.80.3";s:9:"confirmip";s:10:"14.99.80.3";s:11:"confirmtime";d:1407932201;s:8:"signupip";s:10:"14.99.80.3";s:10:"signuptime";d:1407932201;s:4:"lang";s:2:"en";s:4:"form";s:7:"unknown";}}
Handling a table of meta data is fairly straight forward using Laravel's Eloquent relations. Let's say you have a users table in your database that contains:
id email password created_at updated_at deleted_at
If you want to keep it simple and not add all sorts of extra data to your users table you could create a meta table and then a link table user_meta to relate the two.
But what if you also have a posts table (as with Wordpress) and your posts also need meta data? Instead of also creating a posts_meta table to link your posts to their meta, we can use Laravels Eloquent relations and create some Polymorphic Relations.
The Database
Here's our setup, along with our users table (above) we have a posts table which has the fields:
id title content created_at updated_at deleted_at
We also have our meta table that follows the guidelines for a polymorphic relation:
id name value metable_id metable_type
//int meta key meta value post/user id resource ie post/user
Using this we could add meta for a post or user to our meta table like this:
id name value metable_id metable_type
------------------------------------------------------
1 nickname Steve 1 User
2 author Steve O 1 Post
All we need to do to grab this info from the database is define the relations in our respective models.
The Models
So now we have our DB ready we need to setup our models (one model for User, one for Post and one for Meta) with our polymorphic relationship. Our User and Post models are both going to use the same function to relate to our Meta model:
User.php
========================================
class User extends Eloquent {
public function meta()
{
return $this->morphMany('Meta', 'metable');
}
}
Post.php
========================================
class Post extends Eloquent {
public function meta()
{
return $this->morphMany('Meta', 'metable');
}
}
Now we define the inverse of those relations in our meta model:
Meta.php
========================================
class Meta extends Eloquent {
public function metable()
{
return $this->morphTo();
}
}
That's it!
Getting the data
Now all you need to do to get at the meta data for a user or post is:
// Load in a post with an id of 1 and get all it's related meta
$post = Post::find(1);
$meta = $post->meta;
If we were to return the meta object we might see something like:
[{"id":2,"metable_id":1,"metable_type":"Post","name":"author","value":"Steve O"}]
Onwards!
From here you can create helper functions like this one that checks if the meta you're after exists in the results:
public function hasMeta($key)
{
$meta = $this->meta;
foreach ($meta as $item):
if( $item->name == $key ) return true;
endforeach;
return false;
}
// Use it like:
if($post->hasMeta('author')){
// Display author
}
Read more about Laravels Eloquent relationships in the docs here: http://laravel.com/docs/eloquent-relationships
I once did something similar, my approach was to build a mini DB engine where forms are like tables and data is rows:
A form which describes the structure and design of a form:
Form {
id,
title,
layout,
...
}
Fields of the form with types and validation rules
Field {
formId,
name,
type (String, Date, Image, Integer, Double, List, ...),
pattern (Regex validation maybe),
...
}
Inserted data in a form is a row belonging to that form
Row {
id,
formId,
}
Each row is a group of entries to fields of the corresponding form that can be validated following the predefined rules.
Entry {
rowId,
fieldId,
value
}
Type and rules can be regrouped in another object so you can have dynamic types that you can manage.
Lists can have another object that stores choices and type of list (multi-select, mono-select)
Metadataobjects itself would be saved in one table. But performance-wise I think those object should their own data tables.
Approach 1)
These types of forms needs to be predefined and linked to a specific controller. This must be either so that there is only one controller for each type of form like Registeration, and only one user defined metadataobject can be in use at either time. This controller's table parameter would be set to point to a database table created specifically for that metadataobject (or perhaps same table could be migrated according to metadata but then that table should be empty).
Or 2) every metadataobject should have it's own controller created which points to the object's data table.
In each approach routes needs to be created to point to the one controller of each type at use in each time.
One dilemma is how to manage revisions of those objects. Perhaps each object might have a running number postfix, and have their own controllers and data tables created (then it might be easier to migrate even populated tables [then user would be notified on front-end if his action would result in data loss, like for example with deleting a form data field]).
Another part of this project is to create an intelligent generator engine for assembling the HTML, CSS, and JS code according to a metadataobject. The generated code can be saved to reside in the same table as the objects themselves, and when used should be cached in the backend for rendering views.
Such metadataobject must itself have a clever format, so that it composes of predefined pieces of settings which will be converted to functionality by the form generator code.
I am trying to create a database for storing cars information.
Cars can be categorized as new, used, or for rent.
Each type of car category has different attributes, because new cars have different features that are not needed for used, and same case for used and rent category. Attributes can be added, deleted in future using Application Admin side form manager for these 3 categories.
currently i am storing these in 1 product table with all the attributes required by these 3 categories.
PRODUCT(id,title,description,model,kilometer,enginsize,conditions,.....,.,...)
As form for each category is proposed to be managed from admin control, i am looking for a new scalable database.
current development:
all common attributes in Products
PRODUCT(pid,title,description,...)
CATEGORY(cid,cname) new,used,rent
form_field(formfield_id,name,type) to store all attributes that are not common
form_field_category(formfield_id,cid) to store category associated attributes
form_post_data(post_id,pid,formfield_id,value) to store submitted data
Any suggestions.
for what I understand you have 2 type of attributes: common and category-specific.
So doing something like:
PRODUCT(pid,title,description,...)
CATEGORY(cid,cname) new,used,rent
additional_info_category(aid, cid, name)
adition_info_data (adataid, aid, pid, data)
Should be enough, you just need to loead all the product info plus the fields in additional info that are related to the category.
You should have no issues adding new fields if they are category-specific but my question is: are you sure you won't need to add common fields?
What you need is called an Entity-Attribute-Value model.
If most of the values in table form_post_data are text, simply make it a varchar field. However if you're storing numeric values, choices and other types (things you might want to filter on), have a look at this article An alternative way of EAV modelling.
For you have properties that can have multiple values, have a look at this follow up article EAV multi-value fields.
I'm quite new to CakePHP so I'm wondering if anyone can help me with how to order my pages.
I have a table of products (with a Product model and products_controller).
I also have a table of categories (with a Category model and categories_controller).
The categories hasMany products.
Firstly, is the name categories incorrect to call it. According to CakePHP convention, what is the correct name to call it?
Secondly I would like the user to click on the products link and then be presented with a list of categories and finally, once he/she chooses a category be presented with the products in that category. How would this be laid out?
You're asking some pretty basic CakePHP stuff, I suggest you read the book, which outlines naming conventions, file structure and data retrieval to name a few things.
That being said, the name categories is correct, unless you want products to have more than one category, the relationship will be Product 'BelongsTo' Category.
To get category info inside the product controller you can just access it's find methods with $this->Product->Category->find();, but again I recommend you read through the CakePHP book as you go to build up our knowledge and learn more about the framework you're using.
You mean that categories is not a plural of category? I think so. Your table has to be named as 'categories'.
Secondly, I think that you need a Categories hasAndBelongsToMany Products (HABTM) in your model, so every Category has many Products, and also a Category belongs to many products.
Use the 'cake bake' command and you will see easily if it is what you want.
Hope it helped, althought I'm quite new in cakePHP as well...
Alf.
If you have categories tables in db, its controller would be categories_controller.php and the Products belongsTo Category will work if products belong to only one category. No need to HABTM relationship. See in cakephp the model files are in singular form and controller file are in plural form with controller attached with them. The tables are named in plural in db.
Regarding ur 2nd question, I think im not getting it exactly.
http://www.symfony-project.org/jobeet/1_4/Doctrine/en/12
The section "Virtual" columns details how to add columns to lists that belong to related models.
For example, I have 2 model classes: Company and User. A User is always a member of a Company.
For the User list I want to show the Company name, I can do this by adding a getter to the User class getCompanyName() and then in my generator.yml for the User module I would use the field name company_name.
This works and displays the Company name for each User, but how can I sort the list by using the Company name?
I solve this by adding a table_method, then when I implement the table method in the model, I innerjoin Company and order by a field in company. Not sure if this can be extended to sorting columns in the generated screens, but I think this works as well.
I'm new to zend framework but have made my first steps with it successfully.
Until now I have created some Zend_Forms which are mapping single records of my model
to the form fields. I have handled the forms with form classes for each case.
This works all very well until now.
Now I have the situation that I have to asign features to a product. Features and products are parts of my application. Features are stored in my database in three tables. For each feature there is one record in the third table.
First is the feature group where the name of the feature group is saved. Every feature should be asigned to a feature group.
Second table is the features table. This table has an foreign key to the feature group and the name of the feature.
Third table is some kind of many-to-many relation which connects features to products. This table has an aditional field which contains an optional value (beside the two foreign keys) for this unique feature of the product.
For example: if the product has a weight of 4,78 kg the value "4,78" is stored in the third table and the label "weight of %s kg" is stored in the second table. The feature group could be something like "physical attributes" had is saved in the first table.
To cut a long story short:
My problem is how to handle the case that I have to create and edit multiple database records in one form. The plan is to have a form with many checkboxes for each for a feature whereby features are thematicaly grouped. Every checkbox should have an aditional text field to input optional values.
you could make a custom form class that extends Zend_Form and use that for you classes.
It could take in the construct instances of your models and construct the form inputs based on that models.
After form validation in your controller you can do
$values = $form->getValues();
and use that array to populate your models again
You can try creating subforms (Zend_Form_SubForm) inside your form class. This can separate fields for different tables. For edition, in your controller, when you pull all the data from the tree tables, you can populate subforms that correspond to the tables.
You can try to extend Zend_Form to create your own elements.
You will be able to write a class that connects to DB to get attributes (features & products).
Assuming you wrote My_Form_Element_Features & My_Form_Element_Products classes, you can do $features = new My_Form_Features(); and then use the base class methods like getValues(), populate(), etc.
You can take a look there to start :
http://framework.zend.com/manual/en/zend.form.elements.html
http://smartycode.com/extending/database-aware-select-elements/
--
To answer to your comment, you can use :
Zend_Form::setElementsBelongTo($array):
More information can be found at Zend_Form Advanced manual page.