Laravel 4 foreach loop - wanting to display the last element - loops

I am currently trying to set up an edit page where an order form is populated using json_decode to decode json information that was saved when the form was created. Because the form's size can change I have to create the correct number of inputs so that all the json data will have a place to be displayed. Fortunately as the inputs are numbered this should not be hard to do. Unfortunately I am not sure how to pick the last element of the json information that has been decoded. Currently I am using:
public function getEdit($id){
$order = Order::where('id', '=', $id);
if($order->count()) {
$order = $order->first();
$order->order_serialized = json_decode($order->order_serialized);
foreach($order->order_serialized as $key => $value){
$order->$key = $value;
}
return View::make('orders.edit')
->with('order', $order);
} else {
return App::abort(404);
}
}
to decode the information and it is working splendidly but I need to be able to pick up the last element to be able to find the total number of inputs and am not sure how I could do this without disturbing the foreach loop. Any and all help would be greatly appreciated!! Thank you so much!

You can use the count and toArray methods to find the last item.
$nItem = $order->count();
$aOrder = $order->toArray();
$aLastItem = $aOrder[$nItem-1];

Collections have a last() function to compliment the first() function.

Related

Laravel : How save array in database?

I need your help because I can't save array from form in the pivot table. If someone can show me how because this is going to drive me crazy.
So I have a exam form with input number in foreach and which has a dynamic name.
And I have two total results to.
This is my data form :
I want save my input number question in pivot table and the results on another table.
For the result it's ok but it's for save in pivot table I have a problem.
Thanks to help me.
In my controller I make this :
$data = $request->all();
foreach($data as $question_id => $answer_id){
$result = new PratiqueReponse();
$result->question_id = $question_id;
$result->answer_id = $answer_id;
$result->save();
}
But not working.
You did not share much information, so i can only guess but i think you should save to db like this:
$data = $request->all();
foreach($data['questions'] as $question_id => $answer_id){
$result = new PratiqueReponse();
$result->question_id = $question_id;
$result->answer_id = $answer_id;
$result->save();
}
you need to loop trough questions, not the whole array.

push an array while foreach other array laravel

I'm using laravel package commentable by faustbrian. i've been getting the comment for a post using just like in documentation in github . I want to search the information for user who post the comment, e.g the user avatar, address, and other information as well. I want to include the user information (which is an array) to the current position index of array (while for each i push it). the problem is, i tried using array_push, array_merge and $data[$key]=>$value as well. but none of them is working when i dd the variable. please help.
public function notaPengurusan($id){
$comments=Complaint::findOrFail($id)->comments->toArray();
foreach ($comments as $comment){
$creator=User::findOrFail($comment['creator_id'])->toArray();
array_push($comment,$creator);
}
dd($comments);
return view('complaint::notapengurusan',compact('comments'));
}
image when i dd the image
You need to use array index and its global variable $comments
foreach ($comments as $key=>$comment){
$creator=User::findOrFail($comment['creator_id'])->toArray();
array_push($comments[$key],$creator);
}
you should add user() relationship in your Comment Model :
public function user(){
return $this->belongsTo('App\Model\User','creator_id');
}
then no need to use for loop and finding user each time , use with('user'):
$comments=Comment::where(['post_id'=>$post_id])->with('user')->orderBy('created_at','desc')->paginate(12);

Saving Array CakePhp

I wanna save values from an array into one field of my database. I've been using that code but nothing got saved.
$this->Form->input('Model.0.field1');
$this->Form->input('Model.0.field2');
$this->Form->input('Model.1.field1');
$this->Form->input('Model.1.field2');
Thanks.
I think you need to save data with json_encode() value.
// In your controller
public function test() {
if($this->request->is('post')) {
//If you want to insert in single row then you can use json_encode() and add to your colum.
$insert_data = json_encode($this->request->data);
$data = array();
// Load your model where you want save data
$this->loadModel('Test');
// set attribute name where you want to save
$data['Test']['value'] = $insert_data;
$this->Test->save($data);
//For viewing your data
$fetchedData = $this->Test->find('all');
foreach($fetchedData as $items) {
var_dump(json_decode($items['Test']['value']));
}
}
}
You can use implode() to generate comma separated data. If you want to use implode(), look at Inserting an array into a mysql database column

Create an instance of a Model in its Controller

This is probably a simple question but I'm having a hard time trying to create an object of the Model. I want to create a temporary variable that is the same as the model so I can update its internal values according to the data I am posting to the action.
My data is successfully posted to the action in the controller.
Currently what I am doing is grabbing all the items in the database and then assigning it the first item from the array. This way I can overwrite existing value, but if the table is empty it won't work.
I am using cakephp 2.x, I am new to this stuff which will explain why I couldn't figure this out.
Here is the code from the controller:
public function lcadd()
{
if ($this->request->is('post'))
{
// Create a new Local Clock object
$temp = $this->LocalClock->find('all'); // THIS IS THE PROBLEM AREA
$temp = $temp[0];
$temp['LocalClock']['name'] = $this->request->data['LocalClock']['Name'];
debug($temp); // THIS DEBUG ONLY DISPLAYS SOMETHING IF THE DATABASE TABLE IS NOT EMPTY
debug($this->request->data); // THE DATA COMING IN IS CORRECT AND I CAN ACCESS IT WITHOUT A PROBLEM
if($this->request->data['LocalClock']['Time Zone'] == 0 or $this->request->data['LocalClock']['Time Zone'] == -1)
{
//debug('Hello');
$temp['LocalClock']['auto_offset'] = 1;
}
else if($this->request->data['LocalClock']['Time Zone'] == 1)
{
$temp['LocalClock']['auto_offset'] = 0;
}
// Check the value posted from the DST
if($this->request->data['LocalClock']['DST Definition'] == -1 or $this->request->data['LocalClock']['DST Definition'] == 0)
{
$temp['LocalClock']['in_month'] = 0;
}
else if($this->request->data['LocalClock']['DST Definition'] == 2)
{
$temp['LocalClock']['in_month'] = $this->request->data['LocalClock']['InMonth'];
}
if ($this->LocalClock->save($temp))
{
$this->set('localClocks', $this->request->data);
$this->set('islcAddValid', true);
$this->set('lcaddValidationErrors', false);
}
}
}
I can't figure out how to make a simple object from the model. The model is LocalClock, and the controller is LocalClocksController.
The function above is in the LocalClocksController.
Thanks in advance.
A few things I noticed...
FIRST ISSUE:
// Create a new Local Clock object
$temp = $this->LocalClock->find('all'); // THIS IS THE PROBLEM AREA
$temp = $temp[0];
That's not creating a new Local Clock object. The first line returns an array (ie, not an object) containing ALL records in your Local Clock database table. Then, the second line says 'take the first row of the results, and store it in $temp'. So, now $temp holds an array (still NOT an object), containing the data of the first record in the LocalClock table.
You actually don't need an object, though, since the 'save' method that you call later on doesn't accept an object - it just accepts an array of data. You also don't need to get anything from the database in order to save a new record. So the code above should be replaced with:
$temp = array(); // Create an empty array. We will populate it as we go, with the data for the new record.
All the stuff in the middle of your method, up until you try to save the record, should work fine as it is.
SECOND ISSUE:
if ($this->LocalClock->save($temp))
Before calling 'save', you'll first need to call 'create' -
$this->LocalClock->create(); // prepare the Model to save a new record
if ($this->LocalClock->save($temp)) // This should now save a new record successfully.
Make sense? Let me know if you have any more questions.
Also, understanding how to retrieve, manipulate and save data from Models is very crucial to using CakePHP, and if you learn how to do it properly from the beginning, you'll save yourself countless hours of frustration in future. I'd recommend reading the following pages end-to-end:
http://book.cakephp.org/2.0/en/models/retrieving-your-data.html
http://book.cakephp.org/2.0/en/models/saving-your-data.html

Need to make full names in cakePHP

If I have a person model with first_name and last_name, how do I create and display a full_name? I would like to display it at the top of my Edit and View views (i.e. "Edit Frank Luke") and other places. Simply dropping echoes to first_name and last_name isn't DRY.
I'm sorry if this is a very simple question, but nothing has yet worked.
Thank you,
Frank Luke
Edit for clarity: Okay, I have a function on the person model.
function full_name() {
return $this->Person->first_name . ' ' . $this->Person->last_name;
}
In the view, I call
echo $person['Person']['full_name']
This gives me a notice that I have an undefined index. What is the proper way to call the function from the view? Do I have to do it in the controller or elsewhere?
If what you are wanting is just to display a full name, and never need to do any database actions (comparisons, lookups), I think you should just concatenate your fields in the view.
This would be more aligned with the MVC design pattern. In your example you just want to view information in your database in a different way.
Since the action of concatenating is simple you probably don't save much code by placing it in a separate function. I think its easiest to do just in the view file.
If you want to do more fancy things ( ie Change the caps, return a link to the user ) I would recommend creating an element which you call with the Users data.
The arrays set by the save() method only return fields in the datbase, they do not call model functions. To properly use the function above (located in your model), you will need to add the following:
to the controller, in the $action method:
$this->set( 'fullname', $this->Person->full_name();
// must have $this-Person->id set, or redefine the method to include $person_id
in the view,
echo $fullname;
Basically, you need to use the controller to gather the data from the model, and assign it to the controller. It's the same process as you have before, where you assign the returned data from the find() call to the variable in the view, except youre getting the data from a different source.
There are multiple ways of doing this. One way is to use the afterFind-function in a model-class.
See: http://book.cakephp.org/view/681/afterFind.
BUT, this function does not handle nested data very well, instead, it doesn't handles it al all!
Therefore I use the afterfind-function in the app_model that walks through the resultset
function afterFind($results, $primary=false){
$name = isset($this->alias) ? $this->alias : $this->name;
// see if the model wants to attach attributes
if (method_exists($this, '_attachAttributes')){
// check if array is not multidimensional by checking the key 'id'
if (isset($results['id'])) {
$results = $this->_attachAttributes($results);
} else {
// we want each row to have an array of required attributes
for ($i = 0; $i < sizeof($results); $i++) {
// check if this is a model, or if it is an array of models
if (isset($results[$i][$name]) ){
// this is the model we want, see if it's a single or array
if (isset($results[$i][$name][0]) ){
// run on every model
for ($j = 0; $j < sizeof($results[$i][$name]); $j++) {
$results[$i][$name][$j] = $this->_attachAttributes($results[$i][$name][$j]);
}
} else {
$results[$i][$name] = $this->_attachAttributes($results[$i][$name]);
}
} else {
if (isset($results[$i]['id'])) {
$results[$i] = $this->_attachAttributes($results[$i]);
}
}
}
}
}
return $results;
}
And then I add a _attachAttributes-function in the model-class, for e.g. in your Person.php
function _attachAttributes($data) {
if (isset($data['first_name']) && isset($data['last_name'])) {
$data['full_name'] = sprintf("%s %s %s", $data['first_name'], $data['last_name']);
}
return $data;
}
This method can handle nested modelData, for e.g. Person hasMany Posts then this method can also attachAttributes inside the Post-model.
This method also keeps in mind that the linked models with other names than the className are fixed, because of the use of the alias and not only the name (which is the className).
You must use afterFind callback for it.
You would probably need to take the two fields that are returned from your database and concatenate them into one string variable that can then be displayed.
http://old.nabble.com/Problems-with-CONCAT-function-td22640199.html
http://teknoid.wordpress.com/2008/09/29/dealing-with-calculated-fields-in-cakephps-find/
Read the first one to find out how to use the 'fields' key i.e. find( 'all', array( 'fields' => array( )) to pass a CONCAT to the CakePHP query builder.
The second link shows you how to merge the numeric indexes that get returned when you use custom fields back into the appropriate location in the returned results.
This should of course be placed in a model function and called from there.

Resources