Hot answers tagged

14

Ok worked out a solution to the attributes. You can set them like this: array(AttributeType::String, 'column' => ColumnType::Text, 'required' => false) By defining the column, so hopefully this will help someone else.


8

Have you tried it? I'm pretty sure that's not going to work as Active Record is tied to the db connection in craft/config/db.php hanging off of craft()->db. You should be able to pull it off with a plugin that instantiates its own DbConnection, though and uses Query Builder instead of Active Record. Completely untested, but something like this: $...


6

I might be wrong here, but I don't think a model can be used to save entries. You populate a model, then populate a record with that model and save it. Once saved, you get data from the db as a record, then populate a model with it to pass that to a view, for instance. If everything works as it should, a record is never used outside the service.


5

If you use $model->getErrors() instead, it should return a multidimensional array of errors indexed by attribute name like so: array( 'email' => array( 'First email error.', 'Second email error.', ), 'firstName' => array( 'First firstName error.', ), ); Or you can get errors specifically for an attribute ...


5

Models are classes that contains abstractions of the reality, for example you could have the model car that contains the technical information about it, how many wheels it has and it's brand. Models are usually not supposed to contain any logic. So it's just a "container" with information Components are more like services that contains business logic to ...


4

Records can do that too (where that = hold data), but, according to Craft docs, Records should never ever leave Service layer. So, yes, you do need a model too.


4

Found an answer in the form of a customer validator class on the model: https://experiencehq.net/blog/the-definitive-guide-to-validation-in-craft-part-5-custom-validators#newsletter So something like this: public function validateMySetting($attribute) { $values = (is_array($this->$attribute)) ? $this->$attribute : [ $this->$...


4

You can do either or both of: Use javascript validation on the front end (with e.g. parsley) Create a plugin with a method that is registered as a listener on this event: https://craftcommerce.com/docs/events-reference#commerce_addresses.onbeforesaveaddress ...and perform validation on the address model before it is saved. use $event->performAction = ...


3

I can think of a couple of options and I'll just throw them all out there. Have a separate model per partial form and each model performs its own validation. Have a single model, but have it override the rules() method and you can conditionally set what validations methods you want depending on the step you're on. Presumably, you'd want to pass in a step ...


3

Well, it looks like Sprout Forms itself prefers separate services for everything (they'd be some big services if they weren't,) but Craft does bundle closely-related things together sometimes - FieldsService deals with both fields and groups, TagsService with both tags and tag groups for example. Personally I just look at how much code there is, if I start ...


3

Ok, so I finally figured it out. The trick was using the following two methods: assembleLayoutFromPost() setContentFromPost('fields') The controller now looks like this: public function actionSubmit() { // require POST $this->requirePostRequest(); // assume new element type $elementtype = new PluginName_ElementTypeModel(); // assign the attributes ...


3

I haven't tried this in php, but on the 'template' side there is an attribute called 'status' which you might try. I assume it would work in php as well. $existing = craft()->elements->getCriteria($this->entry->elementType)->first(array( 'someHandle' => 'someValue', 'status' => null )); Default is 'live'; other values would be ...


3

I ended up overriding BaseModel->setAttribute() and BaseRecord->prepAttributesForUse() in my plugin. Works well! Right now I'm just handling Bool and Number types. Posted this solution here: http://craftcookbook.net/recipes/324


3

Currently the only thing Craft does in BaseModel->setAttribute() and BaseRecord->prepAttributesForUse() is some normalization when the attribute in either case happens to be AttributeType::DateTime or AttributeType::Mixed. All other attribute types will be returned directly as the database returned them (as a string). However, I agree with you that we ...


3

It sounds like you have 3 different general buckets of entries to consider: Streams of similar entries (News section, blogs, etc.) General content pages (100+ of them) Unique/one-off pages (Contact Us, application forms, etc.) Streams First, the easy ones: the streams of similar content (news, blogs, etc.) should each get their own Channel sections. A ...


3

Kind of, but probably not what you're looking for. Your plugin can certainly do a MyAssetFileModel extends AssetFileModel and (in the scope of your plugin) take advantage of existing AssetFileModel methods and properties and override them as needed. But that's the catch... it will only be within the executing scope of your plugin. There's no native way (...


2

BaseComponentModel, BaseElementModel and BaseEntryRevisionModel all ultimately end up extending BaseModel, which itself extends Yii's CModel. I like to think of them, roughly, as beefed up Data Transfer Objects. Primarily useful for transferring data throughout the various layers of Craft (templates, controllers, services, etc.). Regarding which ones you ...


2

Got it working now, namespace issue :s. The autoloaded classes are in the Craft namespace and i didnt prepend this to the dynamicly generated class names. Time to take a break...


2

Yii's setAttributes method is probably a better way to do this than the populateRecords method, as by default assignments will only be made to safe attributes. See this wiki article, Understanding "Safe" Validation Rules , for details on how you can specify what attributes are safe to be massively assigned. This will allow you to protect against unwanted ...


2

Yii does have the equivalent populateRecord and populateRecords on CActiveRecord. However, on both the populateModel(s) and populateRecord(s) methods, you should be very cautious of blindly mass-assigning untrusted inputs to models/records that participate in the Active Record pattern (like Craft/Yii does). They can be susceptible to what's known as the ...


2

This might be similar to Brad Bell's recommendation, but if you are using Yii's built-in validation rules, you should just override the rules() method in your model or record, specify the rule there, and then customise the error message text for it. For example: /** * Returns this record's validation rules. * * @return array */ public function rules() ...


2

In addition to Brad’s answer (which is what I was looking for), you could also use template-specific messages using conditionals if for some reason you only needed to override the global error in a certain place. Unlikely but here’s an example: {% if errors.attributeOne is defined ? errors.attributeOne | length %} <p class="alert">Custom ...


2

If you have $entry, you should be able to get the tags by the field name, (codes, in your case). $tags = $entry->codes; foreach($tags as $tag) { echo "<li>".$tag->title."</li>"; }


2

In your Micros_GuestRegistrationRequestModel's attribute definition, if you define person like so: 'person' => array(AttributeType::Mixed, 'model' => 'Micros_GuestPersonModel'); Craft should take care of ensuring person will be an instance of Micros_GuestPersonModel.


2

In your model you can override setAttribute(), which covers calling setAttribute('foo', 'bar') directly as well as $model->foo = 'bar'. public function setAttribute($name, $value) { if ($name == 'foo') { // Not sure if your value will be a dateTime object, string, etc. // But check to see if it's < than today's current date. ...


2

I'm pretty sure 'default'=>[] isn't doing anything so it's probably not necessary. If you wanted to force a single attribute to be of a specific model, you could use: 'courierShippingItems' => array('type' => AttributeType::Mixed, 'model' => 'Shipper_ShippingItemModel'); Regardless, you'll want to use BaseModel's setAttribute to do what you'...


2

Looks like I can just refer to the other field name: public function validateUsername($attribute) { $value = $this->$attribute; $otherFieldsValue = $this->otherField; if ($value && strtolower($otherFieldsValue) == 'spartacus') { $message = Craft::t("No, I'm Spartcus!"); $this->addError($attribute, $message); ...


2

Problem is: so far as I can tell, nobody's written the book. That's partly our fault... we've never really documented the Attribute parts of Models and Records. And it probably won't happen now since the majority of that has been stripped out of the upcoming Craft 3 making it much easier to follow Yii 2 conventions (which happens to be way more documented)....


2

I would move that logic out of your model class and into a service method. Your model could still have a thin wrapper for it: public function getVideos() { return craft()->myPluginVideoService->getVideosByChannelId($this->id); } Then your plugin's video service would have: public function getVideosByChannelId($channelId) { // Can memoize ...


2

I'm going to look pretty dumb if somebody drops a one-line answer down the line, but here goes: AFAIK, unfortunately, "cloning" an element (e.g. an EntryModel) isn't that simple. For one, $model->getContent() will pull the entry's ContentModel, which basically contains all the custom fields that are stored in the craft_content table for your particular ...


Only top voted, non community-wiki answers of a minimum length are eligible