what do you think
step 1
web.php
'language' => 'de',
'components' => [
'i18n' => [
'translations' => [
'app*' => [
'class' => 'yii\i18n\PhpMessageSource',
'basePath' => '#app/messages',
'sourceLanguage' => 'en',
'fileMap' => [
'app' => 'app.php',
'app/error' => 'error.php',`
.....
Step2
I created the -foldert messages, and I added three folder in messages folder (en, fr, de) and created three file(each contained one)-app.php
'language' => 'de', when i change 'language' => 'hu' Works with translation
step 3
But because I am a beginner I do not know what's next.
I created two buttons but I can not write the Controller.
view/index.php
German<br>
Hungarian
My question is how could the button to switch the language,Need to create a Controller, or work without it, it's how?
step 4 ?
Thanks
Create an action to Set Language in your controller for example SiteController i.e.
public function actionSetLang($lang)
{
switch ($lang) {
case "en":
\Yii::$app->language = "en";
break;
case "de":
\Yii::$app->language = "de";
break;
case "hu":
\Yii::$app->language = "hu";
break;
default:
\Yii::$app->language = "en";
}
$this->goBack();
}
Then in your view you can set up your buttons i.e.
Hungarian
German
The above is a very simple approach. Ideally you want to use cookies to store the user's preferred language in the browser, so the users don't have to change the language every time they visit the page. The cookies can be implemented within the setLang action. I will skip the cookies implementation as they are out of the scope of this question.
You could use this to set your language:
Yii::$app->language = 'ru_RU';
use this function in your controller:
public function init()
{
//set here your language
parent::init();
}
And it wil works for all the functions of that controller.
EDIT:
The first function sets the languages for the rest of the application. when you call that function the rest of the Yii::t() labels will be in that language if the label exsists in that language. de init is a function that is always called before the action in a controller every controller have that function. so if you set a language there the rest of the function will be in that language
Related
I got a little issue to solve. In my app I am handling with a lot of Models and each model does have something like:
ModelResource
ModelResourceCollection
ModelResourceOverview
ModelResourceOverviewCollection
The reason is: Sometimes I don't need all the information that are visible if I am using the ModelResource - in this case I am calling the ModelResourceOverview.
Example
PostResource
- title
- tags
- content
- author
Example
PostOverviewResource
- title
- author
As I have a lot of Models I have a huge number of ApiResource-Classes and I want to get rid of that.
I thought about using $this->when in the Resource and pass something like "full" or "overview" to the request in the Controller.
Example
$data
= new PostResource($this->post);
So my question is: Is it the best way to add this to the request or is there a handier/nicer way to handle this?
Laravel has a way to hide fields on the fly: Hiding attributes from json
e.g.
return $post->makeHidden('content')->toArray();
If your logic about "visible or not" is bound to the current request, then you should use when or mergeWhen as you mentioned (everything here https://laravel.com/docs/7.x/eloquent-resources#conditional-attributes ), therefore you'll only have 2 resources instead of 4
public function toArray($request)
{
return [
'title' => $this->title,
'author' => $this->author,
$this->mergeWhen($this->needsFullData($request), [
'tags' => $this->tags,
'content' => $this->content,
]),
];
}
protected function needsFullData($request)
{
//Your logic
}
I have MyEntity.php model. As a part of the model script, there are some rules and some scenarios defined:
public function rules()
{
return [
[['myentity_id', 'myentity_title', 'myentity_content', 'myentity_date'], 'required'],
[['myentity_id'], 'integer'],
[['myentity_title', 'myentity_content'], 'string', 'max' => 120],
[['myentity_date'], 'safe'],
];
}
public function scenarios()
{
$scenarios = parent::scenarios();
$scenarios['scenario_one'] = ['myentity_id', 'myentity_title'];
$scenarios['scenario_two'] = ['myentity_id', 'myentity_content'];
return $scenarios;
}
I need to be able to have different scenarios, and for different actions only certain validations (by params) to be active. For example, scenario_one for actionOne, scenario_two for actionTwo etc.
Here is some small part of code from the controller:
public function actionOne($id)
{
$modelMyEntity = $this->findModel($id);
$modelMyEntity->scenario = 'scenario_one';
.
.
.
}
public function actionTwo($id)
{
$modelMyEntity = $this->findModel($id);
$modelMyEntity->scenario = 'scenario_two';
.
.
.
}
Now I want to have a scenario_three where there should NOT be any validations at all. I'll have additional checks in code that will prevent failing while storing in database. I'll just need to make sure that no validations are applied because it's preventing my form from submitting. If I don't apply any scenario, then the default scenario is applied (all listed validations will be active, which is totally opposite of the scenario I need).
To be able to do this, you need to do a few things (including the ones you almost did yourself):
In your controller, write $modelMyEntity->scenario = 'scenario_three';
In model, add an additional scenario array 'scenario_three' in scenarios() method:
Like this:
$scenarios['scenario_three'] = ['myentity_id', 'myentity_content'];
Finally, most changes will be required in rules() as you will need to add where to include or exclude specific scenarios.
Basically, in each rule you can now write except conditional and point which attributes will not comply to which scenario. So in your example, let's say, let's exclude all attributes for scenario_three:
[['myentity_id', 'myentity_title', 'myentity_content', 'myentity_date'], 'required', 'except' => 'scenario_three'],
[['myentity_id'], 'integer', 'except' => 'scenario_three'],
[['myentity_title', 'myentity_content'], 'string', 'max' => 120, 'except' => 'scenario_three'],
[['myentity_date'], 'safe'],
This is a little different solution to how to ignore rules but I find this more attractive because in future it would be easier to add/remove specific attributes for this scenario and will also be easier for other developers (if there are more than just you) to understand what you're trying to do.
But I think #iStranger's solution works too (much simpler).
If I correctly understood your question, you can assign scenario_three as current scenario: model will not find matched rules and will skip validation checks.
public function actionThree($id)
{
$modelMyEntity = $this->findModel($id);
$modelMyEntity->scenario = 'scenario_three';
.
.
.
}
UPD:
However I strictly recommend to define explicitly all scenarios and corresponding active attributes (in scenario method) and remove $scenarios = parent::scenarios();, because it can cause unnecessary effects. Parent implementation is mostly developed to backward compatibility with Yii1, that has no scenarios() methods. And it is assumed usually if you override scenarios() method, you should not merge your explicitly defined scenarios with parent implementation.
How can I create a model rule that's only required when a certain value from the Database is 1?
I tried using a 'required', 'when' rule but that doesn't seem to update the client-side JavaScript.
I also tried a custom inline validator but that doesn't seem to post an empty field.
Scenario's aren't an option I think as I have 6 fields and can have any combination of required/not required.
EDIT
At the moment I just never add the required rules, instead of directly returning the rules I store them in a variable. $rules = []
Then before I return the variable I add the required options to the array.
if($x->x_required)
$rules[] = ['your-field', 'required', 'on' => 'your-scenario'];
This is a quickfix and I don't really like it, but it works. I'm not sure if there is a better way of doing this.
You need to use combination required with when, but for client side validation you need additionally specify whenClient property.
Example (add this to your rules()):
[
'attributeName',
'required',
'when' => function ($model) {
return $model->country == Country::USA;
},
'whenClient' => function (attribute, value) {
return $('#country').value == 'USA';
},
],
Official docs:
RequiredValidator
Validator $when
Validator $whenClient
I’ve added a small form to an index view to allow users to filter the data. I have placed the following code for the form inside the controller, but I question whether this is the right place to put it.
// ...
public function indexAction()
// ...
// build group list
$groupList = array(
0 => 'all',
1 => 'short people',
2 => 'tall people',
3 => 'fun people',
4 => 'boring people',
);
// create group selection box
$groupSelect = new Element\Select('group');
$groupSelect->setValueOptions($groupList);
$groupSelect->setAttributes(array(
'onChange' => 'this.form.submit()',
));
// create filter form
$form = new Form('group-filter');
$form->add($groupSelect);
$form->setData(array(
'group' => $group,
));
// process the form
$request = $this->getRequest();
if ($request->isPost()) {
$groupSelection = $request->getPost('group', 0);
return $this->redirect()->toRoute('admin-members', array('group'=>$groupSelection,));
}
// ...
Following the MVC pattern, does all of this code belong in the controller?
Nope it does not belong in the controller. Create a new form class (that extends Zend\Form\Form) and inject into the controller class. You can do that through the controllers factory, either through a factory class or the anonymous function "factory".
Other way to do it would be to get it (the form you created) in the controller from the service manager, but as far I know that's not the recommended method anymore, even though it still in the ZF2 docs.
That way your form code will be separated from the controller code, not mixing with the actual controller logic and, in the former case, also more easily testable.
You can learn more from this ZF2 forum thread. It's lengthy, but there are code samples and lead devs from ZF2 team are weighing in.
I'm trying to implement a multilanguage laravel 4 website, with language code in the url ( mywebsite.com/en/home and mywebsite.com/de/home )
I've seen a couple of options like filtering all requests and checking if the first param is one of the language code.
I've also check on packagist but haven't find something that already do tee job.
Is there a better way to implement it?
Thank you
Finally, I've create a config variable in config/app.php
'available_language' => array('en', 'fr', 'es'),
In filters.php I detect the browser language:
Route::filter('detectLang', function($lang = "auto")
{
if($lang != "auto" && in_array($lang , Config::get('app.available_language')))
{
Config::set('app.locale', $lang);
}else{
$browser_lang = !empty($_SERVER['HTTP_ACCEPT_LANGUAGE']) ? strtok(strip_tags($_SERVER['HTTP_ACCEPT_LANGUAGE']), ',') : '';
$browser_lang = substr($browser_lang, 0,2);
$userLang = (in_array($browser_lang, Config::get('app.available_language'))) ? $browser_lang : Config::get('app.locale');
Config::set('app.locale', $userLang);
}
});
and then in routes.php I can either detect the language or force it:
Route::get('/', array(
'before' => 'detectLang()', // auto-detect language
function(){
...
})
);
or
Route::get('/', array(
'before' => 'detectLang("fr")', // force language to "fe"
function(){
...
})
);
You could set a language variable in the user session.
Then use a 'before' filter, and view that variable, and log the correct language file.
If there is no variable set - then use a default (perhaps based upon their IP location).