class MyForm extends Model
{
const SCENARIO_DEFAULT = self::SCENARIO_CREATE;
const SCENARIO_CREATE = 'create';
const SCENARIO_UPDATE = 'update';
}
$form = new MyForm();
echo $form->scenario;
create
default
I can't write:
public function fields()
{
// PHP Notice – yii\base\ErrorException Undefined index: default
return $fields = $this->scenarios()[$this->scenario];
}
That why:
// \yii\base\Model
private $_scenario = self::SCENARIO_DEFAULT;
To fix it I can rewrite init() method - IMHO: not elegantly.
| Q | A |
| --- | --- |
| Yii version | 2.0.9 |
| PHP version | > 7 |
That's fine IMO. I don't think we should do something with it
why would you ever want to do that? imo it is not a good idea as it means that all models loaded from the DB are in scenario 'create'. that does not make sense.
from DB
extends Model - no any DB
@cebe I want to write the code:
class MyForm extends Model
{
const SCENARIO_DEFAULT = 'create';
const SCENARIO_CREATE = 'create';
const SCENARIO_UPDATE = 'update';
public function scenarios()
{
return [
self::SCENARIO_CREATE => ['name', 'imageFile'],
self::SCENARIO_UPDATE => ['name', 'imageFile', 'clearImage'],
];
}
}
it's simple code. No any DEFAULT....
$form = new MyForm();
$form-load($data);
$form->validate(); // here again error Unknown scenario: default
If you're just wanting to use the const SCENARIO_CREATE why not inherit it from SCENARIO_DEFAULT
class MyForm extends Model
{
const SCENARIO_CREATE = self::SCENARIO_DEFAULT;
const SCENARIO_UPDATE = 'update';
public function scenarios()
{
return [
self::SCENARIO_CREATE => ['name', 'imageFile'],
self::SCENARIO_UPDATE => ['name', 'imageFile', 'clearImage'],
];
}
}
@Alex-Code I can, but it's litehack....like all of Yii2
You could change scenario in init() or __construct().
I want to be able to define my scenarios once, and be able to set the default as needed.
Say, I have a ModelB that extends ModelA, the default scenario for ModelA is SCENARIO_DRAFT, but the default for ModelB should be SCENARIO_REFURBISHED. Currently this is not possible without redefining several scenario constants in ModelB — setting SCENARIO_REFURBISHED to SCENARIO_DEFAULT, and then setting SCENARIO_DRAFT to something and crossing my fingers, that ModelA uses static::SCENARIO_DRAFT everywhere. And that nothing uses scenario constants of the parent, ModelA, when interacting with the child, ModelB (which is a very common practice in OOP).
And what if ModelC exends from ModelB and needs to have yet another default scenario?
I can create the PR for this.
@U-D13 how about doing as @rob006 proposed?
@samdark that would not really affect Model::scenarios().
All it takes is static:: instead of self:: on that line, and
/**
* @inheritdoc
*/
public function __construct($config = array())
{
$this->_scenario = static::SCENARIO_DEFAULT;
parent::__construct($config);
}
somewhere near the top of the class.
I still don't get it a use case for it.
Such a slim use case adding it into the core is a definite bad idea. Luckily, php has a great little function called array_merge... So, your use case could be something of this sort:
class ModelA {
const SCENARIO_DEFAULT = 'create';
const SCENARIO_CREATE = 'create';
const SCENARIO_UPDATE = 'update';
public function scenarios()
{
return [
self::SCENARIO_CREATE => ['name', 'imageFile'],
self::SCENARIO_UPDATE => ['name', 'imageFile', 'clearImage'],
];
}
}
class ModelB extends ModelA {
const SENARIO_DEFAULT = 'somethingelse';
public function scenarios()
{
$custom_scenarios = [ self::SCENARIO_DEFAULT => ['something']];
return array_merge($custom_scenarios, parent::scenarios());
}
}
note: I may be completely off base, but I imagine that'd give you the functionality you are after in that it pulls the scenarios from the parent model, and merges with any custom ones for the child. syntax and ability may also be completely off as this is 100% untested.
@jblac dude, this has nothing to do with validation — I'm talking about the default scenario constant, Model::SCENARIO_DEFAULT, which should be override-able in child classes as needed. Scenario constants are most commonly used by controllers, which would set the model's scenario to one of the constants that's defined in the class, or let it default to what the model is set up to have as the default scenario.
Also, referring to a class constant as static and initializing a class variable in the constructor adds a negligible overhead, while doing array_merge stuff, unavoidably adds noticeable overhead in every case where that is needed.
@samdark here's a use case for you:
use yii\base\Model;
class ModelA extends Model {
const SCENARIO_DEFAULT = self::SCENARIO_NEW;
const SCENARIO_EXISTING = 1;
const SCENARIO_NEW = 2;
// ...
}
class ModelB extends ModelA {
const SCENARIO_DEFAULT = self::SCENARIO_EXISTING;
const SCENARIO_DRAFT = 3;
// ...
}
class ModelC extends ModelB {
const SCENARIO_DEFAULT = self::SCENARIO_RETURN;
const SCENARIO_RETURN = 4;
// ...
}
I am not authorized to release the intellectual property of my employer in any form, so, no, I will not publish the exact class and scenario names in use in our projects.
@U-D13 that's not a use case. It shows new syntax but I have no idea why it's introduced at the first place. What is the purpose? Can you give an example?
A'ight. I'll just extend yii\base\Model to override the relevant parts.
Most helpful comment
If you're just wanting to use the const
SCENARIO_CREATEwhy not inherit it fromSCENARIO_DEFAULT