i have this json data come from a url:
[
{
"id": "4070",
"title": "Speedway Racing",
"description": "Drivers start your engines! Professional oval track racing that explodes with stock car racing action!",
"instructions": "Use WASD or Arrow keys to move the car ",
"url": "https://html5.gamemonetize.com/b7dzsckxzmy5z3to54nif435exdiogkz/",
"tags": "Car, Cars, Racing",
"thumb": "https://img.gamemonetize.com/b7dzsckxzmy5z3to54nif435exdiogkz/512x384.jpg",
"width": "960",
"height": "600",
"category": "Driving"
},]
I need to save all data in database but for category i need to create new category from the category fled and save it in post_categry table (cat_id, post_id) if his not exists, also check f this game exists in db if yes ignore if no save it.
My GameController:
the json data come from this lik:
This link
public function importer_start(Request $request)
{
$game_cat = new Game;
$validatedata = $this->validate($request, [
'game_source' => 'required',
'source_url' => 'required|url',
]);
$dataurl = $request->input('source_url');
$sourve_name = $request->input('game_source');
$content = file_get_contents($dataurl);
$data = json_decode($content, true);
$query_ammount = $request->input('source_url');
parse_str($query_ammount, $params);
$game_amount = $params['amount'];
$query_ammount = $request->input('source_url');
parse_str($query_ammount, $params);
$game_amount = $params['amount'];
$url = $request->input('source_url');
$parmt_url = parse_url($url);
parse_str($parmt_url['query'], $params);
if ($params['format'] != 'json') {
toastr()->error('Please select JSON file to import games');
return redirect()->back();
}
if (#strpos($dataurl, Constants::GAMESOURCE_GAMEMONETIZE)) {
$finalarray = array();
foreach ($data as $key=>$value) {
// dd($value);
array_push($finalarray,array(
'game_id' => $value['id'],
'title' => $value['title'],
'description' => $value['description'],
'instructions' => $value['instructions'],
'url' => $value['url'],
'category' => !empty($value['category']) ? $value['category']: 'uncategorized',
'tags' => $value['tags'],
'thumb' => $value['thumb'],
'width' => $value['width'],
'height' => $value['height'],
'source' => Constants::GAMESOURCE_GAMEMONETIZE,
'views' => 15,
)
);
}
$categories[] = $value['category'];
Game::insert($finalarray);
toastr()->success('You have add '.$game_amount.' from '.\Constants::GAMESOURCE_GAMEMONETIZE.'');
return redirect()->route('admin.importer');
}elseif (#strpos($dataurl, Constants::GAMESOURCE_GAMEDISTRIBUTION)) {
$result = json_decode(json_encode($data), true);
$key = array_search('categoryList', array_column($result, 'categoryList'));
$finalarray = array();
foreach ($data as $key=>$value) {
array_push($finalarray,array(
'title' => $value['title'],
'gameType' => $value['gameType'],
'gameMobile' => $value['gameMobile'],
'mobileMode' => $value['mobileMode'],
'instructions' => $value['instructions'],
'description' => $value['description'],
'width' => $value['width'],
'height' => $value['height'],
'url' => $value['url'],
'source' => Constants::GAMESOURCE_GAMEDISTRIBUTION,
'assetList' => json_encode($value['assetList']),
'tagList' => json_encode($value['tagList']),
'category' => $value['categoryList'][0]['name'],
'views'=> 15,
)
);
}
//dd($finalarray);
Game::insert($finalarray);
toastr()->success('You have add '.$game_amount.' from '.\Constants::GAMESOURCE_GAMEDISTRIBUTION.'');
return redirect()->route('admin.importer');
}
}
Laravel version: 7.0
Thank you for your helpe.
Related
I have created a custom restful API endpoint in WordPress which returns the JSON with the only required fields.
So with this one when I go to the example.com/wp-json/wl/posts, it returns 5 posts as I have limited the number of the posts.
function wl_posts() {
$args = [
'numberposts' => 99999,
'post_type' => 'post'
];
$posts = get_posts($args);
$data = [];
$i = 0;
foreach($posts as $post) {
$data[$i]['id'] = $post->ID;
$data[$i]['title'] = $post->post_title;
$data[$i]['content'] = $post->post_content;
$data[$i]['slug'] = $post->post_name;
$data[$i]['featured_image']['thumbnail'] = get_the_post_thumbnail_url($post->ID, 'thumbnail');
$i++;
}
return $data;
}
add_action('rest_api_init', function() {
register_rest_route('wl/v1', 'posts', [
'methods' => 'GET',
'callback' => 'wl_posts',
]);
});
But I also want to add the pagination, so if I add ?page=2 , it should return another 5 posts.
How can that be archived?
When visiting /?rest_route=/ or /wp-json/wp/v2/pages you can drill down into ie. wp/v2/pages/endpoints/0/args then check with page and per_page
curl http://YOUR-SITE/wp-json/wl/v1/posts/?per_page=1&page=2
Publish arguments for reference
We can define and publish these as arguments. This is not required but they are now in line with posts and pages
add_action('rest_api_init', function() {
register_rest_route('wl/v1', 'posts', [
'methods' => 'GET',
'callback' => 'wl_posts',
'args' => [
'page' => [
'description' => 'Current page',
'type' => "integer",
],
'per_page' => [
'description' => 'Items per page',
'type' => "integer",
]
],
]);
});
Fetch arguments
As get_posts has its own logic and it uses WP_Query in the end let's use WP_Query for the better.
function wl_posts() {
$args = [];
if (isset($_REQUEST['per_page'])) {
$args['posts_per_page'] = (int) $_REQUEST['per_page'];
}
if (isset($_REQUEST['page'])) {
$args['page'] = (int) $_REQUEST['page'];
}
$args['post_type'] = 'post';
$get_posts = new WP_Query;
$posts= $get_posts->query( $args );
$data = [];
$i = 0;
foreach($posts as $post) {
$data[$i]['id'] = $post->ID;
$data[$i]['title'] = $post->post_title;
$data[$i]['content'] = $post->post_content;
$data[$i]['slug'] = $post->post_name;
$data[$i]['featured_image']['thumbnail'] =
get_the_post_thumbnail_url($post->ID, 'thumbnail');
$i++;
}
return $data;
}
I have made a Listbox depend on a dropDownList, when selecting an option from the dropDownList brings me a list of data that is added to the Listbox, it works to save a single option but the problem occurs when trying to save multiple selections, I cannot save more than 1 option, I have tried to add a foreach in my controller but it throws an error.
DropDownList
<?php echo $form->field($model, 'group_id')->widget(Select2::classname(), [
'data' => $seccion->lgrupo, //I get the group list
'size' => Select2::MEDIUM,
'theme' => Select2::THEME_BOOTSTRAP,
'options' => [
'placeholder' => '-- '.Yii::t('backend', 'Select').' --',
'onchange'=>'
$.post( "lists?id="+$(this).val(), function( data ) {//I get the list of people registered in the group and send it to the listbox
$( "select#assignment-user_id" ).html( data );
});',
],
'pluginOptions' => [
'allowClear' => true,
],
'addon' => [
'prepend' => [
'content' => Html::icon('building')
],
]
]); ?>
ListBox
<?php echo $form->field($model2, 'users_id')->listBox([] ,['multiple'=>true,'size'=>17]
); ?>
Groups Controller
public function actionCreate()
{
$model = new Groups();
$model2 = new Assignment();
$seccion = new Group();
if ($model->load(Yii::$app->request->post()) && $model2->load(Yii::$app->request->post())) {
if ($model->save(false)) {
foreach ($model2->users_id as $i => $as) {
$as->assign_group_id = $model->id_group_list;
if ($model2->save()) {
} else {
// error in saving model
}
}
return $this->redirect(['view', 'id' => $model->id_group]);
}
}
return $this->render('create', [
'model' => $model,
'model2' => $model2,
'seccion' => $seccion,
]);
}
Tables
I hope your can tell me what I'm doing wrong.
public function actionCreate()
{
$model = new Groups();
$model2 = new Assignment();
$seccion = new Group();
if ($model->load(Yii::$app->request->post()) && $model2->load(Yii::$app->request->post())) {
if ($model->save(false)) {
foreach ($model2->users_id as $user_id) {
$assignmentModel = new Assignment();
$assignmentModel->user_id= $user_id;
$assignmentModel->assign_group_id = $model->id_group_list;
//$assignmentModel->area= ''; //if you want to set some value to these fields
//$assignmentModel->assignment= '';
if ($assignmentModel->save()) {
} else {
// error in saving model
}
}
return $this->redirect(['view', 'id' => $model->id_group]);
}
}
return $this->render('create', [
'model' => $model,
'model2' => $model2,
'seccion' => $seccion,
]);
}
I'm trying to implement a multiple models form using the form-wizard widget, with Profile as main model and few others as linked ones. When I select the entity type field for the main model, I would like to change the linked model for the next step, basing on the value of entity type field.
I have tried with this code:
Create Form Code
$modelUrlReletedModelsCreate = Profile::urlRelatedModelCreate();
$urlLinkedProfile = Url::to(['create']);
echo FormWizard::widget([
'formOptions'=>[
'id'=>'profile_form',
'enableClientValidation'=>true,
'enableAjaxValidation'=>true,
'validationUrl' => Url::to(['profile-models-validation'])
],
'theme' => FormWizard::THEME_MATERIAL_V,
'steps' => [
//step 1
[
'model' => $model,
'title' => \Yii::t('app', 'Profile'),
'fieldConfig' => [
'only' => ['entity_type_id', 'profile_type_id'],
'entity_type_id' => [
'widget' => Select2::class,
'options' => [
'data' => EntityType::arrayNamesList(),
'options' => ['placeholder' => \Yii::t('app','Select an element')],
'pluginEvents' => ['select2:select'=>'function(e){;'
. 'var type = $("#pr-ty-sel").val();'
. 'var profile= "'.($model->profile_id ? : "no").'";'
. '$.ajax({ method: "GET",'
. 'url:"'.$urlLinkedProfile.'",'
. 'data:{ entity_text : e.params.data.text,'
. 'entity_id : e.params.data.id,'
. 'profile_type_id : type,'
. 'profile_id : profile},'
. 'success: function(data){'
. '$("#profile_form").html(data);'
. '}'
. '});}'],
],
],
'profile_type_id' =>[
'widget' => Select2::class,
'options' => [
'data' => \app\models\ProfileType::arrayNamesList(),
'options' => ['placeholder' => \Yii::t('app','Select an element'),'id'=>'pr-ty-sel'],
],
]
],
'description' => \Yii::t('app', 'Add Profile Type Data'),
'formInfoText' => \Yii::t('app', 'Fill all fields'),
],
//step 2 I want ot change here $linkedModel
[
'model' => [$model,$linkedModel],
'title' => \Yii::t('app', 'Personal Data'),
'description' => \Yii::t('app', 'Insert Personal Data'),
],
]
]);
Controller Action Create Code
public function actionCreate($profileId = NULL)
{
if($profileId AND $profileId !== 'no'){
$model = $this->findModel($profileId);
}else{
$model = new Profile();
}
$profileLinkedModel = new ProfilePrivate();
$renderMethod = 'render';
if (Yii::$app->request->isAjax) {
$entityText = \Yii::$app->request->get('entity_text');
$entity_id = \Yii::$app->request->get('entity_id');
$profileTypeId = \Yii::$app->request->get('profile_type_id');
$profileId = \Yii::$app->request->get('profile_id');
//Utility function to clean the entity text (remove number and special characters)
$entityTextCleaned = \app\components\Utility::cleanString($entityText);
if ($entityTextCleaned == 'private') {
$profileLinkedModel = new ProfilePrivate();
} elseif ($entityText == 'company') {
$profileLinkedModel = new ProfileCompany();
} else {
//#TODO
return FALSE;
}
$model->entity_type_id = $entity_id;
$model->profile_type_id = $profileTypeId;
$profileLinkedModel->profile_id = $model->profile_id;
Yii::$app->response->format = Response::FORMAT_JSON;
$renderMethod = 'renderAjax';
}
//extra table field used to enable custom rule in model
$model->createFullProfile = TRUE;
if ($model->load(Yii::$app->request->post())) {
return $this->redirect(['view', 'id' => $model->profile_id]);
}
return $this->$renderMethod('create', [
'model' => $model,
'profileLinkedModel' => $profileLinkedModel,
]);
}
When I select a field for entity type field, the server runs the ajax request on select event, but when it ends the other form field is not more selectable. So, in other words, after the ajax request I'm unable to select the profile type field. If I try to select the profile type field before the entity type field I can go to next step, but load always the default model.
I use Select2 widget in multiply mode in YII2 framework. "kartik-v/yii2-widget-select2": "#dev" - this one I have downloaded via composer.
kartik-v/yii2-widget-select2 dev-master dd09e46
I added initial values with ajax on widget init ('initSelection'). And added another ajax method to suggest new values on user's typing. When user select one from list, it replaced initial values what were added on init. New values replace initial values, but don't another new.
I want new values to add to initial instead of replace it.
<?= $form->field($model, 'security[]')->widget(Select2::class, [
'attribute' => 'security',
'hideSearch' => true,
'data'=>$security_data,
'options' => [
'placeholder' => 'Security',
'multiple' => true,
],
'pluginOptions' => [
'allowClear' => true,
'minimumInputLength' => 1,
'ajax' => [
'url' => Url::toRoute([ '/admin/security/select-items' ]),
'dataType' => 'json',
'data' => new JsExpression('function(params) { return {q:params.term}; }'),
'results' => new JsExpression('function(data,page) { return {results:data.results}; }'),
],
'initSelection' => new JsExpression('function(element, callback) { var id = '.Yii::$app->request->getQueryParams()['id'].';if(id !== "") {$.ajax("' . \yii\helpers\Url::toRoute([ '/admin/security/init-items' ]) . '", {data: {id: id},dataType: "json"}).done(function(data) {callback(data.results);});}}'),
],
]); ?>
And here is my api methods:
public function actionSelectItems($q = null){
Yii::$app->response->format = Response::FORMAT_JSON;
$out = ['results' => []];
if(!empty($q)){
$items = Security::find()->where(['like', 'title', $q])->all();
foreach ($items as $item){
$out['results'][] = ['id'=>$item->id, 'text'=>$item->title];
}
}
return $out;
}
public function actionInitItems($id = null){
Yii::$app->response->format = Response::FORMAT_JSON;
$adv = Adv::findOne($id);
$security = #json_decode($adv->security, true);
$out = ['results' => []];
foreach ($security as $item){
$text = Security::findOne($item)->title;
$out['results'][] = ['id'=>$item, 'text'=>$text];
}
return $out;
}
Is there some sort of settings or I missed something when handle http result?
I am using wbraganca dynamic form widget. It works fine for the Create action.
Let me thanks for those guys making great tutorial video on youtube!!!
I am working on the Update action now. I work it on a purchase order function.
the controller of update action :
public function actionUpdate($id)
{
$model = $this->findModel($id);
$modelsItem = $model->purchaseitems;
if ($model->load(Yii::$app->request->post()) ) {
$oldIDs = ArrayHelper::map($modelsItem, 'purchaseitem_id', 'purchaseitem_id');
$modelsItem = Model::createMultiple(Purchaseitem::classname(), $modelsItem);
Model::loadMultiple($modelsItem, Yii::$app->request->post());
$deletedIDs = array_diff($oldIDs, array_filter(ArrayHelper::map($modelsItem, 'purchaseitem_id', 'purchaseitem_id')));
$valid = $model->validate();
$valid = Model::validateMultiple($modelsItem) && $valid;
if ($valid) {
$transaction = \Yii::$app->db->beginTransaction();
try {
if ($flag = $model->save(false)) {
if (! empty($deletedIDs)) {
Purchaseitem::deleteAll(['purchaseitem_id' => $deletedIDs]);
}
foreach ($modelsItem as $modelItem) {
$modelItem->purchaseitem_purchaseorder_id = $model->purchaseorder_id;
$modelItem->purchaseitem_description = Inventory::findOne($modelItem->purchaseitem_inventory_id)->inventory_partno;
if (! ($flag = $modelItem->save(false))) {
$transaction->rollBack();
break;
}
}
}
if ($flag) {
$transaction->commit();
return $this->redirect(['view', 'id' => $model->purchaseorder_id]);
}
} catch (Exception $e) {
$transaction->rollBack();
}
}
//return $this->redirect(['view', 'id' => $model->purchaseorder_id]);
} else {
return $this->render('update', [
'model' => $model,
'modelsItem' => (empty($modelsItem)) ? [new Purchaseitem] : $modelsItem
]);
}
}
But I think the problem may happen on the view file, as the Select2 field can show the value, which is the 'id' of the product rather than the product code.
view:
<div class="panel panel-default">
<div class="panel-body">
<?php DynamicFormWidget::begin([
'widgetContainer' => 'dynamicform_wrapper',
'widgetBody' => '.container-items',
'widgetItem' => '.item',
'limit' => 50,
'min' => 1,
'insertButton' => '.add-item',
'deleteButton' => '.remove-item',
'model' => $modelsItem[0],
'formId' => 'dynamic-form',
'formFields' => [
'purchaseitem_inventory_id',
'purchaseitem_qty',
'purchaseitem_cost_usd',
'purchaseitem_deliverydate',
],
]); ?>
<?php foreach ($modelsItem as $i => $modelItem): ?>
<div class="item">
<?php
// necessary for update action.
if (! $modelItem->isNewRecord) {
echo Html::activeHiddenInput($modelItem, "[{$i}]purchaseitem_id");
}
?>
<div class="row">
<?= $form->field($modelItem, "[{$i}]purchaseitem_inventory_id")->widget(
Select2::classname(), [
'pluginOptions' => [
'allowClear' => true,
'minimumInputLength' => 2,
'language' => [
'errorLoading' => new JsExpression("function () { return 'Error on finding results...'; }"),
],
'ajax' => [
'url' => Url::toRoute('inventory/inventorylist'),
'dataType' => 'json',
'data' => new JsExpression('function(params) { return {q:params.term}; }')
],
'escapeMarkup' => new JsExpression('function (markup) { return markup; }'),
'templateResult' => new JsExpression('function(purchaseitem_inventory_id) { return purchaseitem_inventory_id.text; }'),
'templateSelection' => new JsExpression('function (purchaseitem_inventory_id) { return purchaseitem_inventory_id.text; }'),
],
])->label(false) ?>
<?= $form->field($modelItem, "[{$i}]purchaseitem_qty")->textInput(['maxlength' => true])->label(false) ?>
<?= $form->field($modelItem, "[{$i}]purchaseitem_cost_usd")->textInput(['maxlength' => true])->label(false) ?>
<?= $form->field($modelItem, "[{$i}]purchaseitem_deliverydate")->widget(
DatePicker::className(), [
'options' => [
['placeholder' => 'Please enter delivery date'],
],
'removeButton' => false,
'pluginOptions' => [
'autoclose'=>true,
'format' => 'yyyy-mm-dd',
'todayHighlight' => true,
]
]
)->label(false) ?>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
I have a thought that the problem maybe related to that few lines of JsExpression function.
'escapeMarkup' => new JsExpression('function (markup) { return markup; }'),
'templateResult' => new JsExpression('function(purchaseitem_inventory_id) { return purchaseitem_inventory_id.text; }'),
'templateSelection' => new JsExpression('function (purchaseitem_inventory_id) { return purchaseitem_inventory_id.text; }'),
For the Select2 query URL method is here:
public function actionInventorylist($q = null, $id = null) {
Yii::$app->response->format = yii\web\Response::FORMAT_JSON;
$out = ['results' => ['id' => '', 'text' => '']];
if (!is_null($q)) {
$query = new Query;
$query->select('inventory_id AS id, inventory_partno AS text')
->from('inventory')
->where(['like', 'inventory_partno', $q])
->limit(10);
$command = $query->createCommand();
$data = $command->queryAll();
$out['results'] = array_values($data);
}
elseif ($id > 0) {
$out['results'] = ['id' => $id, 'text' => Inventory::find($id)->inventory_partno];
}
return $out;
}
I can load the record, when I click in the update view. Most of the data are feed in right place of the form, except the 'partno' field. I use Select2 to let user select partno by text and store the 'id' in table. It works on the Create view.
but in the update view, it only show the 'id' instead of the 'partno'.
if I make input to the field, I can select 'other' partno only, let me explain here:
if there are 2 code, "ABC" with 'id' is 1, "XYZ" with 'id' 2.
the record original is "ABC", the field show "1".
If I input "XYZ", it will show "XYZ" as normal effect of widget. But, if I change back to "ABC", it will show "1" instead of "ABC".
And the form also cannot submit for update. the button click with no effect.
I am new to Yii2 framework, and quite stuck on this issue, does anyone knows how can I solve this?
THANKS!!!!
I just solve the problem, a few issue happened actually.
To solve the Select2 widget cannot display the partno instead of the ID, I find the partno by the ID and feed it with initValueText in Select2. For my case:
$partno = empty($modelItem->purchaseitem_inventory_id) ? '':Inventory::findOne($modelItem->purchaseitem_inventory_id)->inventory_partno;
$form->field($modelItem, "[{$i}]purchaseitem_inventory_id")->widget(Select2::classname(), ['initValueText' => $partno, ...
About the update POST fail issue, I got error of Getting unknown property: backend\models\Purchaseitem::id, and I found it happened on the Dynamic-form widgets Model.php line 25. That lines is $keys = array_keys(ArrayHelper::map($multipleModels, 'id', 'id'));
If I change the 'id' to my ID field name, i.e 'purchaseitem_id', it will work, but this model will only work for this Id field name afterward. So I get the model's primaryKey and make it work for my other model.
add this line $primaryKey = $model->tableSchema->primaryKey; and modify above line $keys = array_keys(ArrayHelper::map($multipleModels, $primaryKey, $primaryKey));