class not found even when it exits on Yii2 - yii2

I'm making my first application using Yii and I have the next code:
public function actionCreate()
{
$model = new User();
$singUp = new \frontend\models\SingupForm;
if ($singUp->load(Yii::$app->request->post()) && $singUp->save()) {
$model = ModelName::findOne(['id' => $singUP->id]);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
}
} else {
return $this->render('create', [
'model' => $model,
'singUp' => $singUp
]);
}
}
And I'm having the next error message when I try to go to that method:
Class 'frontend\models\SingupForm' not found
But I have the file saved on the directory as it is showed in the screenshot I attached. Additionally I added all the models folder of the Frontend on the controller I am using:
use Yii;
use \frontend\models;
use common\models\User;
use backend\models\search\UserSearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
use yii\filters\AccessControl;
use common\models\PermissionHelpers;
So I don't know what I'm doing wrong. Please help
Screenshot

There is a typo in your code.
Please Change frontend\models\SingupForm to frontend\models\SignupForm.

Related

Yii2: how to remove required attribute in a view?

I have a text field that was defined as required in its model. But a view needs not be required. I try this way to remove the required attribute but it doesn't work:
<?= $form->field($model, 'city')->textInput(['required' => false]) ?>
I need to change it in a view or in its controller. But not in its model (because others view needs the required attribute.).
I know how to do it using jQuery but I prefer with PHP/Yii2.
Update (requiered by the nice help of #Muhammad Omer Aslam):
My model is called Persons.
My view is called _form.
My controller is called PersonsControllers. It has the update function:
actionUpdate($id):
public function actionUpdate($id)
{
$model = $this->findModel($id); // How to add my new scenario here?
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id_person]);
}
return $this->render('update', [
'model' => $model,
]);
}
You can use scenarios to make the field required or not for the specific view. You can assign the active fields that are required for the scenario, and those fields will be the subject to validation.
I assume the model is Profile. In below example firstname, lastname and city is required in the default scenario.
A model may be used in different scenarios, by default the scenario default is used. Let's say in your case we can declare a scenario special that will only require firstname and lastname. In your model, you will declare a constant for the scenario name, and then override the scenarios() method, key=>value pairs with the active field names being passed in form of an array to the value will be assigned.
namespace app\models;
use yii\db\ActiveRecord;
class Profile extends ActiveRecord
{
const SCENARIO_SPECIAL = 'special';
public function scenarios()
{
$scenarios = parent::scenarios();
$scenarios[self::SCENARIO_SPECIAL] = ['firstname', 'lastname'];
return $scenarios;
}
}
and then inside your controller/action for that view where you do not want the city field to be required, initialize the Profile model object as below
public function actionProfile(){
$model = new \common\models\Profile(['scenario'=> \common\models\Profile::SCENARIO_SPECIAL]);
return $this->render('profile',['model'=>$model]);
}
Now if you submit the form inside this view it will ask only for the firstname and lastname whereas in your previous forms/views if you try to submit the form it will ask you to provide the city when trying to submit, you don't have to change or add anything for the rest of the forms or the rules.
As you are trying to update the record and do not want the city to be required when updating the record, the only difference that could be is to assign the scenario like below as you are not creating a new object for the model.
$model->scenario=\common\models\Profile::SCENARIO_SPECIAL;
In the model:
const SCENARIO_MYSPECIAL = 'myspecial';
public function rules()
{
return [
[['id_person', 'city'], 'required', 'on' => self::SCENARIO_DEFAULT],
[['id_person'], 'required', 'on' => self::SCENARIO_MYSPECIAL],
];
}
In the controller:
public function actionUpdate($id)
{
$model = $this->findModel($id);
$model->scenario = 'myspecial';
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id_person]);
}
return $this->render('update', [
'model' => $model,
]);
}
go to the model and remove the attribute
public function rules()
{
return [
[['id_person', 'city'], 'required'],
[['id_person'], 'required'],
];
}
EX:
public function rules()
{
return [
[['id_person'], 'required'],
[['id_person'], 'required'],
];
}

How to use Yii 2 Lajax ToggleTranslate

I searched in documentation how to turn on ToggleTranslate on Yii 2 but with no success. I echoed widget
<?= \lajax\translatemanager\widgets\ToggleTranslate::widget(); ?>
but it does not apper. Then I went to source code and got this:
if (!Yii::$app->session->has(Module::SESSION_KEY_ENABLE_TRANSLATE)) {
return;
}
I commented it and my button appeared. But button is not working. So my question is how to properly (by proper flow, by proper guide) configure it and run it?
Site controller I modified:
public function actionLogin()
{
if (!Yii::$app->user->isGuest) {
return $this->goHome();
}
$model = new LoginForm();
if ($model->load(Yii::$app->request->post()) && $model->login()) {
/** set session key for appearing translate button */
if(array_key_exists('admin', Yii::$app->authManager->getAssignments(Yii::$app->user->id)))
\Yii::$app->session->set('frontendTranslation_EnableTranslate',1);
return $this->goBack();
} else {
return $this->render('login', [
'model' => $model,
]);
}
}

Yii2 POST image to model in API without Yii2 Naming convention

I'm creating an endpoint for a mobile application to send a image to the server. I'm posting the image with the POSTMAN extension for chrome. The image is in the $_FILES variable, and named image. How can I load this image into a model, or the UploadedFile class? The $model->load(Yii::$app->request->post()) line does not correctly load the file, as it is not in Yii2's naming convention for forms.
It's currently returning:
{
"success": false,
"message": "Required parameter 'image' is not set."
}
Code
models\Image.php
<?php
namespace api\modules\v1\models;
use yii\base\Model;
use yii\web\UploadedFile;
class Image extends Model
{
/**
* #var UploadedFile
*/
public $image;
public function rules()
{
return [
[['image'], 'file', 'skipOnEmpty' => false, 'extensions' => 'png, jpg'],
];
}
public function upload()
{
$path = dirname(dirname(__FILE__)) . '/temp/';
if ($this->validate()) {
$this->image->saveAs($path . $this->image->baseName . '.' . $this->image->extension);
return true;
} else {
die(var_dump($this->errors));
return false;
}
}
}
controllers\DefaultController.php
<?php
namespace api\modules\v1\controllers;
use api\modules\v1\models\Image;
use yii\web\Controller;
use yii\web\UploadedFile;
use Yii;
class DefaultController extends Controller
{
public $enableCsrfValidation = false;
public function actionIndex()
{
Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
$model = new Image();
if (Yii::$app->request->isPost) {
if($model->load(Yii::$app->request->post()))
{
$model->image = UploadedFile::getInstance($model, 'image');
if ($model->upload()) {
// file is uploaded successfully
return ['success' => true, 'message' => 'File saved.'];
}
else return ['success' => false, 'message' => 'Could not save file.'];
}
else return ['success' => false, 'message' => 'Required parameter \'image\' is not set.'];
}
else return ['success' => false, 'message' => 'Not a POST request.'];
}
}
Postman
Your problem seems to be the name you are using to send the image file. Usually Yii2 uses names for form attributes like "ModelName[attributeName]" and you are sending your image file with the name "image"
There are 2 ways of fixing this:
Change the name you use to send your image file to follow the same naming conveniton. However you don't seem to want that.
Use getInstanceByName('image') method instead of getInstance($model, 'image')
The problem come here
When you send files via api they are not sent asynchronously. If you check
echo '<pre>';
print_r($_FILES); //returns nothing
print_r($_POST["image"]); //returns something
echo '</pre>';
die;
One reason is that your controller extendsyii\web\controller which is not used by rest apis, extend yii\rest\controller
The other way to go about this is by using javascript formData when sending the post request
This is a way i handled a previous ajax post of an image probably itll give you a guideline
The form
<?php $form = ActiveForm::begin(['options' => ['enctype' =>
'multipart/form-data','id'=>'slider_form']]); ?> //dont forget enctype
<?= $form->field($model, 'file')->fileInput() ?>
Then on the ajax post
var formData = new FormData($('form#slider_form')[0].files);
$.post(
href, //serialize Yii2 form
{other atributes ,formData:formData}
)
Then on the controller simply access via
$model->file =$_FILES["TblSlider"]; //here this depends on your form attributes check with var_dump($_FILES)
$file_tmp = $_FILES["TblSlider"]["tmp_name"]["file"];
$file_ext = pathinfo($_FILES['TblSlider']['name']["file"], PATHINFO_EXTENSION);
if(!empty($model->file)){
$filename = strtotime(date("Y-m-d h:m:s")).".".$file_ext;
move_uploaded_file($file_tmp, "../uploads/siteimages/slider/".$filename);
///move_uploaded_file($file_tmp, Yii::getAlias("#uploads/siteimages/slider/").$filename);
$model->image = $filename;
}
I hope this helps

Yii2: why does the layout not get shown?

I have a controller with a working action:
class ConfigurationController extends Controller {
public function actions() {
return [
'error' => [
'class' => 'yii\web\ErrorAction',
],
];
}
public function actionView() {
$myModel = ...
$this->render('view', ['model' => $myModel]);
}
}
All seems to be fine, however the layout file which is app/views/layout/main.php does not get shown. There is no special configuration about the layout. What could be wrong?
The main reason: I did not use the return statement. So the correct action is:
public function actionView() {
$myModel = ...
return $this->render('view', ['model' => $myModel]);
// ^^^^^^
}
More info can be found in the guide.
Note: Usually an empty page would be shown. But I also had a <?php $form = ActiveForm::begin(); ?> without an <?php ActiveForm::end(); ?> in the view file. This caused a partial rendering somehow (caused no exception). So I needed to correct this as well.
I'm just sharing my problem and what I've found out so if anyone else has a similar effect may be reminded that the return statement must not be forgotten.

create an expandable grid view in Yii2

I am trying to create an expandable grid view in Yii2 but I have some problems.
I get this warning:
PHP Warning – yii\base\ErrorException
reset() expects parameter 1 to be array, null given
in C:\xampp\htdocs\advanced\vendor\yiisoft\yii2\grid\DataColumn.php at line 129
$provider = $this->grid->dataProvider;
if ($this->label === null) {
if ($provider instanceof ActiveDataProvider && $provider->query instanceof ActiveQueryInterface) {
/* #var $model Model */
$model = new $provider->query->modelClass;
$label = $model->getAttributeLabel($this->attribute);
} else {
$models = $provider->getModels();
129 if (($model = reset($models)) instanceof Model) {
/* #var $model Model */
$label = $model->getAttributeLabel($this->attribute);
} else {
$label = Inflector::camel2words($this->attribute);
}
}
} else {
$label = $this->label;
}
This is my search model code:
<?php
namespace app\models;
use Yii;
use yii\data\ActiveDataProvider;
use yii\base\Model;
use app\models\Articles;
/**
*
*/
class ArticlesSearch extends Model
{
/* your calculated attribute */
public $article_num;
public $title;
public $jour_id;
/* setup rules */
public function rules() {
return [
/* your other rules */
[['title'], 'safe']
];
}
public function search($params) {
$query = Articles::find()->select('*')
->where(['`journal_id`'=>$this->jour_id]);
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
if (!($this->load($params) && $this->validate())) {
return $dataProvider;
}
$query->orderBy('`articles`.`publication_date` ASC ');
$query->andWhere(['LIKE','title',$this->title]);
// $query->orFilterWhere(['like', '`publishers`.`name`', $this->name]);
return $dataProvider;
}
public function getCount()
{
}
public function getModels()
{
}
}
I added two last methods to my class to bypass the following error:
Calling unknown method: app\models\ArticlesSearch::getCount()
Calling unknown method: app\models\ArticlesSearch::getModels()
I don't know why I need this two methods in my class. I have written two other search models and I didn't put these methods there and they work fine!!!
Controller code:
$dataProvider=new ArticlesSearch();
$dataProvider->jour_id=$param['journalID'];
$searchModel= $dataProvider->search(Yii::$app->request->queryParams);
return $this->render('index', [ 'searchModel' => $searchModel,
'dataProvider' => $dataProvider]);
View code:
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' =>$searchModel,
'columns' => [
[
'class'=>'kartik\grid\SerialColumn',
'contentOptions'=>['class'=>'kartik-sheet-style'],
//'width'=>'36px',
'header'=>'',
'headerOptions'=>['class'=>'kartik-sheet-style']
],
[
'class'=>'kartik\grid\CheckboxColumn',
'headerOptions'=>['class'=>'kartik-sheet-style'],
],
[
'class'=>'kartik\grid\ExpandRowColumn',
//'width'=>'50px',
'value'=>function ($model, $key, $index, $column) {
return GridView::ROW_COLLAPSED;
},
'detail'=>function ($model, $key, $index, $column) {
// return Yii::$app->controller->renderPartial('_expand-row-details', ['model'=>$articles]);
},
'headerOptions'=>['class'=>'kartik-sheet-style']
//'disabled'=>true,
//'detailUrl'=>Url::to(['/site/test-expand'])
],
[
'attribute'=>'Title',
//'value' => $model->title,
// 'width'=>'410px',
],
],
]);
?>
Any help would be much appreciated.
Try this amended code and see if it works. I've added some comments to explain what is going on.
<?php
namespace app\models;
use Yii;
use yii\data\ActiveDataProvider;
use app\models\Articles;
/**
** firstly, your search model needs to extend your original class, that was you have access to all the original attributes of your model, without having to declare them again.
**/
class ArticlesSearch extends Articles
{
//If your original model already has these properties, you don't need to declare them again.
public $article_num;
public $title;
public $jour_id;
/* Here you should declare rules for ALL the attributes that you want to use in search */
public function rules() {
return [
/* your other rules */
[['title', 'jour_id', 'article_num'], 'safe']
];
}
public function search($params) {
//Start by defining your basic search function
$query = Articles::find();
//Add in the dataProvider
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
//Start building the query that will be used to retrieve results
$query->where(['jour_id' => $this->jour_id]);
//Try to load the $params and validate them. If this fails, just return the dataProvider and do nothing else
if (!($this->load($params) && $this->validate())) {
return $dataProvider;
}
//If we're still in the method, carry on building the query
$query->orderBy('`articles`.`publication_date` ASC ');
//andFilterWhere() is better because it ignores empty values
$query->andFilterWhere(['LIKE','title',$this->title]);
return $dataProvider;
}
//Finally, remove the two extras functions you put in. If everything is working, you shouldn't need them.
}
Next, in your controller, use this code;
//Here you are telling Yii what model you want to use for searching, and for generating the form for the grid search.
$searchModel = new ArticlesSearch();
//I'm not sure where this $param is coming from.
$dataProvider->jour_id=$param['journalID'];
//Now you are actually setting up the dataProvider for the grid view. Notice that your $searchModel->search() method always returns a dataProvider, so this is the correct way to do it. Yii::$app->request->queryParams is loading the parameters that the search method will use for it's parameters.
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', ['searchModel' => $searchModel, 'dataProvider' => $dataProvider]);
Now you should be able to use the grid widget as normal, use the dataProvider and searchModel for your dataProvider and filterModel respectively, but don't mix them up!