I'm trying to save a data to my database coming from 2 inputs which has multiple values. The scenario is that after a product has been saved, data will be save to my another table with columns 'product_id','price','size'. How ever when I tried to run my code, only the first value is saved in the column 'size', the data in 'price' are fine.
<input name="fix_size[]">
<input name="fix_price[]">
foreach($request->fix_price as $prc){
$cprice = new ContainerPrice;
$cprice->product_id = $id;
$cprice->price = $prc;
foreach($request->fix_size as $size){
$cprice->size = $size;
}
$cprice->save();
}
Remember, fix_size and fix_price are arrays.
You have to get the respective pairs of each fix_size and fix_price. So you have to monitor the index in the loop.
This is one of the possible solution in your problem:
$fix_sizes = $request->fix_size;
foreach($request->fix_price as $i => $prc){
$cprice = new ContainerPrice;
$cprice->product_id = $id;
$cprice->price = $prc;
$cprice->size = $fix_sizes[$i];
$cprice->save();
}
I may suggest to you to master the basic principles of programming and learn to debug codes by yourself.
Try this
foreach($request->fix_price as $prc){
foreach($request->fixed_size as $size){
$cprice = new ContainerPrice;
$cprice->product_id = $id;
$cprice->price = $prc;
$cprice->size = $size;
$cprice->save();
}
}
You could try this:
foreach($request->fix_price as $key => $prc) {
$cprice = new ContainerPrice;
$cprice->product_id = $id;
$cprice->price = $prc;
$cprice->size = $request->input('size')[$key];
$cprice->save();
}
The problem you had is because you loop over all elements inside the main loop and keeping only the last element. In other words, in the foreach loop, you are constantly overriding the $cprice->size property with the last you find.
Now with this code you access the "size" which has the same index as your "price".
Related
I loop trough an eloquent Collection and I want to add the data to another Collection called "$tagCollection". If an entry with the same tag_id already exists I only want to increase the rating-column for the existing entry.
At the moment it looks like this. Has anyone an Idea?
$tagCollection = collect();
$entries->each(function($entry) use($tagCollection){
$tagId = $entry->tag_id;
//something like this
if($tagCollection->contains('tag_id', $tagId)){
$tagCollection->update ('rating' => $oldRating + 0.5)
} else{
$tagCollection->push(array(
'tag_id' => $tagId,
'rating' => 0.35
));
}
});
I also tried to use ->pull() to remove the Item out of the Collection and then push it again with the new rating but I also do not know how
Can you do it with array instead of collection? For example:
$tagArray = [];
$entries->each(function ($entry) use (&$tagArray) {
if (isset($tagArray[$entry['tag_id']])) {
$tagArray[$entry['tag_id']] += 0.5;
} else {
$tagArray[$entry['tag_id']] = 0.35;
}
});
If the end goal is to update all the entries present in $entries that belong to a specific $tagId, then you can do this
$entryIds = $entries->where('tag_id',$tagId)->pluck('id')->toArray();
Entry::whereIn('id', $entryIds)->update(['rating' => \DB::raw('rating + 0.5')]);
And thats it.
I'm working with Lumen framework v5.8 (it's the same as Laravel)
I have a command for read a big XML (400Mo) and update datas in database from datas in this file, this is my code :
public function handle()
{
$reader = new XMLReader();
$reader->open(storage_path('app/mesh2019.xml'));
while ($reader->read()) {
switch ($reader->nodeType) {
case (XMLREADER::ELEMENT):
if ($reader->localName === 'DescriptorRecord') {
$node = new SimpleXMLElement($reader->readOuterXML());
$meshId = $node->DescriptorUI;
$name = (string) $node->DescriptorName->String;
$conditionId = Condition::where('mesh_id', $meshId)->first();
if ($conditionId) {
ConditionTranslation::where(['condition_id' => $conditionId->id, 'locale' => 'fr'])->update(['name' => $name]);
$this->info(memory_get_usage());
}
}
}
}
}
So, I have to find in the XML each DescriptorUI element, the value corresponds to the mesh_id attribute of my class Condition.
So, with $conditionId = Condition::where('mesh_id', $meshId)->first(); I get the Condition object.
After that, I need to update a child of Condition => ConditionTranslation. So I just get the element DescriptorName and update the name field of ConditionTranslation
At the end of the script, you can see $this->info(memory_get_usage());, and when I run the command the value increases each time until the script runs very very slowly...and never ends.
How can I optimize this script ?
Thanks !
Edit : Is there a way with Laravel for preupdate multiple object, and save just one time at the end all objects ? Like the flush() method of Symfony
There is a solution with ON DUPLICATE KEY UPDATE
public function handle()
{
$reader = new XMLReader();
$reader->open(storage_path('app/mesh2019.xml'));
$keyValues = [];
while ($reader->read()) {
switch ($reader->nodeType) {
case (XMLREADER::ELEMENT):
if ($reader->localName === 'DescriptorRecord') {
$node = new SimpleXMLElement($reader->readOuterXML());
$meshId = $node->DescriptorUI;
$name = (string) $node->DescriptorName->String;
$conditionId = Condition::where('mesh_id', $meshId)->value('id');
if ($conditionId) {
$keyValues[] = "($conditionId, '".str_replace("'","\'",$name)."')";
}
}
}
}
if (count($keyValues)) {
\DB::query('INSERT into `conditions` (id, name) VALUES '.implode(', ', $keyValues).' ON DUPLICATE KEY UPDATE name = VALUES(name)');
}
}
I am trying to save a long form data to database. Till now i am getting the form value from request object and setting it to database model.
This works perfectly fine. But I want to know if there is another way to initialise the model efficiently without need to set each value. My model has one to one relation.
I have been doing like this. But i don't think this is the right way to do
//Student details
$studentDetail->student_first_name = $request->input('studentFirstName');
$studentDetail->student_last_name = $request->input('studentLastName');
$studentDetail->student_phone_number = $request->input('studentPhoneNumber');
$studentDetail->student_date_of_birth = $request->input('studentDOB');
$studentDetail->student_email = $request->input('studentEmail');
$studentDetail->save();
$studentAddress = new Address();
$studentAddress->address_1 = $request->input('studentAddress1');
$studentAddress->address_2 = $request->input('studentAddress2');
$studentAddress->city = $request->input('studentCity');
$studentAddress->state = $request->input('studentState');
$studentAddress->country = $request->input('studentCountry');
$studentAddress->post_code = $request->input('studentPostCode');
$studentDetail->addresses()->save($studentAddress);
$visaDetails = new Visa();
$visaDetails->passport_number = $request->input("visaPassportNumber");
$visaDetails->visa_number = $request->input("visaVisaNumber");
$visaDetails->visa_class = $request->input("visaVisaClass");
$visaDetails->visa_grant_date = $request->input("visaVisaGrantDate");
$visaDetails->visa_expiry_date = $request->input("visaVisaExpiryDate");
$studentDetail->visaDetails()->save($visaDetails);
//
$instituteDetails = new Institute();
$instituteDetails->institute_name = $request->input("instituteName");
$instituteDetails->institute_location = $request->input("instituteLocation");
$instituteDetails->institute_phone1 = $request->input("institutePhone1");
$instituteDetails->institute_phone2 = $request->input("institutePhone2");
$instituteDetails->institute_email = $request->input("instituteEmail");
// dd($instituteDetails->courses);
$courseDetails = new Course();
$courseDetails->course_level = $request->input("courseLevel");
$courseDetails->course_name = $request->input("courseName");
$courseDetails->course_fee = $request->input("courseFee");
$courseDetails->course_concession_fee = $request->input("courseConcessionFee");
$courseDetails->course_duration = $request->input("courseDuration");
$courseDetails->course_commencement_date = $request->input("courseCommencementDate");
$studentDetail->instituteDetails()->save($instituteDetails);
$instituteDetails->courses()->save($courseDetails);
Any idea on making this process faster??
Simply set create your models using mass assignment, so:
So in your model StudentDetail:
class StudentDetail{
protected $fillable = [
'student_first_name',
'student_last_name',
'student_phone_number',
'student_date_of_birth',
'student_email',
];
//...
//... rest of your model
}
Then tweak your HTML inputs to have in their names the user array like so for example:
<input type="text" id="foo" name="student[student_first_name]">
<input type="text" id="foo" name="student[student_last_name]">
.....
Tip: for validation, you have to treat it with dot notation, so your rule could be:
'student.student_first_name' => 'required|humanName|string|max:255',
Now simply do the following in your controller:
$studentDetail = StudentDetail::create($request->input('student'));
Now you made do the same for your address and other models.
The GIST: After mass assignment enabled for your models you could end up having ONLY the following couple lines of code doing it all for you and it's way more fun and full of dynamism ;) IMHO!
$relatedModels = ['Address', 'Visa', 'Institute', 'Course'];
foreach ($relatedModels as $relatedModel) {
$relatedModelClass = 'App\\'.$relatedModel; //adjust the namespace of your models here.
$ormRelatedModel = $relatedModelClass::create(strtolower($request->input($relatedModel)));
$studentDetail->{strtolower(str_plural($relatedModel)) . 'Details'}()->save($ormRelatedModel);
}
please note that in this case your relations names should be changed a bit like addresses function within your StudentDetail class/model should be changed to addressesDetails or just remove the .'Details' from my sample code above and remove it from your other relations names, i.e: change instituteDetails() to institute(). and make the relation names plural please!
I just tested it and it's working,
Cheers!
I am creating an application in Symfony2. This is the first time I develop using a framework and one of my first projects. It is a student project.
In this project, I want my collections of entities to be sorted somewhere before reaching the view. This can be done in this way:
In getters on the entities on the many-to-one relations, with comparator methods on the many-side that is used by the usort() method in the getter on the one-side. Below I have a method that also fills in gaps in a collection of "Day" entities (in a form of diary), but the point is that it sorts the days with usort.
In User entity class:
public function getDaysWithNulls()
{
$days = $this->getDays()->toArray();
//get the first day and find out how many days have passed
usort($days, array("\Pan100\MoodLogBundle\Entity\Day", "daySorter"));
$firstEntry = $days[0];
$interval = $firstEntry->getDate()->diff(new \DateTime());
$numberOfDaysBack = $interval->d;
//create an array consisting of the number of days back
$daysToShow = array();
for ($i=0; $i < $numberOfDaysBack ; $i++) {
$date = new \DateTime();
$date->sub(new \DateInterval('P' . $i . 'D'));
$daysToShow[] = $date;
}
$daysToReturn = array();
foreach ($daysToShow as $day) {
//figure out if this day has an entity, if not set an empty Day object
$dayEntityToProcess = new \Pan100\MoodLogBundle\Entity\Day();
$dayEntityToProcess->setDate($day);
foreach ($days as $dayEntity) {
//check if there is a day entity
if($day->format('Y-m-d') == $dayEntity->getDate()->format('Y-m-d')) {
$dayEntityToProcess = $dayEntity;
}
}
$daysToReturn[] = $dayEntityToProcess;
}
//return a collection
return new \Doctrine\Common\Collections\ArrayCollection($daysToReturn);
}
usort uses this in the Day entity class:
static function daySorter($dayEntity1, $dayEntity2) {
$interval = $dayEntity1->getDate()->diff($dayEntity2->getDate());
if($interval->invert == 1) {
return +1;
}
else if ($interval->invert == 0) {
return 0;
}
else return -1;
}
My question is: is this the best practice for sorting and returning sorted collections, or should sorting happen somewhere else?
I did think this was a tedoius way of doing it. So I searched the web a bit, and read some more, and found that I can create custom repositories.
I will do it this way instead:
http://symfony.com/doc/2.1/book/doctrine.html#custom-repository-classes
EDIT: found out the sorting is better done in annotations:
/**
* #ORM\OneToMany(targetEntity="Day", mappedBy="user_id")
* #ORM\OrderBy({"date" = "DESC"})
**/
protected $days;
I want to create some kind of sitemap in extbase/fluid (based on the pagetree). I have loaded the pages table into a model:
config.tx_extbase.persistence.classes.Tx_MyExt_Domain_Model_Page.mapping.tableName = pages
I have created a controller and repository, but get stuck on the part wich can load the subpages as relation into my model.
For example:
$page = $this->pageRepository->findByPid($rootPid);
Returns my rootpage. But how can I extend my model that I can use $page->getSubpages() or $page->getNestedPages()?
Do I have to create some kind of query inside my model? Or do I have to resolve this with existing functions (like the object storage) and how?
I tried a lot of things but can simply figure out how this should work.
you have to overwrite your findByPid repository-method and add
public function findByPid($pid) {
$querySettings = $this->objectManager->create('Tx_Extbase_Persistence_Typo3QuerySettings');
$querySettings->setRespectStoragePage(FALSE);
$this->setDefaultQuerySettings($querySettings);
$query = $this->createQuery();
$query->matching($query->equals('pid', $pid));
$pages = $query->execute();
return $pages;
}
to get all pages. Than you can write your own getSubpages-method like
function getSubpages($currentPid) {
$subpages = $this->pagesRepository->findByPid($currentPid);
if (count($subpages) > 0) {
$i = 0;
foreach($subpages as $subpage) {
$subpageUid = $subpage->getUid();
$subpageArray[$i]['page'] = $subpage;
$subpageArray[$i]['subpages'] = $this->getSubpages($subpageUid);
$i++;
}
} else {
$subpageArray = Array();
}
return $subpageArray;
}
i didn't test this method, but it looks like this to get alle subpages.
i wonder that i couldĀ“t find a typo3 method that return the complete Page-Tree :( So i write a little function (you can use in an extbase extension), for sure not the best or fastes way, but easy to extend or customize ;)
first you need an instance of the PageRepository
$this->t3pageRepository = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\Page\\PageRepository');
this->t3pageRepository->init();
make the init, to set some basic confs, like "WHERE deletet = 0 AND hidden = 0..."
then with this function you get an array with the page data and subpages in. I implement yust up to three levels:
function getPageTree($pid,$deep=2){
$fields = '*';
$sortField = 'sorting';
$pages = $this->t3pageRepository->getMenu($pid,$fields,$sortField);
if($deep>=1){
foreach($pages as &$page) {
$subPages1 = $this->t3pageRepository->getMenu($page['uid'],$fields,$sortField);
if(count($subPages1)>0){
if($deep>=2){
foreach($subPages1 as &$subPage1){
$subPages2 = $this->t3pageRepository->getMenu($subPage1['uid'],$fields,$sortField);
if(count($subPages2>0)){
$subPage1['subpages'] = $subPages2;
}
}
}
$page['subpages'] = $subPages1;
}
}
}
return $pages;
}