Controller inserting only last data in array into database - laravel-4

Have asked this question before but it wasn't answered.So am asking again.I have a table subjects with columns:
id->primary key,auto-increment;
class_id->foreign key->refrences id on classes table;
subject;
and a users table:
id->primary key,auto-increment;
username;
password;
and a classes table:
id->primary,autoincrement;
class;
term;
and a pivot table student_user:
id->primary;
user_id->refrences id on users table;
subject_id->refrences id on subject table;
class_id->foreign,refrences id on classes table;
And i have my model to define there relationship thus
//User Model
//User.php
public function subjects()
{
return $this->belongsToMany('Subject');
}
public function myclass()
{
return $this->belongsTo('SchoolClass');
}
//Class Model
//SchoolClass.php
public function subjects()
{
return $this->hasMany('Subject','class_id');
}
//Subject Model
//Subject.php
public function term()
{
return $this->belongsTo('SchoolClass');
}
public function student()
{
return $this->belongsToMany('User');
}
Now here comes the problem.When ever i try to insert data into the pivot table subject_user,only the the last data in the array of values that i want to insert gets saved into the database.I dont know if its the foreign constraint keys that's only updating the row instead of inserting a new one when looping through data.I cant figure out what is wrong.And below is my controller to see how my data is been inserted.Am not very conversant with relationships in laravel
//Save Registered Courses
public function post_proceed_registration()
{
$PageTitle = 'Register Subjects';
$id = Auth::user()->id;
$User = User::find($id);
$class_id = $User->profile->class_id;
$subjects = Input::get('subjects');
$registration = RegistrationCheck::where('class_id',$class_id)->where('user_id',$id)->pluck('status');
if(count(Input::get('students')) != 0)
{
if($registration == 'true')
{
PivotSubject::where('user_id',$id)->where('class_id',$class_id)->delete();
foreach($subjects as $sub_id)
{
$subject = new PivotSubject;
$subject->user_id = $id;
$subject->subject_id = $sub_id;
$subject->class_id = $class_id;
$subject->save();
}
RegistrationCheck::where('class_id',$class_id)->where('user_id',$id)->update(['status'=>'false']);
return Response::Json('Success: Subject/Courses Registered');
}
return Response::Json('Error: You already registered for this Term/Semester.Please Contact ICT for help');
}
return Response::Json('Error:You did not choose any course to register');
}
Am stucked here.Any help would be appriciated

Related

Trying to get referenced Laravel Eloquent data from another table

I'm just learning Laravel, and this is probably super easy for someone experienced with the framework, but I'm trying to get data from a different table and not sure what I'm doing wrong.
I have two tables, Users, which has fields first_name, last_name, and pair_id. The pair_id column is programmatically restricted to either null or an integer in two rows that designates a "pair". The there's the confirmed_pair table that has one pair per row and has a unique pair_id column, that refers to the one in the Users table.
In the ConfirmedPair model, I did this:
class ConfirmedPair extends Model
{
public function pair() {
return $this->hasMany(User::class, 'pair_id');
}
public function pair_names() { // returns an array of names of the players in the confirmed pair
$names = User::where("pair_id", $this->get(["pair_id"])[0]->pair_id)->get(['first_name','last_name']);
if (count($names) == 2) { // if this pair exists
return [
$names[0]['first_name']." ".$names[0]['last_name'],
$names[1]['first_name']." ".$names[1]['last_name']
];
}
return null;
}
}
In the controller, I did this:
class PageController extends Controller
{
public function index()
{
$confirmed_pair = new ConfirmedPair;
return view('page', compact('confirmed_pair'));
}
}
And in the blade view if I do this:
#for ($i = 1; $i < 10; $i++)
{{ $confirmed_pair->find($i)->pair_names()[0] }}<br>
#endfor
No matter what $i's value is, it returns the values of confirmed_pair id #1.
What am I doing wrong? Thanks!
If pair_id is assigned to 2 users
class ConfirmedPair extends Model {
public function pairs() {
return $this->hasMany(User::class, 'pair_id', 'pair_id');
}
public function pair_names() {
if ($this->pairs->count() != 2) return null;
// $this->pairs returns you a Collection of Users
// try to dd($this->pairs) to see in action
$pairs = $this->pairs->toArray();
return [
$pairs[0]['first_name']." ".$pairs[0]['last_name'],
$pairs[1]['first_name']." ".$pairs[1]['last_name']
];
}
}
Can be done better but for your case this should work.

how to view order submitted by customer to the seller?

A customer can post an order to the seller. The problem is how can seller(ps) can view his order.Because each order may be submitted to different seller.
SLotController.php
public function order(Request $request)
{
$slotorder = new Slotorder;
$slotorder->name = $request->name;
$slotorder->user_name = Auth::user()->name;
$slotorder->user_id = Auth::user()->id;
$slotorder->type = $request->type;
$slotorder->quantity = $request->quantity;
$slotorder->size = $request->size;
$slotorder->ps_id = ? // i dont know how to get seller id
$slotorder->save();
return view('home');
}
User model
public function slotorder()
{
return $this->hasMany('Slotorder::class');
}
SlotOrder model
public function user()
{
return $this->belongsTo('User::class');
}
public function user()
{
return $this->belongsTo('Ps::class');
}
Ps Model
public function slotorder()
{
return $this->hasMany('Slotorder::class');
}
Update
After user click make an order, it will go to this page according to their id. For this screenshot the id for the seller is 1. So back to my question , how can i get the seller id when user submit the order. Therefore he can view the order in his dashboard.
You are using a get route, which uses the seller id, so in the method which handles this route send the variable to the view, example:
Route
Route::get('giveorder/{seller_id}',Controller#method);
Controller Method
public function method($seller_id){
return view('giveorder',compact('seller_id'));
}
Create a hidden input inside your form:
<input type="hidden" value="{{$seller_id}}" name="seller_id">
So now you can use this seller_id in your order method:
public function order(Request $request)
{
$slotorder = new Slotorder;
$slotorder->name = $request->name;
$slotorder->user_name = Auth::user()->name;
$slotorder->user_id = Auth::user()->id;
$slotorder->type = $request->type;
$slotorder->quantity = $request->quantity;
$slotorder->size = $request->size;
$slotorder->ps_id = $request->seller_id;
$slotorder->save();
return view('home');
}

Laravel - Best way to store user and his/her dynamically created relations on submit

Which way should I store User Relations which are made "Dynamically"?
By that i mean. I have People table with record of husband for example now husband can add as relation to him (hasMany) his wife and children. Now I have setup the model and it works
Model
This relations are in same table as data is same for them I only need to know if they belong to husband
public function children(){
return $this->hasMany( get_class($this) ,'people_id','id');
}
public function parent(){
return $this->belongsTo( get_class($this) , 'people_id','id');
}
Now when i go to form and add a person husband there. I would have an option to dynamically add his children() (his wife, his children, his grandma...) and submit once its done.
Now i have tought about saving these children to Session first (put them in array) and on submit to post it to controller. Is this a good way or should i do it some other way?
(I hope i explained this well, if not i will try to explain it better)
I have done it like this i dont know if this way is ok but it works for me. Also to add i have just used name for the DB data as i wanted to get this to work.
Store parent and his/her children (if any) in DB from Session
public function store(AdminCreatePersonRequest $request)
{
$data = $request->all();
$parent = new Person;
$parent->name = $data['name'];
$parent->save();
$children = $request->session()->pull('children');
if ($children != null) {
foreach($children as $childData){
$child = new Person(['name' => $childData['child-name']]);
$parent->children()->save($child);
}
}
return redirect('dashboard')->with('success', ['The user was successfully created']);
}
AJAX
Add child to session
public function add(AdminCreatePersonChildRequest $request)
{
$temp = $request->session()->get('children',[]);
$data = $request->all();
unset($data['_token']);
array_push($temp,$data);
end($temp);
$key = key($temp);
$data += ['id' => $key];
$request->session()->put('children', $temp);
return $data;
}
Remove child from session
public function delete(Request $request, $id) {
$temp = $request->session()->pull('children');
unset($temp[$id]);
$request->session()->put('children', $temp);
return 1;
}
Load children from Session on view create (if any)
public function load(Request $request) //get children from session (if exists)
{
$data = $request->session()->get('children');
if($data != null){
return $data;
}
else {
return 0;
}
}
Clear all children from session
public function clear(Request $request) //remove children from session
{
$request->session()->forget('children');
return 1;
}
And with data form controller you update your view (in my case add <li> to <ul> element)

ManyToOne form creating linked object

Imagine these 2 entities:
Article
title
description
category <- ManyToOne
Category
name
Say we need to manage an article with a form and the category attached.
$builder
->add('name')
->add('description')
->add('category')
This one will allow me to select from existing categories.
Now I'd like to be able to create categories if needed.
Title [ ]
Description
[ ]
[ ]
Category [ ]
The category field would be a free text box.
If the text corresponds to no category, a new one would be created and attached.
I tried with some DataTransformer with no luck
I need a reusable solution to manage that because I'll need to embed it especially in another form as a collection.
How can I do it reusable ?
Suggest that you do an "if" on your category.
When you check your form submission is valid and submitted, get the 'category' data, and if not exists persist it as a new category then query for the article after.
The code might be something like this:
if ($form-isSubmitted() && $form->isValid()){
$catName = $form->get('category')->getData(); // Get category.
// Query if it exists.
$qb = $em->createQueryBuilder();
$qb->select('c')
->from('AppBundle:Category', 'c')
->where('c.name = :catName')
->setParameter('catName', $catName);
$cat_results = $qb->getQuery()->setMaxResults(1)->getOneOrNullResult();
if ($cat_results == null){
$newCat = new Category();
$newCat()->setname($catName);
$em->persist($newCat);
$em->flush();
}
else{
...
\\ Render your form etc...
}
Hopefully you get the idea. The above code is simpler, because then you create the category in the same form.
Here is what I ended up with using a DataTransformer
My ArticleType:
class ArticleType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('description')
->add('category', CategoryType::class)
//...
A new CategoryType class:
class CategoryType extends AbstractType
{
protected $myService;
public function __construct(MyService $myService)
{
$this->myService = $myService;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$transformer = new CategoryTransformer($this->myService);
$builder->addModelTransformer($transformer);
}
}
Registered as service
app.form.category_type:
class: AppBundle\Form\CategoryType
arguments: ['#app.my.service']
tags:
- { name: form.type }
And finally the transformer:
class CategoryTransformer implements DataTransformerInterface
{
// ...MyService initialization...
public function transform($category)
{
if (null === $category) {
return '';
}
return $category->getName();
}
public function reverseTransform($categoryName)
{
if (!$categoryName) {
return null;
}
$category = $this->myService->getOrCreateCategoryFromName($categoryName);
if (null === $category) {
throw new TransformationFailedException();
}
return $category;
}
}
MyService is responsible to get or create a category with the given name using the entity manager.
Quite some lines of code but once this is done, wherever I'll use my form, it can be dealt in the easy standard way:
$articleForm = $this->createForm(ArticleType::class, $article);
$articleForm->handleRequest($request);
if ($articleForm->isValid()) {
$em->persist($article);
$em->flush();
//...

Adding custom eloquent attribute in Laravel 5

I have a function named siblings which fetches all siblings of a user.
select siblings(id) as `siblings` from users where id = 1
I can access the function in Eloquent as
User::where('id', 1)->first([DB::raw(siblings(id) as `siblings`)]->siblings;
I want to make the siblings available via custom attribute.
I added siblings to $appends array
I also created getSiblingsAttribute method in my User model as
public function getSiblingsAttribute()
{
if (!$this->exists()) {
return [];
}
$siblings = User::where('idd', $this->id)
->first([DB::raw('siblings(id) AS `siblings`')])
->siblings;
return explode(',', $siblings);
}
But this is not working as $this->id returns null
My table schema is users(id, username,...), so clearly id is present.
Is there a way by which I can bind the siblings function while querying db and then returning something like $this->siblings from getSiblingsAttribute. If I can bind siblings(id) as siblings with query select globally as we do for scopes using global scope.
That way my code can be simply
public function getSiblingsAttribute()
{
return $this->siblings;
}
The simplest way is to create a view in your database and use that as a table:
protected $table = 'user_view';
Otherwise I need more information about your id == null problem.
If you can fix this by your own in the next step it is important that you use an other column name by selecting as in your accessor otherwise you run in an infinite loop.
public function getSiblingsAttribute()
{
if (!$this->exists()) {
return [];
}
$siblings = User::where('id', $this->id)
->first([DB::raw('siblings(id) AS `siblings_value`')])
->siblings_value;
return explode(',', $siblings);
}
EDIT
Sadly there is no simple way to archieve this.
But after a little bit tinkering I have found a (not very nice) solution.
Give it a try.
You have to add the following class and trait to your app.
app/Classes/AdditionalColumnsTrait.php (additional column trait)
namespace App\Classes;
trait AdditionalColumnsTrait {
public function newEloquentBuilder($query) {
$builder = new EloquentBuilder($query);
$builder->additionalColumns = $this->getAdditionalColumns();
return $builder;
}
protected function getAdditionalColumns() {
return [];
}
}
app/Classes/EloquentBuilder.php (extended EloquentBuilder)
namespace App\Classes;
use Illuminate\Database\Eloquent\Builder;
class EloquentBuilder extends Builder {
public $additionalColumns = [];
public function getModels($columns = ['*']) {
$oldColumns = is_null($this->query->columns) ? [] : $this->query->columns;
$withTablePrefix = $this->getModel()->getTable() . '.*';
if (in_array('*', $columns) && !in_array($withTablePrefix, $oldColumns)) {
$this->query->addSelect(array_merge($columns, array_values($this->additionalColumns)));
} elseif (in_array($withTablePrefix, $oldColumns)) {
$this->query->addSelect(array_values($this->additionalColumns));
} else {
foreach ($this->additionalColumns as $name => $additionalColumn) {
if (!is_string($name)) {
$name = $additionalColumn;
}
if (in_array($name, $columns)) {
if (($key = array_search($name, $columns)) !== false) {
unset($columns[$key]);
}
$this->query->addSelect($additionalColumn);
}
}
if (is_null($oldColumns)) {
$this->query->addSelect($columns);
}
}
return parent::getModels($columns);
}
}
after that you can edit your model like this:
class User extends Model {
...
use App\Classes\AdditionalColumnsTrait;
protected function getAdditionalColumns() {
return [
'siblings' => DB::raw(siblings(id) as siblings)),
];
}
...
}
now your siblings column will be selected by default.
Also you have the option to select only specific columns.
If you don't want to select the additional columns you can use: User::find(['users.*']).
Perhaps it is a solution for you.

Resources