Making JSON Objects from Zend Controllers Using JQuery in ZF2 - php

I am new in Zend Framework. I am trying to display data from database using JSON. And I encoded the data and passed it to JQuery. But cannot retrieve value from database. Data displayed as "undefined". My controller function is as follows:
public function displayAction()
{
$data1 = array();
$request = $this->getRequest();
$response = $this->getResponse();
if ($request->isPost()) {
$response->setContent(\Zend\Json\Json::encode(array('data' => $this-> getStickyNotesTable() -> fetchAll())));
}
return $response;
}
My FetchAll() is:
public function fetchAll() {
$resultSet = $this->select(function (Select $select) {
$select->order('created ASC');
});
$entities = array();
foreach ($resultSet as $row) {
$entity = new Entity\StickyNote();
$entity->setId($row->id)
->setNote($row->note)
->setCreated($row->created);
$entities[] = $entity;
}
return $entities;
}
JQuery function :
function getUserList(element) {
$('#indicator').show();
$.post('stickynotes/display',
function(data, textStatus) {
renderUserList(data);
$('#indicator').hide();
},
"json"
);
}
function renderUserList(jsonData) {
var table = '<table width="600" cellpadding="5" class="table table-hover table-bordered"><thead><tr><th scope="col">Note</th></tr></thead><tbody>';
$.each(jsonData, function(index, data){
table += '<tr>';
table += '<td class="edit" field="note" user_id="'+data.id+'">'+data.note+'</td>';
table += '<td><i class="icon-remove icon-white"></i></td>';
table += '</tr>';
});
table += '</tbody></table>';
$('div#content').html(table);
}
I tested it using Firebug. It shows
{"data":[{},{},{},{},{},{},{},{},{},{},{},{},{}]}
as Response.
Anyone please help me. Thanks.

The issue is with your fetchAll method. Try with this updated version:
public function fetchAll() {
$resultSet = $this->select(function (Select $select) {
$select->order('created ASC');
});
$entities = array();
foreach ($resultSet as $row) {
$entity = array(
"id" => $row->id,
"note" => $row->note,
"created" => $row->created
);
$entities[] = $entity;
}
return $entities;
}

You'll need to configure your module.config.php and add a strategy within your template_map add.
'strategies' => array(
'ViewJsonStrategy',
),
to return a jsonModel.
If you want to work with a jsonModel within your controller you'll need to call it like so:
$json = new JsonModel(array(
'param' => 'foobar',
'success' => true,
));
return $json;

Related

How to save scraped data through command in database

I have this in the command but not saving the database.
$client = new Client(HttpClient::create(['timeout' => 60]));
$crawler = $client->request('GET', 'https://www.bbc.com/news/');
$model = new Scraper();
$crawler->filter('.gs-c-promo-heading')->each(function ($node) {
$model->title = $node->text();
});
$crawler->filter('.gs-c-promo-summary')->each(function ($node) {
$model->text = $node->text();
});
$crawler->filter('.gs-c-timestamp')->each(function ($node) {
$model->time = $node->text();
});
$crawler->filter('.gs-c-section-link')->each(function ($node) {
$model->country = $node->text();
});
$model->save();
$this->info('done success');
Giving this type of error
$ php artisan scraper:start
ErrorException
Creating default object from empty value
at E:\wamp64\www\Laravel7Projects\system\system\app\Console\Commands\ScrapCommand.php:49
45| $crawler = $client->request('GET', 'https://www.bbc.com/news/');
46|
47| $crawler->filter('.gs-c-promo-heading')->each(function ($node) {
48|
> 49| $model->title = $node->text();
51| });
52| $crawler->filter('.gs-c-promo-summary')->each(function ($node) {
53|
1 E:\wamp64\www\Laravel7Projects\system\system\app\Console\Commands\ScrapCommand.php:49
Illuminate\Foundation\Bootstrap\HandleExceptions::handleError("Creating default object from empty value", "E:\wamp64\www\Laravel
7Projects\system\system\app\Console\Commands\ScrapCommand.php", [Object(Symfony\Component\DomCrawler\Crawler), Object(stdClass)])
2 E:\wamp64\www\Laravel7Projects\system\system\vendor\symfony\dom-crawler\Crawler.php:352
App\Console\Commands\ScrapCommand::App\Console\Commands\{closure}(Object(Symfony\Component\DomCrawler\Crawler))
but with this mthod is working which is no need because I want to save all attributes in one new class
$crawler->filter('.gs-c-promo-heading')->each(function ($node) {
$model = new Scraper();
$model->title = $node->text();
$model->save();
});
I want to save every attribute in the database but getting error
With this logic only saving first row where as i want to save all loop in the database
$client = new Client(HttpClient::create(['timeout' => 60]));
$crawler = $client->request('GET', 'https://www.bbc.com/news/');
$model = new Scraper();
$crawler->filter('.gs-c-promo-heading')->each(function ($node) use ($model) {
$model->title = $node->text();
});
$model->save();
Edit: Only titles are saving in the database whereas others not saving with this method because we are looping only titles in foreach
And map is not working whereas each in working you can check below code
$titles = $crawler->filter('.gs-c-promo-heading')->each(function($node) {
return $node->text();
});
$texts = $crawler->filter('.gs-c-promo-summary')->each(function($node) {
return $node->text();
});
$times = $crawler->filter('.gs-c-timestamp')->each(function($node) {
return $node->text();
});
$countries = $crawler->filter('.gs-c-section-link')->each(function($node) {
return $node->text();
});
$dataArray = [];
foreach ($titles as $key => $item) {
$newModelData = [
'title' => $titles[$key],
'text' => $texts[$key],
'time' => $times[$key],
'country' => $countries[$key]
];
$dataArray[] = $newModelData;
}
Scraper::insert($dataArray);
When you are using each() you don't have access to $model variable (outside of the scope).
You should try use() to introduce $model variable inside of local scope of an anonymous function
$crawler->filter('.gs-c-promo-heading')->each(function ($node) use($model) {
$model->title = $node->text();
});
Edit: If you want to save multiple items at the same time you could pluck necessary values and then create arrays of data according to your model attributes.
$titles = $crawler->filter('.gs-c-promo-heading')->map(function($node) {
return $node->text();
});
$texts = $crawler->filter('.gs-c-promo-heading')->map(function($node) {
return $node->text();
});
// same for times, countries
$dataArray = [];
foreach ($titles as $key => $item) {
$newModelData = [
'title' => $titles[$key],
'text' => $texts[$key],
'time' => $times[$key],
'country' => $countries[$key]
];
$dataArray[] = $newModelData;
}
Model::createMany($dataArray);

Addition of a new value to API response

Currently learning Laravel and any help is much appreciated!
My API controller has the following index function
public function index()
{
abort_if(Gate::denies('course_access'), Response::HTTP_FORBIDDEN, '403 Forbidden');
$response=Course::all()->toArray();
$allData = [];
foreach (Course::all() as $ids=>$CMF) {
UNSET($response[$ids]['media']);
$data_sequence = DB::table('media_sequence')->where('data_id', $CMF["id"])->where('type','CMF')->first();
$data_id=$data_sequence->id;
$data_sequence = json_decode($data_sequence->data_sequence);
$data = [];
$data["id"] = $CMF["id"];
$data["title"] = $CMF["title"];
foreach ($data_sequence as $id => $dataSeq) {
if ($dataSeq->type == "Text") {
$response[$ids]['media'][]=["id"=>$data_id,"text"=> $dataSeq->name,"mime_type"=>"text"];
} elseif ($dataSeq->type == "file") {
foreach ($CMF["media"] as $file) {
if (str::slug($dataSeq->name) == str::slug($file["file_name"])) {
$file["thumb"] = $file->getUrl('video_thumb');
$response[$ids]['media'][]=$file;
}
}
}
}
$allData[] = $data;
}
return new CourseResource($response);
//Commented: return new CourseResource(Course::with(['category', 'assigned_teams', 'team'])->get());
}
Getting no result when trying to return 'assigned_teams' with $response
The API response still doesn't include 'assigned_teams'
I tried: return new CourseResource($response, 'assigned_teams');
It is not returning the assigned_items since it is not included in the $response array.
Change
$response=Course::all()->toArray();
To
$response=Course::with(['category', 'assigned_teams', 'team'])->get();
Read more: eager-loading-multiple-relationships
Btw, as #apokryfos mentioned, you should refactor your code using Eloquent Relationships and Eager Loading.
I assume that the assigned_teams are not handled in your CourseResource.
You need to extend your resource to respect this additional relation.
class CourseResource extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
// return teams if they have been loaded
'teams' => TeamsResource::collection($this->whenLoaded('assigned_teams')),
];
}
}
This is just exemplary, since you did not provided your code for CourceResource yet, you need to update it according to your needs.
Here is the link to the appropriate laravel documentation: https://laravel.com/docs/8.x/eloquent-resources#conditional-relationships

validate and saving an array of objects laravel 6, vue, axios

vue function:
sendData() {
this.isLoading = true;
const postData = {
data: this.items,
};
var self = this;
axios.post(this.postUrl, postData).then(function (response) {
console.log(response.data);
self.isLoading = false;
});
this.items = [];
},
Laravel controller:
public function store(request $request)
{
foreach ($request->data as $data) {
$serie = [];
$serie = ['imei' => $data['serie']];
$imei = new Imei([
'imei' => $data['serie'],
'status_id' => 1,
'sucursal_id' => $data['sucursal'],
'equipo_id' => $data['equipo']
]);
$validator = Validator::make($serie, [
'imei' => 'unique:imeis,imei|digits:15',
]);
if ($validator->fails()) {
// Here I need to build the response of every imei with its validation error
} else {
$imei->save();
}
}
return >Here I want to return the errors back to vue
}
my vue app sends to laravel trough axios an array of objects that looks like this [{imei:xxxx,sucursal_id...},{imei:xxxx,sucursal_id...}] I need to validate imei is unique and save it, and if error return errors in the same way [{imei:xxxx,errorMsg: 'already exist in DB'}]. but I can't find the proper way to do it.
Basically you want to customize your errorbag right ? try this one out. Add this inside your fail condition. Let me know if it works.
$err = [{imei:xxxx,errorMsg: 'already exist in DB'}];
foreach ($validator->errors()->toArray() as $error) {
foreach($error as $sub_error) {
array_push($err, $sub_error);
}
}
return ['errors'=>$err];

database value how to pass dropdown list in codeigniter

How to pass value to drop down list in CodeIgniter?
This is my view file HTML code:
<div class="form-group">
<select name="department" id ="department">
<?php
foreach($dept as $country)
{
echo '<option value="'.$country['dept_id'].'">'.$country['managers_name'].'</option>';
}
?>
</select>
</div>
This is my controller code:
public function department()
{
$this->load->model('insert_model');
$data['dept'] = $this->insert_model->category_name_get();
}
This is my model file code:
function category_name_get()
{
$query = $this->db->get('dept');
if ($query->num_rows >= 1)
{
foreach($query->result_array() as $row)
{
$data[$row['dept_id']]=$row['managers_name'];
}
return $data;
}
}
I think you are searching for Adding Dynamic Data to the View
Data is passed from the controller to the view by way of an array or an object in the second parameter of the view loading method. Here is an example using an array:
$data = array(
'title' => 'My Title',
'heading' => 'My Heading',
'message' => 'My Message'
);
$this->load->view('blogview', $data);
In your case $data contains the department list in it as an array.
In Your COntroller file you will get all date on $data['dept'] that returned from model.
public function department()
{
$this->load->model('insert_model');
$data['dept'] = $this->insert_model->category_name_get();
$this->load->view('view_file_name',$data);
}
In your view file you will get this data
Just do print_r($dept); and check array..
you will find more info from this link
Probably your model is not returning "proper" data for your view. Perhaps something like this:
function category_name_get()
{
$data = array();
$query = $this->db->get('dept');
if ($query->num_rows >= 1)
{
foreach($query->result_array() as $row)
{
$data[] = array(
'dept_id' => $row['dept_id'],
'managers_name' => $row['managers_name']
);
}
}
return $data;
}
function category_name_get()
{
$query = $this->db->get('dept');
if ($query->num_rows() >= 1)
{
foreach($query->result_array() as $row)
{
$data[$row['dept_id']]=$row['managers_name'];
}
return $data;
}
}
Use num_rows() instead of num_rows. I hope it works now.

CAutoComplete HowTo set call back function ? YII

Hi I am using a SAutoComplete (extends CAutoComplete) and need to do some work when a value is selected from the list.
i am using it like this.
this->widget('application.components.SAutoComplete', array('width'=>200,
'model'=>$cssAtapsClient, 'parseData'=>true, 'matchContains'=>true,
'attribute'=>'suburb_id', 'data'=>$postCode, 'ddindicator'=>true,
'max'=>50,
'multipleSeparator'=>false,
'options' => array(
'select' => new CJavaScriptExpression('function(e, ui) { alert("hi"); }')
),
)); ?>
i am wondering why there is no select option like available in jquery UI auto completed?
example of a select is as below.
$("#auto_cp").autocomplete({
minLength: 3,
//source
source: function(req, add) {
$.getJSON("friends.php?callback=?", req, function(data) {
var suggestions = [];
$.each(data, function(i, val) {
suggestions.push({
label: val.name,
zzz: val.zzz
});
});
add(suggestions);
});
},
//select
select: function(e, ui) {
alert(ui.item.zzz);
}
});​
EDIT 2
http://www.yiiframework.com/doc/api/1.1/CAutoComplete
code is like this,
<?php
class SAutoComplete extends CAutoComplete
{
public $ddindicator;
/**
*
* #var boolean whether to parse the data assumes data uses an assoc array
* array(value => array(name, value, ...), ...). Only works with a model present
*/
public $parseData;
/**
* #var boolean whether to raise the change event
*/
public $raiseChangeEvent = false;
/**
* Initializes the widget.
* This method registers all needed client scripts and renders
* the autocomplete input.
*/
public function init()
{
if ( !$this->max )
$this->max = 50000;
if ( $this->ddindicator )
$this->alternateInit();
else
parent::init();
}
public function alternateInit()
{
list($name,$id)=$this->resolveNameID();
$this->htmlOptions['id'] = $id.'_input';
$this->minChars = 0;
echo CHtml::openTag('div', array('class'=>'ac-input-dd'));
echo CHtml::openTag('div', array('class'=>'ac-input-btn'));
echo CHtml::closeTag('div');
if($this->hasModel())
{
$htmlOpt = array();
if ( $this->parseData )
{
$menu = $this->data;
$key = $this->attribute;
//Change if attribute is apart of a array. eg attribute[0]
$pos1 = stripos($key, '[');
$pos2 = stripos($key, ']');
if($pos1!==false && $pos2!==false)
{
$key = str_replace (substr($key,$pos1,$pos2 - $pos1 + 1),'',$key);
$htmlOpt['value'] = isset($this->model->$key) ? $this->model->$key : '';
}
$this->value = isset($menu[$this->model->$key][0]) ? $menu[$this->model->$key][0] : '';
$this->data = is_array($menu) ? array_values($menu) : array('Error in data.');
}
echo CHtml::activeHiddenField($this->model, $this->attribute, array_merge(array('id'=>$id, 'name'=>$name), $htmlOpt));
echo CHtml::textField('', $this->value, $this->htmlOptions);
}
else
{
echo CHtml::hiddenField($name, $this->value, array('id'=>$id));
echo CHtml::textField($name.'_input',$this->value,$this->htmlOptions);
}
echo CHtml::closeTag('div');
$this->methodChain = $this->methodChain.'.result(function(evt, data, formatted) { $("#'.
$id.'").val(data ? data[1] : "")'.($this->raiseChangeEvent?'.change()':'').'; })'.
'.parent().find(".ac-input-btn").mousedown(function(){'.
'jQuery(this).parent().find(".ac_input").toggleResults();})'.
'.mouseup(function(){jQuery(this).parent().find(".ac_input").focus();});';
$this->registerClientScript();
}
public static function registerScript()
{
$cs = Yii::app()->getClientScript();
$cs->registerCoreScript('jquery');
$cs->registerCoreScript('bgiframe');
TK::registerScriptFile('autocomplete');
$cs->registerCssFile($cs->getCoreScriptUrl().'/autocomplete/jquery.autocomplete.css');
}
/**
* Registers the needed CSS and JavaScript.
* #since 1.0.1
*/
public function registerClientScript()
{
// can cut this down once YII releases a fix for defect #38
if ( Yii::app()->request->isAjaxRequest || $this->ddindicator )
{
$id=$this->htmlOptions['id'];
$acOptions=$this->getClientOptions();
$options=$acOptions===array()?'{}' : CJavaScript::encode($acOptions);
$cs=Yii::app()->getClientScript();
if($this->data!==null)
$data=CJavaScript::encode($this->data);
else
{
$url=CHtml::normalizeUrl($this->url);
$data='"'.$url.'"';
}
if ( Yii::app()->request->isAjaxRequest )
{
echo '<script type="text/javascript">jQuery(document).ready('.
'function() {jQuery("#'.$id.'").autocomplete('.$data.','.$options.')'.
$this->methodChain.';});</script>';
}
else
{
SAutoComplete::registerScript();
$cs->registerScript('Yii.CAutoComplete#'.$id,"jQuery(\"#{$id}\").autocomplete($data,{$options}){$this->methodChain};");
}
}
else
parent::registerClientScript();
}
}
You can pass any option that the JUI autocomplete widget supports by including an options array:
$this->widget('zii.widgets.jui.CJuiAutoComplete', array(
// your other settings here
'options' => array(
'select' => new CJavaScriptExpression('function(e, ui) { alert("hi"); }')
),
));
If the options you want to pass include JavaScript code then you also have to wrap that inside a CJavaScriptExpression as above.
Try to add this,
'methodChain'=>".result(function(event,item){ urFunction(); })",
Have a nice day!
So at last it will look like,
$this->widget('application.components.SAutoComplete', array('width'=>200,
'model'=>$cssAtapsClient, 'parseData'=>true, 'matchContains'=>true,
'attribute'=>'suburb_id', 'data'=>$postCode, 'ddindicator'=>true,
'max'=>50,
'methodChain'=>".result(function(event,item){ urFucntion(); })",
));
I'm using CAutoComplete as the followin code:
In post/_form.php
<?php $this->widget('CAutoComplete', array(
'model' => $model,
'attribute' => 'tags',
'url' => array('suggestTags'),
'multiple' => true,
'htmlOptions' => array(
'size' => 50,
'class' => 'span11'
),
)); ?>
In PostController.php
Add one more action call: suggestTags
/**
* Suggests tags based on the current user input.
* This is called via AJAX when the user is entering the tags input.
*/
public function actionSuggestTags()
{
if(isset($_GET['q']) && ($keyword=trim($_GET['q']))!=='')
{
$tags=Tag::model()->suggestTags($keyword);
if($tags!==array())
echo implode("\n",$tags);
}
}
In Post.php model
add private $_oldTags; to the top of class (under class name).
add these functions:
/**
* Normalizes the user-entered tags.
*/
public function normalizeTags($attribute, $params)
{
$this->tags = Post::array2string(array_unique(Post::string2array($this->tags)));
}
public static function string2array($tags)
{
return preg_split('/\s*,\s*/', trim($tags), -1, PREG_SPLIT_NO_EMPTY);
}
public static function array2string($tags)
{
return implode(', ', $tags);
}
See more Yii tutorials here

Categories