Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

Data Model Questions

Virtual "name" attribute


Reply

6 Posts   1485 Views

Avatar
Judge

21 February 2010 at 2:25pm (Last edited: 21 February 2010 2:32pm), Community Member, 79 Posts

If a data object has a "Name" attribute, then the name is displayed in the automatically generated default admin screens when listing data for that object. This is all nice and handy.

I have an object that does not have a Name attribute stored in the database, but instead I would like the name to be derived from other data in that object (e.g. for an address, the name could be the house number, street name and town concatenated). This only needs to be constructed when the object is fetched from the database, but then it needs to look like it originally came from the database so that it gets used in the admin screens.

Thinking as I write this, would the solution be to create my set of fields using the getCMSFields() method, including a mix of real database fields and non-database fields as required?

-- Jason

Edit: No. A 'ReadonlyField' with the name "Name" unfortunately does not appear in the default admin screens for that object.

Avatar
Hamish

21 February 2010 at 2:32pm Community Member, 712 Posts

Simply create a method called getName() that returns the name of the object.

Avatar
Judge

21 February 2010 at 2:50pm Community Member, 79 Posts

Perfect. Thank you.

I'm rewriting something that I started in Kohana. Already I've got more functionality in SS with under 100 lines of code than I managed in Kohana in over a thousand. I think it strikes the balance well between providing a decent programmers framework, and enough CMS functionality that you don't need to spend any time on getting the basic admin screens up and running.

Loving it so far :-)

-- Jason

Avatar
Judge

24 February 2010 at 12:26am (Last edited: 24 February 2010 1:23am), Community Member, 79 Posts

Hamish,

I've had some success with that method on most of my data objects, but one is giving me a strange error. The data model is simple enough:

class NaceTitles extends DataObject {
static $db = array(
'Title' => 'Varchar(255)',
'NaceField' => 'Int',
'NaceGroup' => 'Int',
'NaceSubGroup' => 'Int',
);

static $singular_name = 'NACE Title';
static $plural_name = 'NACE Titles';

// FIXME: Why is this erroring???
function getName() {
return 'xxx';
// return $this->NaceField . '.' . $this->NaceGroup . '.' . $this->NaceSubGroup;
}
}

The error I get, when trying to do a search in the admin screen is:

Error: "Uncaught Exception: Unable to traverse to related object field [Name] on [NaceTitles]" at line 2211 of /var/www/vhosts/.../httpdocs/sapphire/core/model/DataObject.php

I'm stumped as to what it could be. The code around the error implies that the model must have a "Name" attribute in order for this to work, but I have other working models that don't have a Name attribute.

Any clues?

-- Jason

Edit: if I add a 'Name' attribute to the model, then it works, i.e. 'Name' => 'Varchar'. However, I don't want a name attribute, so am puzzled as to why I'm getting this error. I have also tried changing the "Title" attribute to something less reserved (NaceTitle) and that makes no difference - same error.

Edit2: the only difference between the working and non-working data models that I can think of, is that this non-working model is a master object, and the working ones are all detail objects. Detail objects display differently to master objects (there are different icons on the RHS for a start) so that may be where the problem lies.

Avatar
Judge

24 February 2010 at 3:37am (Last edited: 24 February 2010 3:44am), Community Member, 79 Posts

I think this is a bug. At least, I can understand why it is happening, but SS could handle it easily without raising an error.

The problem is that SS makes assumptions on what fields are searchable. If you don't list the searchable fields in the model for AdminModel to use, it will assume that any mention of Name, Title, FirstName or Description will be searchable. So long as these fields are listed as a part of the data model, i.e. are real database columns, then it works fine.

However, if you create a virtual field called Name using the GetName() method, SS will assume that this should be searchable and will assume that it is a real database column. It fails when looking for the object that represents that database column.

The fix is to define your own set of searchable fields, including *only* those that exist in the database. For example:

class NaceTitles extends DataObject {
static $db = array(
'Title' => 'Varchar(255)',
'NaceField' => 'Int',
};

static $summary_fields = array(
'Name' => 'Name', // Displayed, but not in the database. We will generate this on-the-fly.
);

// Only allow searches on the title. Without this, SS errors trying to make Name searchable.
static $searchable_fields = array(
'Title',
);

// Now define the value of the constructed virtual column.
function getName() {
return $this->NaceField . ': ' . $this->Title;
}
}

This is actually a cut-down version of what really happens in my module, but it gives you an idea.

SS could handle this condition by not assuming Name is a database column if it happens to be a displayed column. There is the static db array it can use to check.

Edit: the column does not have to be called "Name" - it could be a Varchar of any name.

-- Jason

Avatar
SheaDawson

8 October 2012 at 2:52am Community Member, 46 Posts

Thanks for sharing that Judge, this problem has me up way too late and I can now finally retire for the day!