get limited numbers of data with yii2 - php

I want to get limited numbers of data from database using Yİİ2. I fetched all the record by writing this:
$departures = ArrayHelper::map(
TourDeparture::find()->all(),
'id',
'tour_id'
);
I tried to use limit(5), so that I can get only 5 rows. But I could not. Still, I get the all the rows in the table. How can I achieve that?
Updated: Here is my tourdeparture model
class TourDeparture extends \yii\db\ActiveRecord
{
public static function tableName()
{
return 'tour_departure';
}
/**
* {#inheritdoc}
*/
public function rules()
{
return [
[['tour_id', 'start_date', 'end_date', 'price_1adult', 'price_2adult', 'price_3adult', 'price_child', 'price_baby', 'min_guests', 'max_guests', 'status', 'required_min_guest'], 'required'],
[['tour_id', 'min_guests', 'max_guests', 'status', 'required_min_guest'], 'integer'],
[['start_date', 'end_date'], 'safe'],
[['price_1adult', 'price_2adult', 'price_3adult', 'price_child', 'price_baby'], 'number'],
[['tour_id'], 'exist', 'skipOnError' => true, 'targetClass' => Tour::className(), 'targetAttribute' => ['tour_id' => 'id']],
];
}
/**
* {#inheritdoc}
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'tour_id' => 'Tour ID',
'start_date' => 'Start Date',
'end_date' => 'End Date',
'price_1adult' => 'Price 1adult',
'price_2adult' => 'Price 2adult',
'price_3adult' => 'Price 3adult',
'price_child' => 'Price Child',
'price_baby' => 'Price Baby',
'min_guests' => 'Min Guests',
'max_guests' => 'Max Guests',
'status' => 'Status',
'required_min_guest' => 'Required Min Guest',
];
}
/**
* Gets query for [[Tour]].
*
* #return \yii\db\ActiveQuery
*/
public function getTour()
{
return $this->hasOne(Tour::className(), ['id' => 'tour_id']);
}
/**
* Gets query for [[TourReservations]].
*
* #return \yii\db\ActiveQuery
*/
public function getTourReservations()
{
return $this->hasMany(TourReservation::className(), ['tour_departure_id' => 'id']);
}
}

$departures = ArrayHelper::map( TourDeparture::find()->limit(5), 'id',
'tour_id' );
I wrote it like above. but ı got all the record
I'm surprised your code worked at all! You are passing the Query class into the map function. ArrayHelper::map is expecting an array and needs the query to be executed using the ->all(). ->limit(5) just adds a new term to the SQL query.
$departures = ArrayHelper::map( TourDeparture::find()->limit(5)->all(), 'id', 'tour_id' );

for retrieve the first 5 rows should be
TourDeparture::find()->orderBy("id")->limit(5)->all()

The code you shared didn't do the limit(5). Anyway, I believe it is caused by the array map,
you may try to simulate the changes as below
$q = TourDeparture::find()->select(['id', 'tour_id'])->limit(5)->asArray()->all();
\yii\helpers\VarDumper::dump($q, $depth = 10, $highlight = true);
For the above, records selected in array form, before array map.
After array map, from here you can compare the changes.
$departures = ArrayHelper::map(
$q,
'id',
'tour_id'
);
\yii\helpers\VarDumper::dump($departures, $depth = 10, $highlight = true);

Related

Laravel Error when referencing a resource in a resource

I'm using a Laravel Json Resource in my controller, as follows
public function index(Request $request)
{
$itemsWithTranslations = MenuItem::where(['menu_id' => $request->id, 'parent_id' => null])
->with(['children', 'translations'])
->orderBy('sort_order', 'asc')
->get();
return MenuItemResource::collection($itemsWithTranslations);
}
Now I would like to generate a collection, inside this collection with the children for the item that's being shown.
The following code works fine. Notice how I commented out the children reference
class MenuItemResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'text' => $this->title,
// 'children' => MenuItemResource::collection($this->whenLoaded('children')),
'data' => [
'id' => [
'value' => $this->id,
'type' => 'hidden'
],
'title' => [
'value' => $this->title,
'type' => 'text',
'label' => 'Title'
],
'resource_link' => [
'value' => $this->resource_link,
'type' => 'text',
'label' => 'Resource Link'
],
'translations' => MenuItemTranslationResource::collection($this->whenLoaded('translations'))->keyBy(function ($translation) {
return $translation['locale'];
})
]
];
}
}
When I uncomment the children, I get the following error
"Call to undefined method Illuminate\Http\Resources\Json\AnonymousResourceCollection::keyBy()"
Is it wrong, to include a Resource inside a resource? Or how should I go about this?
Model
class MenuItem extends Model
{
protected $table = 'menu_items';
protected $fillable = ['menu_id', 'parent_id', 'title', 'order', 'resource_link', 'html_class', 'is_blank'];
public function translations()
{
return $this->hasMany(MenuItemTranslation::class, 'menu_item_id');
}
public function children()
{
return $this->hasMany(MenuItem::class, 'parent_id');
}
}
Extra Information
When I return the following data, it does return empty as a collection for the children.
MenuItemResource::collection($this->children);
This returns
While if I return the children without a collection, it returns them (for 1 item, which is correct)
return $this->children;
returns
you should use ChildrenResource::collection
'children' => ChildrenResource::collection($this->whenLoaded('children'))
hope this works.
create a ChildrenResource class if not exists.

how to limit content in yii model

Is there any way to limit n number of contents in yii model any my code is
public function rules()
{
return [
[['id', 'editedby', 'cat_id', 'prod_id', 'parent', 'order', 'status'], 'integer'],
[['name', 'content', 'excerpt', 'date', 'url', 'posttype'], 'safe'],
];
}
/**
* #inheritdoc
*/
public function scenarios()
{
// bypass scenarios() implementation in the parent class
return Model::scenarios();
}
/**
* Creates data provider instance with search query applied
*
* #param array $params
*
* #return ActiveDataProvider
*/
public function search($params)
{
$query = Posts::find();
// add conditions that should always apply here
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$this->load($params,'');
if (!$this->validate()) {
// uncomment the following line if you do not want to return any records when validation fails
// $query->where('0=1');
return $dataProvider;
}
// grid filtering conditions
$query->andFilterWhere([
'id' => $this->id,
'date' => $this->date,
'editedby' => $this->editedby,
'cat_id' => $this->cat_id,
'prod_id' => $this->prod_id,
'parent' => $this->parent,
'order' => $this->order,
'status' => $this->status,
]);
$query->andFilterWhere(['like', 'name', $this->name])
->andFilterWhere(['like', 'content', $this->content])
->andFilterWhere(['like', 'excerpt', $this->excerpt])
->andFilterWhere(['like', 'url', $this->url])
->andFilterWhere(['like', 'posttype', $this->posttype]);
return $dataProvider;
}
it was a model to list products if the user was in free plan have to show only one product or else have to display products based on plan count will change i have no idea that how to add the condition i need something like
if($user_type==1){
$query->andFilterWhere([['id' => SORT_DESC])->one();]);
}
As Raul Sauco already mentioned you could use something like that
$query->andFilterWhere([['id' => SORT_DESC])->limit($user_type == 1 ? 1 : 20);

Yii2 Gridview filtering a column that has Int data type based on varchar as inputed value

I've an gridView for showing data. GridView table has a column that called as Created By, this column contain the ID of User that I get from user table. Basicly, this column will show data as Integer(ID) like this:
But I've set code like this to show the username of the ID:
[
'attribute' => 'created_by',
'format' => 'raw',
'value' => function ($data) {
$modelUser = Users::find()->where(['id' => $data->created_by])->one();
$nama = $modelUser->username;
return $nama;
},
'vAlign' => 'middle',
'hAlign' => 'center',
],
Result:
The gridView has filter column, I'm trying to filter data based on inserted value. I'm trying input username as the value for filtering but it give an error message "created By must be an Integer", like this:
How do I can filtering that column using the a username(varchar)?
Thanks
Update
This is my searchModel.php
<?php
namespace app\search;
use Yii;
use yii\base\Model;
use yii\data\ActiveDataProvider;
use app\models\Product;
/**
* ProductSearch represents the model behind the search form of `app\models\Product`.
*/
class ProductSearch extends Product {
/**
* #inheritdoc
*/
public function rules() {
return [
[['productId', 'userId', 'parentId', 'created_by'], 'integer'],
[['date', 'created_at', 'name', 'address'], 'safe'],
[['price'], 'number'],
];
}
/**
* #inheritdoc
*/
public function scenarios() {
// bypass scenarios() implementation in the parent class
return Model::scenarios();
}
/**
* Creates data provider instance with search query applied
*
* #param array $params
*
* #return ActiveDataProvider
*/
public function search($params) {
$query = Product::find();
// add conditions that should always apply here
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$this->load($params);
if (!$this->validate()) {
// uncomment the following line if you do not want to return any records when validation fails
return $dataProvider;
}
// grid filtering conditions
$query->andFilterWhere([
'productId' => $this->productId,
'price' => $this->price,
'created_at' => $this->created_at,
'created_by' => $this->created_by,
]);
$query->andFilterWhere(['MONTH(date)' => $this->date])
->andFilterWhere(['like', 'name', $this->name])
->andFilterWhere(['like', 'address', $this->address]);
return $dataProvider;
}
}
public function rules()
{
return [
[['productId', 'userId', 'parentId'], 'integer'],
[['date', 'created_at', 'name', 'address'], 'safe'],
[['price'], 'number'],
[['created_by'], 'string'],
];
}
public function search($params)
{
$query = Product::find()->joinWith('createdBy'); // Whatever relation name
.
.
.
.
.
// grid filtering conditions
$query->andFilterWhere([
'productId' => $this->productId,
'price' => $this->price,
'created_at' => $this->created_at,
]);
$query->andFilterWhere(['MONTH(date)' => $this->date])
->andFilterWhere(['like', 'name', $this->name])
->andFilterWhere(['like', 'address', $this->address])
->andFilterWhere(['like', 'userTableName.username', $this->created_by]); // Whatever table name and field name.
return $dataProvider;
}
You should add a proper filter to your column
[
'attribute'=>'your_attribute',
......
'filter'=>ArrayHelper::map(YourModel::find()->asArray()->all(),
'your_id_column', 'your_name_column'),
],

there is no any change to the rows displayed when doing "search" in yii2

I have problem when making modelsearch in yii2. Here's is relation diagram
I want to display Jurusan from table aitambah to table ais3 and I want to display NamaMahasiswa from table ai to ais3. I made table s3penghubung so that table aitambah can be related to ais3. I was able to display them. But, when I try to type "BIO" in Jurusan field, the searching not working properly. it is refreshing the page. there is no any change to the rows displayed. so, what should I do to fix that?
MODEL SEARCH CODE
<?php
namespace app\models;
use Yii;
use yii\base\Model;
use yii\data\ActiveDataProvider;
use app\models\Ais3;
use app\models\AiTambah;
/**
* Ais3Search represents the model behind the search form about `app\models\Ais3`.
*/
class Ais3Search extends Ais3
{
/**
* #inheritdoc
*/
public function rules()
{
return [
[['id', 'kode'], 'integer'],
[['NRP', 'NRP1', 'NRP2', 'NRP3', 'NRP4', 'NRP5', 'NRP6', 'NRP7', 'namaMahasiswaText', 'ProgramStudi', 'TanggalMasuk', 'TanggalKeluar', 'jURUSANText','NAMKANTOR','ANGKATAN'], 'safe'],
];
}
public $NamaMahasiswa;
public $namaMahasiswaText;
public $NRP1;
public $NRP2;
public $NRP3;
public $NRP4;
public $NRP5;
public $NRP6;
public $NRP7;
public $JURUSAN;
public $jURUSANText;
public $NAMKANTOR;
public $ANGKATAN;
/**
* #inheritdoc
*/
public function scenarios()
{
// bypass scenarios() implementation in the parent class
return Model::scenarios();
}
/**
* Creates data provider instance with search query applied
*
* #param array $params
*
* #return ActiveDataProvider
*/
public function search($params)
{
$query = Ais3::find();
$query->joinWith('ai');
// add conditions that should always apply here
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$this->load($params);
if (!$this->validate()) {
// uncomment the following line if you do not want to return any records when validation fails
// $query->where('0=1');
return $dataProvider;
}
// grid filtering conditions
$query->andFilterWhere([
'id' => $this->id,
'kode' => $this->kode,
]);
$query->andFilterWhere(['like', 'ais3.NRP', $this->NRP])
->andFilterWhere(['like', 'ai.NamaMahasiswa', $this->namaMahasiswaText])
->andFilterWhere(['like', 'ais3.ProgramStudi', $this->ProgramStudi])
->andFilterWhere(['like', 'ai.TanggalMasuk', $this->TanggalMasuk])
->andFilterWhere(['like', 'ais3.TanggalKeluar', $this->TanggalKeluar])
->andFilterWhere(['like', 'aitambah.JURUSAN', $this->JURUSAN]);
return $dataProvider;
}
}
MY GRIDVIEW CODE
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
//'id',
'NRP',
'namaMahasiswaText',
'ProgramStudi',
//'TanggalMasuk',
[
'attribute' => 'TanggalMasuk',
'value' => function($data) {
return $data->ai->TanggalMasuk;
},],
'TanggalKeluar',
//YANG DITAMBAH
/*[
'attribute'=>'NRP1',
'value'=>'s3penghubung.aitambah.JURUSAN',
'label' => 'Jurusan',
],*/
'jURUSANText',
[
'attribute'=>'NRP2',
'value'=>'s3penghubung.aitambah.NAMKANTOR',
'label' => 'Nama Kantor',
],
[
'attribute'=>'NRP3',
'value'=>'s3penghubung.aitambah.ANGKATAN',
'label' => 'Angkatan',
],
[
'attribute'=>'NRP4',
'value'=>'s3penghubung.aitambah.TELP',
'label' => 'Nomor HP/Telp',
],
[
'attribute'=>'NRP5',
'value'=>'s3penghubung.aitambah.PEKERJAAN',
'label' => 'Pekejaan',
],
[
'attribute'=>'NRP6',
'value'=>'s3penghubung.aitambah.EMAIL',
'label' => 'Email',
],
[
'attribute'=>'NRP7',
'value'=>'s3penghubung.aitambah.KODEPROP',
'label' => 'KodeProp',
],
// 'kode',
['class' => 'yii\grid\ActionColumn'],
],
]); ?>
MY MODEL'S CODE
<?php
namespace app\models;
use Yii;
/**
* This is the model class for table "ais3".
*
* #property integer $id
* #property string $NRP
* #property string $ProgramStudi
* #property string $TanggalMasuk
* #property string $TanggalKeluar
* #property integer $kode
*
* #property Ai $nRP
* #property S3penghubung $kode0
*/
class Ais3 extends \yii\db\ActiveRecord
{
/**
* #inheritdoc
*/
public static function tableName()
{
return 'ais3';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['kode'], 'required'],
[['kode'], 'integer'],
[['NRP'], 'string', 'max' => 15],
[['ProgramStudi'], 'string', 'max' => 5],
[['TanggalMasuk', 'TanggalKeluar'], 'string', 'max' => 20],
[['NRP'], 'exist', 'skipOnError' => true, 'targetClass' => Ai::className(), 'targetAttribute' => ['NRP' => 'NRP']],
[['kode'], 'exist', 'skipOnError' => true, 'targetClass' => S3penghubung::className(), 'targetAttribute' => ['kode' => 'kode']],
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => Yii::t('app', 'ID'),
'NRP' => Yii::t('app', 'Nrp'),
'ProgramStudi' => Yii::t('app', 'Program Studi'),
'TanggalMasuk' => Yii::t('app', 'Tanggal Masuk'),
'TanggalKeluar' => Yii::t('app', 'Tanggal Keluar'),
'kode' => Yii::t('app', 'Kode'),
'namaMahasiswaText' => Yii::t('app', 'Nama Mahasiswa'),
'jURUSANText' => Yii::t('app', 'Jurusan'),
];
}
/**
* #return \yii\db\ActiveQuery
*/
public function getai()
{
return $this->hasOne(Ai::className(), ['NRP' => 'NRP']);
}
/**
* #return \yii\db\ActiveQuery
*/
public function getS3penghubung()
{
return $this->hasOne(S3penghubung::className(), ['kode' => 'kode']);
}
//YANG DITAMBAH
public function getRelasiS3()
{
return array(
'aitambah'=>array(self::MANY_MANY, 'Aitambah', 'S3Penghubung(AiS3.id, Aitambah.NRP)'),
);
}
public function getNamaMahasiswaText()
{
$ai = ai::findOne(['NRP'=> $this->NRP]);
if (empty($ai))
return '';
return $ai->NamaMahasiswa;
}
public function getJURUSANText()
{
$aitambah = aitambah::findOne(['NRP'=> $this->NRP]);
if (empty($aitambah))
return '';
return $aitambah->JURUSAN;
}
}
I dont know how to fix those codes. Could you please help me to solve this? Thankyou
Your code is very difficult to debug. Try to keep a consistency for your naming conventions. The Yii way is all lower case letters separated with underscores.
Please read this and this about displaying and sorting relations.
As for the solution you can experiment a bit with the following:
Create a new relation in your model:
/**
* #return \yii\db\ActiveQuery
*/
public function getAitambah()
{
return $this->hasOne(Aitambah::className(), ['NRP' => 'NRP']);
}
Then in your SearchModel:
public function rules()
{
return [
[['id', 'kode'], 'integer'],
[['NRP', 'NRP1', 'NRP2', 'NRP3', 'NRP4', 'NRP5', 'NRP6', 'NRP7', 'namaMahasiswaText', 'ProgramStudi', 'TanggalMasuk', 'TanggalKeluar', 'jURUSANText','NAMKANTOR','ANGKATAN', 'JURUSAN'], 'safe'],
];
}
And in your search method:
...
$query = Ais3::find();
query->joinWith(['ai ai', 'aitambah aitambah']);
...
Finally in your view:
[
'attribute' => 'JURUSAN',
'value' => 'aitambah.JURUSAN',
'label' => 'JURUSAN',
],

Yii2 rest api join query with ActiveDataProvider

I have a custom action in ActiveController and need to fetch some data by joining two tables.
I have written following query .
$query = Item::find()->joinWith(['subcategory'])->select(['item.*', 'sub_category.name'])->where(['item.active' => 1])->addOrderBy(['item.id' => SORT_DESC]);
$pageSize = (isset($_GET["limit"]) ? $_GET["limit"] : 1) * 10;
$page = isset($_GET["page"]) ? $_GET["page"] : 1;
$dataProvider = new ActiveDataProvider(['query' => $query, 'pagination' => ['pageSize' => $pageSize, "page" => $page]]);
$formatter = new ResponseFormatter();
return $formatter->formatResponse("", $dataProvider->getTotalCount(), $dataProvider->getModels());
but it is throwing an exception
"message": "Setting unknown property: common\\models\\Item::name",
Here is the item Model with all the fields and relation.
<?php
namespace common\models;
use Yii;
use yii\behaviors\TimestampBehavior;
use yii\db\BaseActiveRecord;
use yii\db\Expression;
/**
* This is the model class for table "item".
*
* #property integer $id
* #property integer $subcategory_id
* #property string $title
* #property resource $description
* #property integer $created_by
* #property integer $updated_by
* #property string $created_at
* #property string $updated_at
* #property string $image
* #property integer $active
*
* #property SubCategory $subcategory
*/
class Item extends \yii\db\ActiveRecord
{
public $imageFile;
/**
* #inheritdoc
*/
public static function tableName()
{
return 'item';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['created_by', 'updated_by'], 'required'],
[['subcategory_id', 'created_by', 'updated_by', 'active'], 'integer'],
[['description'], 'string'],
[['created_at', 'updated_at'], 'safe'],
[['title', 'image'], 'string', 'max' => 999],
[['title'], 'unique'],
[['imageFile'], 'file', 'skipOnEmpty' => true, 'extensions' => 'png, jpg'],
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'subcategory_id' => 'Subcategory ID',
'title' => 'Title',
'description' => 'Description',
'created_by' => 'Created By',
'updated_by' => 'Updated By',
'created_at' => 'Created At',
'updated_at' => 'Updated At',
'image' => 'Image',
'active' => 'Active',
'imageFile' => 'Image',
];
}
/**
* #return \yii\db\ActiveQuery
*/
public function getSubcategory()
{
return $this->hasOne(SubCategory::className(), ['id' => 'subcategory_id']);
}
/**
* #return \yii\db\ActiveQuery
*/
public function getCreatedBy()
{
return $this->hasOne(User::className(), ['id' => 'created_by']);
}
/**
* #return \yii\db\ActiveQuery
*/
public function getUpdatedBy()
{
return $this->hasOne(User::className(), ['id' => 'updated_by']);
}
public function behaviors()
{
return [
'timestamp' => [
'class' => TimestampBehavior::className(),
'attributes' => [
BaseActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'],
BaseActiveRecord::EVENT_BEFORE_UPDATE => 'updated_at',
],
'value' => new Expression('NOW()'),
],
];
}
}
The joinWith makes a query using the joins requested, but result data are mapped in source model (in this case Item).
Since you have select(['item.*', 'sub_category.name']) , the framework will try to fill 'name' field of Item model, that does not exist and this generates the error.
According with documentation (http://www.yiiframework.com/doc-2.0/guide-rest-resources.html#overriding-extra-fields) you should have db relation subcategory populated from db, by default, but I don't see subcategory relation in your model.
So you have only to create subcategory relation in your model, such as:
public function getSubcategory() { return $this->hasOne(Subcategory::className(), ['id' => 'subcategory_id']); }
So you should solve your problem.
Other solution to have custom fields from more models could be:
1) Create a sql View (and from that create the Model) with fields that you want and pass it to ActiveDataProvide
2) Override extraFields method of the model (http://www.yiiframework.com/doc-2.0/yii-base-arrayabletrait.html#extraFields%28%29-detail)
Again, I suggest you to read this good article:
http://www.yiiframework.com/wiki/834/relational-query-eager-loading-in-yii-2-0/

Categories