I was wondering what's the best way to destroy multiples database entries with ELOQUENT and I don't find a way to determine that.
So I have 3 array of id's (2 with ints, 1 with strings).
Is it better to go with a foreach and ->delete() every entry or destroy the array ?
When I look at the destroy function, it states the following :
We will actually pull the models from the database table and call
delete on each of them individually so that their events get fired
properly with a correct set of attributes in case the developers
wants to check these.
And the code clearly shows :
$key = $instance->getKeyName();
foreach ($instance->whereIn($key, $ids)->get() as $model) {
if ($model->delete()) {
$count++;
}
}
So I guess there's no real difference and the destroy function is just to avoid the use of a foreach. Can anyone confirm or inform and explain ?
Thanks :)
At first you need to know the difference between destroy and delete, destroy is think to be used for removing an entity (object/model) and delete for being used on a query builder.
Both are different ways but they have the same purpose you can do like:
Model::destroy(array(1, 2, 3));
or
$ids = explode(",", [1,2,3]);
$model->find($ids)->each(function ($model, $key) {
//Do things before deleting
$model->delete();
});
But as you can see the first one is just more direct, on the second one you can do custom things before deleting.
Related
Using Laravel 5.3, I have a model with the following function
public function myData() {
return $this->hasMany(MyData::class);
}
and in my collection I have the following
$my_data = MyModel->myData()->get();
All good so far. If I return $my_data I get an eloquent collection with three items.
What I need now though is to create a duplicate of that collection but containing only three of the fields.
I have tried several different things, each of which return an error. The following is the closest I have got, but this returns an empty array - I assume because the fields are located one level deeper than the collection object.
$new_collection = $my_data->only(['field_1', 'field_2', 'field_3']);
What would be the correct way to create a new collection containing all three items, each with only the three selected fields?
Thanks for your help
You could use map:
$slimmed_down = $collection->map(function ($item, $key) {
return [
'field_1' => $item->field_1,
'field_2' => $item->field_2,
'field_3' => $item->field_3
];
});
This will return a new Collection with just the values you want. As far as I know there isn't any other method that does what you want, so iterating over every item and selecting the fields this way is one of the few solutions.
The advantage of using map instead of a standard foreach loop is that when you use map it returns a new instance of Collection.
Edit:
After some thoughts and research about this, the problem you'll have created is that the all the values in the Collection aren't instances of anything anymore. If you don't mind this effect, an even prettier and faster way would be to do this:
$slimmed_down = $collection->toArray()->only(['field_1', 'field_2', 'field_3']);
This basically has the same result.
Using Laravel 9, I just had the same issue :
$my_data->only(['field_1', 'field_2', 'field_3']);
returning an empty array.
I solved it with :
$my_data->map->only(['field_1', 'field_2', 'field_3']);
I am having trouble while updating session array value in laravel 5. Here is my function,
public function postCartItemAdd()
{
$id = Request::input('id');
Session::push('items', $id);
dd(Session::all());
}
Instead of pushing a new id into the array it just replaces the existing value leaving single item. Am I doing something wrong?
The problem is the session is saved as a flash data. So, you need to save the session whenever you push the data.
$request->session()->push('user.items', 'item1');
$request->session()->push('user.items', 'item2');
$request->session()->save();
or try this
$items = Session::pull('items');
$items[] = $id;
Session::push('items', $items);
umm i think you used it wrong,
see the DOC
it says
Session::push('user.teams', 'developers');
user is the array and we gonna put a value developers to that array with teams key
so then you need to use it in your case as,
Session::push('items.id', $id);
OR if you need to maintain items as an array with default keys like 0,1,2,3... to put the ids, then items should be an array
so there should be a something like,
Session::put('items', []);
then you can use Session::push('items', $id);
if you need to push ids in to same array as you tried.
The problem is I need to pull a collection from a collection. I have already set up the models and database so these relationships work:
A User can have many Negotiations
A Negotiation has one RiderNegotiation
However I can't perform this query:
$user->negotiations->riderNegotiation
I thought I could get around this in my view file if I just passed off $user->negotiation and then parse through the negotiations. I discovered I can't use isEmpty() this way however.
#if($negotiations->riderNegotiation->isEmpty()
Is there some kind of nifty trick in Laravel to do this kind of relationship querying? I feel like this is a common issue.
hasMany returns a Collection of elements and you can't call hasOne on a Collection.
You should be able to do:
$negociations = User::find(1)->negotiations;
#foreach($negociations as $negociation)
echo get_class($negociation->riderNegotiation); //riderNegotiation
#endforeach
$negotiations = User::find(Auth::user()->id)->negotiations;
$temp = array();
foreach($negotiations as $negotiation ) {
$temp = array_merge($temp,$negotiaton->riderNegotiation->toArray());
};
A little resource expensive but $temp should contain all rider negotiations for that user.
I have two models: Plans and PlanDetails.
Relationship is: PlanDetails hasMany Plans. Plans belongTo PlanDetails.
In the PlanDetails view.ctp, I am pulling in related Plans.
I am trying to sort the Plans by ANY field (I've tried them all), and I cannot get it working. I assume I am overlooking something very simple.
Here is my base code:
PlanDetail >> view.ctp:
...foreach ($planDetail['Plan'] as $plan_edit) :
$class = null;
if ($i++ % 2 == 0) {
$class = ' class="altrow"';
}...
<?php echo $this->Paginator->sort('Plan ID', 'Plan.id'); ?>...
...<?php echo $plan_edit['id']; ?>
plan_details_controller.php:
...function view($id = null) {
if (!$id) {
$this->Session->setFlash(__('Invalid plan detail', true));
$this->redirect(array('action' => 'index'));
}
$this->PlanDetail->recursive = 2; // To run the editable form deeper.
$this->set('planDetail', $this->PlanDetail->read(null, $id));
$this->set('plan', $this->paginate('Plan'));
}...
I should add, no errors are being thrown and the sort() arrows on the ID field are showing as expected, but the sort order DOES not change when clicked either way.
Sorry, I'm not able to comment on the question itself, but I've noticed that in your action, you set planDetail to be the PlanDetail record you read (with recursive set to 2), and then you set plan to be the result of the paginate call.
Then, in your view template, you're iterating over $planDetail's contained Plan association, like this:
foreach ($planDetail['Plan'] as $plan_edit):
But in order to get the sorting and pagination done, you need to be displaying the results of the paginate call i.e. iterate over the records contained in $plan.
Do a debug($plan) in your view template to see what results you get there and to see if the records' ordering changes when you sort by different fields.
Also, perhaps you're using syntax I'm not aware of, but if you simply call $this->paginate('Plan') in your controller, I don't know that you're going to get only the related Plan records for your particular PlanDetail record. (There's nothing tying the $id passed into your view action with the Plan records.) You might need to add some conditions to the paginate call, like so:
$this->paginate['Plan'] = array('conditions' => array('Plan.plan_detail_id' => $id));
$this->set('plans', $this->paginate('Plan'));
Here is what I did to solve this. Based on some helpful direction from johnp & tokes.
plan_details/view.ctp:
...$i = 0;
foreach ($plan as $plan_edit) : // note $plan here.
}...
In my plan_details_controller.php view action:
$conditions = array("Plan.plan_detail_id" => "$id");
$this->set('plan', $this->paginate('Plan', $conditions)); // note "plan" in the first argument of set (this is required to pass the results back to the view). Also. The $condition is set to return ONLY plans that match the plan_detail_id of id (on the plan_details table).
And in my view, in order to get my results (because I changed the array name), I had to change the way I was getting the values to:
$plan_edit['Plan']['modified'] // note I placed ['Plan'] in front of these calls as the array called for this to get the data...
Well until the next problem! SOLVED.
I'm encountering an issue because I'm sure I'm not doing this correctly with my programming. I have created a custom model in Magento.
In the database table of my model there are several entities with the same attributes...
I need to pick just one from all these entities with the same attribute that I have. For the moment I did this:
$myvariable = Mage::getModel('test/test')->getCollection()
->setOrder('idserialkeys', 'asc')
->addFilter('idproduit', 1)
->addFilter('utilise', 0)
->addFilter('customerid', 0)
->addFilter('numcommande', 0)
From this loading I have around a hundred results but I need to update only one of these, so just after I'm doing:
->setPageSize(1);
The problem is that I need a foreach after to update my entity
foreach($mavaribale as $modifiemoi) {
// Update of my entity because of course there is only one
}
As you can see I'm obliged to do a loop (for each) even if I have a setPagesize... I would like to avoid this loop to optimize my code.
When you have a collection, and you only need one element, use the getFirstItem method. Try this:
$modifiemoi = $myvariable->getFirstItem();
Make sure that you also use your setPageSize call so that you only transfer data for one item.
All collections are Varien_Data_Collection objects so you can use getFirstItem:
$modifiemoi = $mavaribale->getFirstItem();