Using yii2 I have created a Model and CRUD using gii.
I want to use a foreach or while loop in my VIEW to display the data in the following format
For each row in database table
echo("addMarker($lat_field, $lon_field);\n");
I have an index page which is rendered using the following controller action.
public function actionIndex()
{
$this->layout = 'directory';
$searchModel = new ShopDirectorySearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
I can use the following to display the data using listview which displays all the data/rows within database however it has html around it and obviously isn't outputted in the format I wish it to be.
<?= ListView::widget([
'dataProvider' => $dataProvider,
'itemOptions' => ['class' => 'col-xs-6 col-sm-3'],
'itemView' => '_index',
]);?>
No need to use ListView here, you should simply try :
foreach ($dataProvider->models as $model) {
echo "addMarker({$model->lat_field}, {$model->lon_field});";
}
If you really want to use ListView, you could simply edit _index view file.
if(!empty($st_data))
{
foreach($st_data as $row)
{
echo 'Country Name: '.$row['country_name'].'</br>';
echo 'State Name: '.$row['state_name'].'</br>';
echo 'City Name: '.$row['city_name'].'</br>';
echo '</br>';
}
exit;
}
$rows = ShopDirectory::findAll();
if(!empty($rows))
{
foreach($rows as $row)
{
$lat = $row->lat;
$lon = $row->lon;
$this->view->registerJs('addmarker("'.$lat.'", "'.$lon.'"."\n");', yii\web\View::POS_END);
...
}
}
http://www.yiiframework.com/forum/index.php/topic/61940-simple-while-loop-to-list-all-rows/page__view__findpost__p__274731
Related
I have a typical ListView widget in a view as follows:
public function actionView($id)
{
$model = $this->findModel($id);
$dataProvider = new \yii\data\ActiveDataProvider(['query' => \app\models\Verses::find()->where(['sura_id' =>$id])->with('sura')]);
return $this->render('view', [
'model' => $model,
'dataProvider' => $dataProvider,
]);
}
In the view a list of Verses model is rendered and the pager of the ListView is available too.
I want to add some details to the page title. Those details are data from the first and last records of the Verses model rendered in the list.
I have tried to use min() and max() PHP functions to get the first and the last records in the view as follows:
$min = min($model->verses);
echo $min->verse_id;
However, it returns the ultimate first record regarding-less the current pager page. In other words, it does not return the verse_id value of the first item of the list.
Is there any way to get the first, last or even a specific nth item of the ListView?
You should simply try :
$models = $dataProvider->getModels();
$first = reset($models);
$last = end($models);
Read more about reset and end.
You could access to the models array of dataProvider a get the firts and the last
public function actionView($id)
{
$model = $this->findModel($id);
$dataProvider = new \yii\data\ActiveDataProvider(['query' => \app\models\Verses::find()->where(['sura_id' =>$id])->with('sura')]);
$first = $dataProvider['models'][0];
$last = $dataProvider['models'][$dataProvide['totalCount']-1];
or you can use
$myModels = $dataProvider->gestModels();
$first = myModels[0];
$last = myModels[$dataProvide['totalCount']-1];
and for the page you can use count instead of total count
return $this->render('view', [
'model' => $model,
'dataProvider' => $dataProvider,
]);
}
I set up editable column for the GridView in Yii2 with Kartik Editable extension. The problem I am facing is that I cannot find a way to update multiple table cell from one editable column.
The things I did:
GridView column
[
'class' => 'kartik\grid\EditableColumn',
'attribute'=>'post_title',
'editableOptions'=> function ($model, $key, $index) {
return [
'inputType' => \kartik\editable\Editable::INPUT_TEXT,
'size'=>'sm',
'afterInput'=>function ($form, $widget) use ($model, $index) {
return $form->field($model, 'post_description')->textInput(['placeholder'=>'Enter post title']);
}
];
}
],
By clicking edit post title column it shows edit fields for title and description
PostsController action
public function actionIndex()
{
$searchModel = new PostsSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
if (Yii::$app->request->post('hasEditable')) {
$postId = Yii::$app->request->post('editableKey');
$model = Posts::findOne($postId);
$out = Json::encode(['output'=>'', 'message'=>'']);
$post = [];
$posted = current($_POST['Posts']);
$post['Posts'] = $posted;
if ($model->load($post)) {
$output = '';
$out = Json::encode(['output'=>$output, 'message'=>'']);
$model->save();
}
echo $out;
return;
}
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
So, when I edit post title and description only post title is saved into database.
I think it is because current saves only one value
$posted = current($_POST['Posts']);
What is the proper way to save both
$model->post_title and $model->post_description ?
This is an Ajax editable column. At a time only one value would be sent to the controller.
So the class of post_title and post_description column must be editable in the view.
This should work everytime you edit those columns.
Also change this
if ($model->load($post)) {
if (isset($model->post_title)){
// here you can format the value of the attribute
and display on the screen
$output = $model->post_title;
}
if (isset($model->post_description)){
$output = $model->post_description;
}
$model->save();
// Here you send a message that the value has been saved
$out = Json::encode(['output'=>$output, 'message'=>'Saved']);
}
I Have my model with 2 fields Product.php:
[['ID_PRODUCT'], 'integer'],
[['NAME_PRODUCT'], 'string'],
my Controller ProductController.php:
public function actionCreate()
{
$model = new Product();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->ID_PRODUCT]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
And i want insert many times the same table with ActiveForm:
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'ID_PRODUCT')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'NAME_PRODUCT')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'ID_PRODUCT')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'NAME_PRODUCT')->textInput(['maxlength' => true]) ?>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
But when i save the information the fields are overwritten and only the last record is inserted
What you are trying to do is collect, validate and save tabular data. The reason it doesn't work is that in the form, Yii generates a name tag based on the field name and model, e.g. name="[Product]["ID_PRODUCT"]. When the form is sent to the server, the first fields get overwritten by the last ones, as they have the same name. The correct way to collect tabular input in a form is to add brackets at the end of the name, like this; name="[1][Product]["ID_PRODUCT"].Using this method, Yii gives ways of loading and validating multiple models.
Modify your controller code to use multiple models;
<?php
namespace app\controllers;
use Yii;
use yii\base\Model;
use yii\web\Controller;
use app\models\Product;
class ProductController extends Controller
{
public function actionCreate(){
//Find out how many products have been submitted by the form
$count = count(Yii::$app->request->post('Product', []));
//Send at least one model to the form
$products = [new Product()];
//Create an array of the products submitted
for($i = 1; $i < $count; $i++) {
$products[] = new Product();
}
//Load and validate the multiple models
if (Model::loadMultiple($products, Yii::$app->request->post()) && Model::validateMultiple($products)) {
foreach ($products as $product) {
//Try to save the models. Validation is not needed as it's already been done.
$product->save(false);
}
return $this->redirect('view');
}
return $this->render('create', ['products' => $products]);
}
}
Now you have all the data you need to populate the form, including any error messages generated for individual instances of you product model. The view file for the form needs to be altered like this, to use the multiple models;
foreach ($products as $index => $product) {
echo $form->field($product, "[$index]ID_PRODUCT")->label($product->ID_PRODUCT);
echo $form->field($product, "[$index]NAME_PRODUCT")->label($product->NAME_PRODUCT);
}
All of this is covered in the Yii2 documentation
I have 2 tables. tables have relation (HAS_MANY)
table1: user(id,name)
table2:address(id,userId,address)
user can has some address
I define relation in moles: user.php and address.php
user.php
'address' => array(self::HAS_MANY, 'address', 'userId'),
address.php
'user' => array(self::BELONGS_TO, 'user', 'userId'),
when i write
$dataProvider = new CActiveDataProvider('user')
i get only record of user table but i want to get records two table i want to get name,array(address) For each user , how can do it?
UserController.php
public function actionIndex() {
$dataProvider = new CActiveDataProvider('User');
$this->render('index', array(
'dataProvider' => $dataProvider,
));
}
index.php
<?php $this->widget('zii.widgets.CListView', array(
'dataProvider'=>$dataProvider,
'itemView'=>'_view',
)); ?>
_view.php
<b><?php echo $data->name)); ?>: <?php $data->address->address; ?>:</b>
In indexaction function, change the dataprovider code as below.
$dataProvider = new CActiveDataProvider('User','criteria'=>array(
'with'=>array(
'address'
),
'together'=>true,
));
You can get the data from address table using $data->address->address_table_field_name in your view file.
Here address is relation name defined in your user model file.
You don't need to use CActiveDataProvider, rather use the model directly.
Give it a try
foreach( User::model()->findAll() as $user ) {
$address = $user->address;
foreach( $address as $a ) {
}
}
try using
$model= User::model()->with('address')->findAll();
Note:- address in with('address') is the relation Name.
Eg:-
To get User records try this
foreach($model as $record)
{
echo $record->id . $record->name;
}
To get address records try this
foreach($model as $record)
{
foreach($record->address as $myaddress)
{
echo $myaddress->id . $myaddress->userId . $myaddress->address;
}
}
I have a view (_form.php) with fields (name,summary) submit button. If I click on submit button, it should update Name field of One model and Summary field of another model.Both this models are of different databases.
Can anyone help on this. I tried the following for this
In _form.php(Test)
<?php echo $form->labelEx($model, ‘name’); ?>
<?php echo $form->textField($model, ‘name’, array(‘size’ => 60, ‘maxlength’ => 250)); ?>
<?php echo $form->error($model, ‘name’); ?>
<?php echo $form->labelEx(Test1::model(), ‘summary’); ?>
<?php echo $form->textField(Test1::model(), ‘summary’, array(‘size’ => 60, ‘maxlength’ => 250)); ?>
<?php echo $form->error(Test1::model(), ‘summary’); ?>
<?php echo CHtml::submitButton($model->isNewRecord ? ‘Create’ : ‘Save’); ?>
In TestController.php
public function actionCreate() {
$model = new Test;
if (isset($_POST['Test'])) {
$model->attributes = $_POST['Test'];
if ($model->save()) {
$modeltest1 = new Test1;
$modeltest1->attributes = $_POST['Test1'];
$modeltest1->Id = $model->Id;
if ($modeltest1->save())
$this->redirect(array('view', 'Id' => $model->Id));
}
}
$this->render('create', array(
'model' => $model,
));
}
This code is not working. How can I make it work for different databases. I followed the below link for this.
http://www.yiiframework.com/wiki/291/update-two-models-with-one-view/
This code actually should work, but its bad.
I assume that you dont understand at all what is model and what its doing in Yii, also how to render and create forms.
I'll try to explain how it should be.
1st of all dont use Test::model() in views, unless you want to call some function from it(but try to avoid it). It can be done by passing it from controller:
public function actionCreate() {
$model_name = new Name;
$model_summary=new Summary;
//something here
$this->render('create', array(
'name' => $model_name,
'summary'=>$model_summary,
));
}
When you make render you passing variables to your view (name_in_view=>$variable)
2nd. In your view you can use your variables.
<?php echo $form->labelEx($name, ‘name’);
echo $form->textField($name, ‘name’, array(‘size’ => 60, ‘maxlength’ => 250));
echo $form->error($name, ‘name’);
echo $form->labelEx($summary, ‘summary’);
echo $form->textField($summary, ‘summary’, array(‘size’ => 60, ‘maxlength’ => 250)); ?>
echo $form->error($summary, ‘summary’); ?>
echo CHtml::submitButton($model->isNewRecord ? ‘Create’ : ‘Save’); ?>
3rd. You need to understand what is model. It's class that extends CActiveRecord in this case. Your code in controller should loo like:
public function actionCreate() {
$model_name = new Name;
$model_summary=new Summary;
if (isset($_POST['Name']))
$model_name->attributes=$_POST['Name'];
if (isset($_POST['Summary']))
$model_name->attributes=$_POST['Summary'];
if ($model_name->save()&&$model_summary->save())
$this->redirect(array('view', 'Id' => $model->Id));
$this->render('create', array(
'name' => $model_name,
'summary'=>$model_summary,
));
}
$model->attributes=$_POST[] here is mass assignment of attributes, so they must be safe in rules. You always can assign attributes with your hands (1 by 1), or form an array and push it from array.