I am able to view and delete the data by passing ID in the URl in format of:
/apis/view/id.json
using:
public function view($id) {
$api = $this->Api->findById($id);
$this->set(array(
'api' => $api,
'_serialize' => array('api')
));
}
Similarly I want to implement add and edit, where I can pass data in Json format in the HTTP body and store/edit it in the database.
I couldn't follow the this solution:
CakePHP API PUT with JSON input
I couldn't understand how to use
$data = $this->request->input('json_decode');
to achieve it.
Add can simply be used as given in documentation by appending .json to it. The URL at which you post the data will become /apis.json. This will automatically access the add() method.
Assuming you pass json values email and password in such format: {"email":"abc#def.com","password":"123456"}
public function add(){
$data=$this->request->input('json_decode', true ); //$data stores the json
//input. Remember, if you do not add 'true', it will not store in array format.
$data = $this->Api->findByEmailAndPassword($data['email'],$data['password']);
//simple check to see if posted values match values in model "Api".
if($data) {$this->set(array(
'data' => $data,
'_serialize' => array('data')));}
else{ $this->set(array(
'data' => "sorry",
'_serialize' => array('data')));}
}// The last if else is to check if $data is true, ie. if value matches,
// it will send the input values back in JSON response. If the email pass
// is not found, it will return "Sorry" in json format only.
Hope that answers your question! Put is also very similar, except it will check if the data exists, if it doesn't it will create or else it will modify existing data. If you have any further doubts don't hesitate to ask :)
As explained in the linked documentation, CakeRequest::input() reads the raw input data, and optionally passes it through a decoding function.
So $this->request->input('json_decode') gives you the decoded JSON input, and in case it's formatting follows the Cake conventions, you can simply pass it to one of Model save methods.
Here's a very basic (untested) example:
public function add()
{
if($this->request->is('put'))
{
$data = $this->request->input('json_decode', true);
$api = $this->Api->save($data);
$validationErrors => $this->Api->validationErrors;
$this->set(array
(
'api' => $api,
'validationErrors' => $validationErrors,
'_serialize' => array('api', 'validationErrors')
));
}
}
This will try to save the data and return the save result as well as possible validation errors.
In case the formatting of the input data doesn't follow the Cake conventions, you'll have to transform it accordingly.
Related
I have been trying to get cakephp to suggest input from data that is from my tables like autocomplete. I've done some reading about how some other people have done this but still can't figure it out. Currently it seems that every time my controller is waiting for an ajax request and it is always false. No errors come up from the console some i'm not sure what i'm doing wrong. I tried removing the if ($this->request->is('ajax')) statement but then I get a error about it cannot emit headers.
Here is my search function in InvoicesController which I have taken code from someone else example but failed to implement it.
public function search()
{
if ($this->request->is('ajax')) {
$this->autoRender = false;
pr('b');
$name = $this->request->query['term'];
$results = $this->Invoices->find('all', [
'conditions' => [ 'OR' => [
'id LIKE' => $id . '%',
]]
]);
$resultsArr = [];
foreach ($results as $result) {
$resultsArr[] =['label' => $result['full_name'], 'value' => $result['id']];
}
echo json_encode($resultsArr);
}
}
And here is my search.ctp
<?php use Cake\Routing\Router; ?>
<?php echo $this->Form->input('id', ['type' => 'text']);?>
<script>
jQuery('#id').autocomplete({
source:'<?php echo Router::url(array('controller' => 'Invoices', 'action' => 'search')); ?>',
minLength: 1
});
</script>
This is my invoice table and the ids are what I want to be suggested from what users type in.
I may not be seeing your exact problem but let me point out a few things I see that might help this issue.
Remove this line. It is not necessary
$this->autoRender = false;
Instead you should be doing this at the end. See using the RequestHandler
$this->set('resultsArr', $resultsArr);
// This line is what handles converting your array into json
// To get this to work you must load the request handler
$this->set('_serialize', 'resultsArr');
This will return the data without a root key
[
{"label":"Label Value"},
{"label":"Another Label Value"}
]
Or you can do it like this
$this->set('_serialize', ['resultsArr']);
This will return data like
{"resultArr":[
{"label":"Label Value"},
{"label":"Another Value"}
]}
Replace your finder query with this.
$resultArr = $this->Invoices->find('all')
->where(['id LIKE' => $id . '%'])
// If you want to remap your data use map
// All queries are collections
->map(function ($invoice) {
return ['label' => $invoice->full_name, 'id' => $invoice->id];
});
It seems to me you might want to review the new cakephp 3 orm. A lot of hard work went into writing these docs so that they could be easily read and relevant. I'm not one to push docs on people but it will save you hours of frustration.
Cakephp 3 ORM documentation
A few minor things I noticed that are also problems.
You never define $id.
You define $name but never use it.
pr is a debug statement and I am not sure why you have it.
Based on your comment, here is an update on ajax detection.
// By default the ajax detection is limited to the x-request-with header
// I didn't want to have to set that for every ajax request
// So I overrode that with the accepts header.
// Any request where Accept is application/json the system will assume it is an ajax request
$this->request->addDetector('ajax', function ($request) {
$acceptHeaders = explode(',', $request->env('HTTP_ACCEPT'));
return in_array('application/json', $acceptHeaders);
});
I am using Laravel 5.3 and I would like to make a query in requests file which I made to have some validation rules for a form where a user can edit his channel. In that file I would like to make a query which would look something like this:
$channelId = Auth::user()->channels()->where('id', $this->id)->get();
So that I can get the channel id and exclude it from the rules array, this is how a file looks like:
public function rules()
{
$channelId = Auth::user()->channels()->where('id', $this->id)->get();
return [
'name' => 'required|max:255|unique:channels,name,' . $channelId,
'slug' => 'required|max:255|alpha_num|unique:channels,slug,' . $channelId,
'description' => 'max:1000',
];
}
I am not sure how to get the channel id of that object that is being updated in the requests file?
When inside of a Requestobject, you can access input as #Silwerclaw correctly said by calling $this->input("id") when you have an input with name "id".
When outside of the object, you can use the facade: Request::input("id").
I used model for that matter, in the request file we can access that object by $this and by model name using this we can access all property, So change just as below.
$channel = Auth::user()->channels()->where('id', $this->channel->id))->first();
But I am not doing like this, i am directly use $this->channel->id in rule as below.
return [
'name' => 'required|max:255|unique:channels,name,' . $this->channel->id,
'slug' => 'required|max:255|alpha_num|unique:channels,slug,' . $this->channel->id,
'description' => 'max:1000',
];
I used a session for that matter, I have stored a key in edit function and then retrieved it in the request file in my query like this and now it works, and the user is not able to manipulate it in the form:
$channel = Auth::user()->channels()->where('id', session('channel_id'))->first();
I'm creating dynamic dropdown lists from values in my database. I'm querying the data, creating a php variable in this format:
$items = array(
'red'=>'apples,firetrucks,blood',
'yellow'=>'bus,pencil,duck'
);
I can then use the json_encode() function to encode.
{
"red":"apples,firetrucks,blood",
"yellow":"bus,pencil,duck",
}
I know the getJson is passed at file or a path like:
$.getJSON("jsondata/data.json", function(data) {
Can my json variable be passed to this function instead? The reason I want a variable to be passed, rather than a file is because my data can chance on a daily basis, ie:
$items = array(
'red'=>'apples,firetrucks,bricks',
'yellow'=>'bus,pencil,duck'
);
You need to create a PHP file that outputs the JSON you want;
In /foo.php:
echo json_encode(array(
"red" => "apples,firetrucks,blood",
"yellow" => "bus,pencil,duck",
));
... then your JavaScript should make an AJAX request to foo.php using getJSON;
$.getJSON("/foo.php", function (data) {
alert(data.red); // shows "apples,firetrucks,blood
alert(data.yellow); // you get the idea
});
... It was so tempting to make the values for your object arrays, but I resisted... somehow
I am completely new in the codigniter i just started day befire Yesterday i am having a problem
Here is my snippet of my controller code
$allcalldetails_array = array(
'id' => $row->id,
'customer_id' => $row->customer_id
);
$this->session->set_userdata('logged',$allcalldetails_array);
I want to iterate the $allcalldetails_array in my views please tell me the way to do this
i tried iterating logged but could not get anything .
If i am printing the array in my views like print_r($allcalldetails_array); but this is also disappointing me .Please help me to get back on track .
Thanks
Its not necessary for session variables to be parsed via controller, access it on view directly:
$logged = $this->session->userdata('logged');
print_r($logged);
If you would like data to be send to your view as variables, you should add the corresponding data to your view load.
Controller:
$logged = $this->session->userdata('logged');
$this->load->view('viewfile', $logged);
View
print "logged id:".$id;
best regards.
Jonas
To get the data from session your need to do the following:
// controller logic
$logged = $data['logged_for_view'] = $this->session->userdata('logged'); // since 'logged' is the name you set it to
// more controller logic
$this->load->view('view_name', $data);
// in view
var_dump($logged_for_view); // this is the key of the $data variable you assigned for the view
Regarding the CodeIgniter's documentation :
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 function.
Then you could use something like :
// Controller side
$data['allcalldetails_array'] = array(
'id' => $row->id,
'customer_id' => $row->customer_id
);
$this->load->view('your_view', $data);
// View side
print_r($allcalldetails_array);
// Loop through your array
foreach ($allcalldetails_array as $detail){
// Do something with your $detail.
}
I have a controller which I use for a login form. In the view, I have a {error} variable which I want to fill in by using the parser lib, when there is an error. I have a function index() in my controller, controlled by array $init which sets some base variables and the error message to '':
function index()
{
$init = array(
'base_url' => base_url(),
'title' => 'Login',
'error' => ''
);
$this->parser->parse('include/header', $init);
$this->parser->parse('login/index', $init);
$this->parser->parse('include/footer', $init);
}
At the end of my login script, I have the following:
if { // query successful }
else
{
$init['error'] = "fail";
$this->parser->parse('login/index', $init);
}
Now, of course this doesn't work. First of all, it only loads the index view, without header and footer, and it fails at setting the original $init['error'] to (in this case) "fail". I was trying to just call $this->index() with perhaps the array as argument, but I can't seem to figure out how I can pass a new $init['error'] which overrides the original one. Actually, while typing this, it seems to impossible to do what I want to do, as the original value will always override anything new.. since I declare it as nothing ('').
So, is there a way to get my error message in there, or not? And if so, how. If not, how would I go about getting my error message in the right spot? (my view: {error}. I've tried stuff with 'global' to bypass the variable scope but alas, this failed. Thanks a lot in advance.
$init musst be modified before generating your view.
To load your header and footer you can include the following command and the footer's equivalent into your view.
<?php $this->load->view('_header'); ?>
to display errors, you can as well use validation_errors()
if you are using the codeigniter form validation.
if you are using the datamapper orm for codeigniter you can write model validations, and if a query fails due to validation rule violation, you get a proper error message in the ->error property of your model.
Code for your model:
var $validation = array(
'user_name' => array(
'rules' => array('required', 'max_length' => 120),
'label' => 'Name'
)
);
You might try this:
function index() {
$init = array(
'base_url' => base_url(),
'title' => 'Login',
'error' => ''
);
$string = $this->parser->parse('include/header', $init, TRUE);
$string .= $this->parser->parse('login/index', $init, TRUE);
$string .= $this->parser->parse('include/footer', $init, TRUE);
$this->parser->parse_string(string);
}
In parse()you can pass TRUE (boolean) to the third parameter, when you want data returned instead of being sent (immediately) to the output class. By the other hand, the method parse_string works exactly like `parse(), only accepts a string as the first parameter in place of a view file, thus it works in conjunction.