Laravel easier way to save multiple input fields to database - laravel

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!

Related

Laravel model is updating multiple models instead of single

I am trying to update my model using multiple where conditions.
my code is
public function UpdateEducationData(Request $request)
{
$user = app('user');
// return $request;
$education = eduinfo::where("id", $user->id)->where("exam", $request->type)->first();
// dump sql query for debugging
// $education->rawSql();
// dd($education);
$education->board = $request->board;
// $education->degree = $request->degree;
$education->year = $request->year;
$education->rollno = $request->rollno;
$education->obtainmarks = $request->obtainmarks;
$education->totalmarks = $request->totalmarks;
$education->division = $request->division;
$education->grade = $request->grade;
$education->totalcgpa = $request->totalcgpa;
$education->obtailcgpa = $request->obtailcgpa;
// update education based on exam
$education->save();
return redirect()->back()->with("message", "Education Information Updated Successfully");
return "Update Education Data";
}
My code is updating a eduinfo table based on id and exam. But whenever this function is called it updates all eduinfo records related to that user id.
I tried to update eduinfo table single record but multiple records are being update at once. I dumped eduinfo after retriving the model and yes it's retrieving the single model using first() method but still when save() is called it updates all records of that user id in eduinfo.
I think Your conditions to make a unique record are not.
But if you wanna Just run one time! I have an offer to you.
$flag=true;
if($flag){
$user = \Auth::user();
$education = eduinfo::where('id','=', $user->id)->where('exam','=', $request->type)->first();
$education->board = $request->board;
$education->year = $request->year;
$education->rollno = $request->rollno;
$education->obtainmarks = $request->obtainmarks;
$education->totalmarks = $request->totalmarks;
$education->division = $request->division;
$education->grade = $request->grade;
$education->totalcgpa = $request->totalcgpa;
$education->obtailcgpa = $request->obtailcgpa;
$education->save();
$flag=false;
}
It's depends on my answer.

Save multiple inputs Laravel 5.6

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".

Magento Observer - Getting Newsletter Subscribtion from Order Object

What can I call from an $observer object to determine if the guest or customer clicked the subscribe checkbox on checkout? So far I have this:
public function collectCustomerData($observer)
{
$this->observer = $observer;
$this->_order = $this->observer->getEvent()->getOrder();
$this->_address = $this->_order->getShippingAddress();
$this->data['first_name'] = $this->_address->getFirstname();
$this->data['last_name'] = $this->_address->getLastname();
$this->data['city'] = $this->_address->getCity();
$this->data['email'] = $this->_order->getCustomerEmail();
}
but I need to add $this->data['is_newsletter'] from either $this->_order(Mage_Sales_Model_Order) or $this->_address(Mage_Sales_Model_Order_Address), or pull in another model that has that information through static factory methods such as Mage::getModel() if I need to
I figured it out, I had to bring the newsletter/subscriber model into the equation. The following code returned either 1 or null:
$email = $this->_order->getCustomerEmail();
$isNewsletter = Mage::getModel('newsletter/subscriber')
->loadByEmail($email)
->getSubscriberStatus();
Based on that I was able to set the opt in flag appropriately:
$this->data['is_newsletter'] = $isNewsletter;

How to Cache Multiple Versions of a Page using Razor Dynamic Query & WebCache

I decided to implement caching to improve the performance of the product pages.
Each page contains a large amount of the product's images.
I created the following code in a Razor view.
#{
var productID = UrlData[0].AsInt();
var cacheItemKey = "products";
var cacheHit = true;
var data = WebCache.Get(cacheItemKey);
var db = Database.Open("adldb");
if (data == null) {
cacheHit = false;
}
if (cacheHit == false) {
data = db.Query("SELECT * FROM Products WHERE ProductID = #0", productID).ToList();
WebCache.Set(cacheItemKey, data, 1, false);
}
}
I'm using the data with the following code:
#foreach (dynamic p in data)
{
<a href="~/Products/View/#p.ProductID"
<img src="~/Thumbnail/#p.ProductID"></a>
}
The caching code works well, but when passing the new query string parameter (changing the version of the page) the result in browser is the same for the declared cashing time.
How to make caching every version of the page?
Thanks
Oleg
A very simple approach might be to convert your key (productID) to a string and append it to the name of your cacheItemKey.
So you might consider changing the line:
var cacheItemKey = "products";
to read:
var cacheItemKey = "products" + productID.ToString();
This should produce the behavior you are looking for -- basically mimicking a VaryByParam setup.
ps. Please keep in mind I have not added any sort of defensive code, which you should do.
Hope that helps.

TYPO3 Extbase: How to render the pagetree from my model?

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;
}

Resources