Here am trying Dependent dropdown using kartik depdrop yii2 extension . the process of this dependent dropdown is, if i select a productname it will show me the dependent batchno, then if select a batchno, it will show the dependent itemid.
Actually first level is working perfectly, if i select a productname, it will show me batchno, this action is working perfectly, but the problem on the second level. if i select a batchno it need to show me a itemid, this action is not working
And am getting error as this image -
Controller
public function actionSubcat() {
$out = [];
if (isset($_POST['depdrop_parents'])) {
$parents = $_POST['depdrop_parents'];
if ($parents != null) {
$cat_id = $parents[0];
$out = Productbatch::getBatchNo($cat_id);
echo Json::encode($out);
// the getSubCatList function will query the database based on the
// cat_id and return an array like below:
// [
// ['id'=>'<sub-cat-id-1>', 'name'=>'<sub-cat-name1>'],
// ['id'=>'<sub-cat_id_2>', 'name'=>'<sub-cat-name2>']
// ]
//echo Json::encode(['output'=>$out, 'selected'=>'']);
return;
}
}
echo Json::encode(['output'=>'', 'selected'=>'']);
}
public function actionProd() {
$out = [];
if (isset($_POST['depdrop_parents'])) {
$ids = $_POST['depdrop_parents'];
$cat_id = empty($ids[0]) ? null : $ids[0];
$subcat_id = empty($ids[1]) ? null : $ids[1];
if ($cat_id != null) {
$data = Productbatch::getItemid($cat_id, $subcat_id);
/**
* the getProdList function will query the database based on the
* cat_id and sub_cat_id and return an array like below:
* [
* 'out'=>[
* ['id'=>'<prod-id-1>', 'name'=>'<prod-name1>'],
* ['id'=>'<prod_id_2>', 'name'=>'<prod-name2>']
* ],
* 'selected'=>'<prod-id-1>'
* ]
*/
echo Json::encode($out);
//echo Json::encode(['output'=>$out, 'selected'=>$data['selected']]);
return;
}
}
echo Json::encode(['output'=>'', 'selected'=>'']);
}
_form
<?= $form->field($model, 'productname')->widget(Select2::classname(), [
'data' => ArrayHelper::map(Productnames::find()->all(),'productnames_productname','productnames_productname'),
'language' => 'en',
'options' => ['placeholder' => 'Select Product Name', 'id' => 'cat-id'],
'pluginOptions' => [
'allowClear' => true
],
]); ?>
<?= $form->field($model, 'batchno')->widget(DepDrop::classname(), [
'options'=>['id'=>'subcat-id'],
'pluginOptions'=>[
'depends'=>['cat-id'],
'placeholder'=>'Select BatchNo',
'url'=>Url::to(['/production/productbatch/subcat'])
]
]); ?>
<?= $form->field($model, 'itemid')->widget(DepDrop::classname(), [
'pluginOptions'=>[
'depends'=>['cat-id', 'subcat-id'],
'placeholder'=>'Select ItemId',
'url'=>Url::to(['/production/productbatch/prod'])
]
]); ?>
Model
public static function getBatchNo($cat_id)
{
$out = [];
$data = Productbatch::find()
->where(['productname' => $cat_id])
->asArray()
->all();
foreach ($data as $dat) {
$out[] = ['id' => $dat['itemid'], 'name' => $dat['batchno']];
}
return $output = [
'output' => $out,
'selected' => ''
];
}
public static function getItemid($cat_id, $subcat_id)
{
$out = [];
$data = Productbatch::find()
->where(['productname' => $cat_id])
->andWhere(['batchno' => $subcat_id])
->asArray()
->all();
$selected = '';
foreach ($data as $dat => $datas) {
$out[] = ['id' => $datas['itemid'], 'name' => $datas['itemid']];
if($dat == 0){
$aux = $datas['itemid'];
}
($datas['productname'] == $cat_id) ? $selected = $cat_id : $selected = $aux;
}
return $output = [
'output' => $out,
'selected' => $selected
];
}
You need do like this in your controller. You have to create new action in controller .
public function actionState() {
$country_id = $_POST['depdrop_parents'][0];
$state = State::find()->where(['country_id' => $country_id])->all();
$all_state = array();
$i = 0;
foreach ($state as $value) {
$all_state[$i]['id'] = $value['state_id'];
$all_state[$i]['name'] = $value['state_name'];
$i++;
}
echo Json::encode(['output' => $all_state, 'selected' => '']);
return;
}
i also suffered from this problem but finally I solved this issue..
Related
I make a parser of items from DotA 2 user inventory in the Steam service. Every time I try to parse user data, I get an empty value:
{"success":true,"items":[]}, but there are items in my Steam inventory.
My function to parse items:
public function loadMyInventory() {
if(Auth::guest()) return ['success' => false];
$prices = json_decode(Storage::get('prices.txt'), true);
$response = json_decode(file_get_contents('https://steamcommunity.com/inventory/'.$this->user->steamid64.'/570/2?l=russian&count=5000'), true);
if(time() < (Session::get('InvUPD') + 5)) {
return [
'success' => false,
'msg' => 'Error, repeat in '.(Session::get('InvUPD') - time() + 5).' сек.',
'status' => 'error'
];
}
//return $response;
$inventory = [];
foreach($response['assets'] as $item) {
$find = 0;
foreach($response['descriptions'] as $descriptions) {
if($find == 0) {
if(($descriptions['classid'] == $item['classid']) && ($descriptions['instanceid'] == $item['instanceid'])) {
$find++;
# If we find the price of an item, then move on.
if(isset($prices[$descriptions['market_hash_name']])) {
# Search data
$price = $prices[$descriptions['market_hash_name']]*$this->config->curs;
$class = false;
$text = false;
if($price <= $this->config->min_dep_sum) {
$price = 0;
$text = 'Cheap';
$class = 'minPrice';
}
if(($descriptions['tradable'] == 0) || ($descriptions['marketable'] == 0)) {
$price = 0;
$class = 'minPrice';
$text = 'Not tradable';
}
# Adding to Array
$inventory[] = [
'name' => $descriptions['market_name'],
'price' => floor($price),
'color' => $this->getRarity($descriptions['tags']),
'tradable' => $descriptions['tradable'],
'class' => $class,
'text' => $text,
'classid' => $item['classid'],
'assetid' => $item['assetid'],
'instanceid' => $item['instanceid']
];
}
}
}
}
}
Session::put('InvUPD', (time() + 5));
return [
'success' => true,
'items' => $inventory
];
}
But should return approximately the following value:
{"success":true,"items":[{"classid":"2274725521","instanceid":"57949762","assetid":"18235196074","market_hash_name":"Full-Bore Bonanza","price":26}]}
Where my mistake?
First of all, you are iterating on descriptions for every assets, which is assets*descriptions iteration, it's quite a lot, but you can optimize this.
let's loop once for descriptions and assign classid and instanceid as object key.
$assets = $response["assets"];
$descriptions = $response["descriptions"];
$newDescriptions=[];
foreach($descriptions as $d){
$newDescriptions[$d["classid"]][$d["instanceid"]] = $d;
}
this will give as the ability to not loop over description each time, we can access the description of certain asset directly $newDescriptions[$classid][$instanceid]]
foreach($assets as $a){
if(isset($newDescriptions[$a["classid"]]) && isset($newDescriptions[$a["classid"]][$a["instanceid"]])){
$assetDescription = $newDescriptions[$a["classid"]][$a["instanceid"]];
$inventory = [];
if(isset($prices[$assetDescription["market_hash_name"]])){
$price = $prices[$assetDescription['market_hash_name']]["price"]*$this->config->curs;
$class = false;
$text = false;
if($price <= $this->config->min_dep_sum) {
$price = 0;
$text = 'Cheap';
$class = 'minPrice';
}
if(($assetDescription['tradable'] == 0) || ($assetDescription['marketable'] == 0)) {
$price = 0;
$class = 'minPrice';
$text = 'Not tradable';
}
$inventory["priceFound"][] = [
'name' => $assetDescription['market_name'],
'price' => floor($price),
'color' => $this->getRarity($assetDescription['tags']),
'tradable' => $assetDescription['tradable'],
'class' => $class,
'text' => $text,
'classid' => $a['classid'],
'assetid' => $a['assetid'],
'instanceid' => $a['instanceid']
];
}else{
$inventory["priceNotFound"][] = $assetDescription["market_hash_name"];
}
}
}
About your mistake:
are you Sure your "prices.txt" contains market_hash_name?
I don't see any other issue yet, operationg on the data you have provided in comment, I got print of variable $assetDescription. Please doublecheck variable $prices.
I'd display the values in sorting order by title. It shows the values sorting only by page_order, I edited Page_model->get_pages() order_by('page_order') to order_by('title') but it continues to display by page_order. I can't seem to find an answer on this topic. How can I sort the values by title in the following code:
<?php
foreach ($menu_links as $item):
if ($item['parent_id'] != "0" && $item['subcat_recip_id'] != "" ):
?>
<?php
$valuesub = explode(",",$item['subcat_recip_id']);
foreach($valuesub as $dt):
if (html_escape("$dt") == html_escape("$subrecp")):
?>
<li><?php echo html_escape($item["title"]) ?></li>
<?php
endif;
endforeach;
?>
<?php
endif;
endforeach;
?>
Recipes Model
* recipes Page
*/
public function recipes()
{
$this->load->model('page_model');
$data['page'] = $this->page_model->get_page('recipes');
if ($data['page']->page_active == 0) {
$this->error_404();
} else {
$data['title'] = get_page_title($data['page']);
$data['description'] = get_page_description($data['page']);
$data['keywords'] = get_page_keywords($data['page']);
$data['page_settings'] = get_page_settings();
$data['menu_links'] = $this->navigation_model->get_menu_links();
$this->load->view('partials/_header', $data);
$this->load->view('recipes', $data);
$this->load->view('partials/_footer');
}
}
Navigation_model->get_Menu_links
public function get_menu_links()
{
$menu = array();
$pages = $this->page_model->get_pages();
if (!empty($pages)) {
foreach ($pages as $page) {
$page_type = "page";
if (!empty($page->link)) {
$page_type = "link";
}
$item = array(
'order' => $page->page_order,
'id' => $page->id,
'lang_id' => $page->lang_id,
'parent_id' => $page->parent_id,
'subcat_recip_id' => $page->subcat_recip_id,
'title' => $page->title,
'slug' => $page->slug,
'link' => lang_base_url() . $page->slug,
'type' => $page_type,
'location' => $page->location,
'visibility' => $page->page_active,
'subcat_recip_id' => $page->subcat_recip_id,
);
if ($page_type == "link") {
$item["link"] = $page->link;
}
if ($page->slug == "index") {
$item["link"] = lang_base_url();
}
array_push($menu, $item);
}
}
$categories = $this->category_model->get_categories();
if (!empty($categories)) {
foreach ($categories as $category) {
$item = array(
'order' => $category->category_order,
'id' => $category->id,
'lang_id' => $category->lang_id,
'parent_id' => $category->parent_id,
'title' => $category->name,
'slug' => $category->slug,
'link' => lang_base_url() . "category/" . $category->slug,
'type' => "category",
'location' => "header",
'visibility' => $category->show_on_menu,
'subcat_recip_id' => $page->subcat_recip_id,
);
array_push($menu, $item);
}
}
sort($menu);
return $menu;
}
Page_model->get_pages
//get pages
public function get_pages()
{
$this->db->where('pages.lang_id', $this->selected_lang->id);
$this->db->order_by('page_order');
$query = $this->db->get('pages');
return $query->result();
}
You can use ksort() function.
Refer from here (offical documentation).
First try to remove sort($menu); from get_menu_links(). Otherwise, whatever order you get in get_pages(), it will be ruined by the sorting.
In either case you can use usort which allows to sort an array using custom compare function.
The comparison function must return an integer less than, equal to, or
greater than zero if the first argument is considered to be
respectively less than, equal to, or greater than the second.
usort($menu_links, function($a, $b) {
return strcmp($a['title'], $b['title']);
});
I have an editable GridView in my Yii2 app and using kartik EditableColumn. When there was only one editable column everything works Ok but when I tried to add one more editable column it saves editted value of Price column and sets to zero the value of expire_days column. The same for opposite way(if update expire_days it saves the value but sets to zero the Price value).
The View:
'columns' => [
[
'class'=>'kartik\grid\EditableColumn',
'attribute' => 'price',
'editableOptions'=>[
'header'=>' ',
'inputType'=>\kartik\editable\Editable::INPUT_SPIN,
'options'=>['pluginOptions'=>['min'=>0, 'max'=>5000000]]
],
'value' => function ($model) {
return $model->price;
},
'filter' => Category::getPrices(),
'format' => 'raw'
],
[
'class'=>'kartik\grid\EditableColumn',
'attribute' => 'expire_days',
'editableOptions'=>[
'header'=>' ',
'inputType'=>\kartik\editable\Editable::INPUT_SPIN,
'options'=>['pluginOptions'=>['min'=>0, 'max'=>100]]
],
'value' => function ($model) {
return $model->expire_days;
},
'filter' => Category::getExpDays(),
'format' => 'raw'
],
]
Controller:
if (Yii::$app->request->post('hasEditable')) {
$model = new Category();
$id = Yii::$app->request->post('editableKey');
$model = Category::findOne($id);
$out = Json::encode(['output'=>'', 'message'=>'']);
$post = [];
$posted = current($_POST['Category']);
$post['Category'] = $posted;
if ($model->load($post)) {
$model->price = $post['Category']['price'];
$model->expire_days = $post['Category']['expire_days'];
$model->save();
$output = '';
$out = Json::encode(['output'=>$output,'message'=>'']);
}
echo $out;
return;
}
You should separately process two scenarios:
if ($model->load($post)) {
if ($post['Category'] && $post['Category']['price']) {
$model->price = $post['Category']['price'];
}
if ($post['Category'] && $post['Category']['expire_days']) {
$model->expire_days = $post['Category']['expire_days'];
}
$model->save();
$output = '';
$out = Json::encode(['output'=>$output,'message'=>'']);
}
If you receive price - you update only price. If you receive expire_days - update expire_days.
I have an array for showing users' contacts list to each other.
I want to add ->paginate(10) features for json response but I could not find where I must put it.
My index function:
public function index()
{
$contacts = [];
$user = request()->user();
// Loop through the contacts and format each one
Contact::for($user->id)->get()->each(function ($contact) use ($user, &$contacts) {
$friend = $contact->user1_id === $user->id ? $contact->user2 : $contact->user1;
$contacts[] = $friend->toArray() + ['room' => $contact->room->toArray()];
});
return response()->json($contacts);
}
You can create a collection for the contact and use LenfthAwarePaginator
class ContactResourceCollection extends ResourceCollection
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request
* #return array
*/
public function toArray($request)
{
$response = [
'data' => $this->collection,
];
if($this->resource instanceof LengthAwarePaginator)
{
$response['pagination'] = [
'total' => $this->resource->total(),
'lastPage' => $this->resource->lastPage(),
'perPage' => $this->resource->perPage(),
'currentPage' => $this->resource->currentPage(),
'nextPageUrl' => $this->resource->nextPageUrl(),
'previousPageUrl' => $this->resource->previousPageUrl(),
];
}
return $response;
}
}
In the controller method add this line:
return new UserResourceCollection($users);
Here is the total code
$contacts = Contact::where('user_id', $user->id)->paginate(12);
if($contacts->count()){
$pageIndex = array();
$lastPage = $contacts->lastPage();
$user = request()->user();
for($i= 2; $i<=$lastPage; $i++){
array_push($pageIndex, $i);
}
return response()->json([
'contacts' => $contacts->map(function ($contact) use ($user) {
if($contact->user1_id === $user->id){
return [
'friend' => $contact->user2,
'room' => $contact->room,
];
} else {
return [
'friend' => $contact->user1,
'room' => $contact->room,
];
}
})->toArray(),
'per_page' => $contacts->perPage(),
'on_first_page' => $contacts->onFirstPage(),
'last_page' => $contacts->lastPage(),
'first_page_url' => $contacts->url(1),
'next_page_url' => $contacts->nextPageUrl(),
'prev_page_url' => $contacts->previousPageUrl(),
'last_page_url' => $contacts->url($contacts->lastPage()),
'total' => $contacts->total(),
'pageIndexArray' => $pageIndex,
'errors' => false,
]);
} else {
// Do Nothing
}
Call
GET 'URL?page='+Page_index to get the response in JS (AJAX)
I am not sure but try : replace get() to paginate(10)
Contact::for($user->id)->paginate(10)->each(function ($contact) use ($user, &$contacts) {
$friend = $contact->user1_id === $user->id ? $contact->user2 : $contact->user1;
$contacts[] = $friend->toArray() + ['room' => $contact->room->toArray()];
});
Can you change the query into:
$contacts = Contact::for($user->id)->paginate(10);
Then after this query you can use for loop for $contact;
foreach ($contacts as $key => $contact)
{
$friend = $contact->user1_id === $user->id ? $contact->user2 : $contact->user1;
$contacts[] = $friend->toArray() + ['room' => $contact->room->toArray()];
}
Paginate first before get into loop/each.
Actually I need to call a function inside an array value.
this my function
public function RelationName()
{
return $this->name .'--'. $this->relationship;
}
I need to call this above function in another function which present same class file
this is my another function:
public static function getClaimerNameList($cat_id, $subcat_id)
{
$out = [];
$emp_code = Employee::find()
->where(['importcompany_id' => $cat_id])
->andWhere(['id' => $subcat_id])
->all();
foreach ($emp_code as $dat => $datas) {
$out[] = ['id' => $datas['id'], 'name' => $datas['name'] ];
if($dat == 0){
$aux = $datas['id'];
}
($datas['id'] == $subcat_id) ? $selected = $subcat_id : $selected = $aux;
}
return $output = [
'output' => $out,
'selected' => $selected
];
}
Actually I need to call function here
foreach ($emp_code as $dat => $datas) {
$out[] = ['id' => $datas['id'], 'name' => $datas['name'] ];
}
instead 'name' => $datas['name'] of this, I need to call a function getRelationName()
without using function am getting output like
id name
1 raja
2 ram
but I don't wanna output like that, if I use a function I will get output like below
id name
1 raja-father
2 ram-son
Help me to sort out this problem
You need to call it like this
foreach ($emp_code as $dat => $datas)
{
$out[] = ['id' => $datas['id'], 'name' => $datas->RelationName() ];
//more code...
}
And RelationName() need to be located in the Employee class and it shouldn't be static