Which is best way about delete row and insert row in Laravel - php

As title, I have a table like student and another table is class.
User can edit about student having some class.
There is one to many relationship.
When user edit student's class, I always must to delete this student's class.
And insert the new class after that.
\App\class:where('student_id',$student->id)->delete();
foreach($request->input('class') as $class){
$new = new \App\class;
$new->student_id = $student->id;
$new->class_id = $class;
$new->save();
}
Is there have any solution about this issue?
Thanks.

For the moment I'll assume you have your relationships setup properly.
You'll want to take a look at sync.
Documentation
$student->classes()->sync($request->input('class'))
The sync method want's the ID's of the classes as argument.

Related

Dynamic hasMany relationship in Laravel/Eloquent

I want to have a dynamic relationship based on a class name, which is stored as a property on a far related model.
There are lots of different class names so I don't want to make lots of relationships. It's a bit complicated but it has to be this way.
function subjectvotes() {
$className = $this->masterCourse->subject->class_name;
return $this->hasMany($class)->orderBy('value');
}
Trying to do it this way won't work mid-query because it doesn't always have the 'child' model information yet (as ->get() hasn't been run). Another issue with this is it's running the same $this->parent->grandparent query every time — not ideal.
Before I start the relationship query, I can run this to get the class name and table name respectively:
$className = $masterCourseModel->subject->class_name;
$tableName = ( new $className )->getTable();
But how to feed this into the relationship I'm not yet sure:
$masterCourseModel->studentCourse()->with('subjectvotes')->get();
Without creating a lot of relationships for each possible class, how do I feed the $className in to create a dynamic hasMany relationship, or can I do this by adding a new query scope and feeding in the $tableName or $className that way?
Thanks in advance for any assistance.

Symfony2: is ArrayCollection better than multiple db queries?

In Symfony2 I have two entities (Companies and Employees) with a One-to-Many relation (one company can have multiple employees).
Each Employee object has an id, a company_id (foreign key), a badge_number, a last_updated datetime field, name, etc
Easy, right?
Now comes the tricky part...
Each day I get (from an API) a $company_upd array that contains the list of all the companies that updated some of their employees data. Then, for each company in $company_upd, I retrieve from the API a $company_employees_list array that cointains the new list of employees .
Then I loop through the array to identify any new/updated record that needs to be persisted in my local database. Like this:
foreach ($company_employees_list as $employee){
$local_employee = $repo->findOneBy("badge_number" => $employee["badge_number"];
//if there is already an employee record with the same badge_number
if($local_employee){
//compare the last_updated field to see if this employee record needs to be updated
if($employee["badge_number"] > $local_employee->getLastUpdated()){
//update the record and persist to the database
$local_employee->setSomething($employee["some_value"];
}
} else {
//create a new employee object and persist it to the database
$new_employee = new Employee();
$new_employee->setSomething('some_value');
$em->persist($new_employee);
}
}
$em->flush();
Of course, this approach works fine BUT I'm doing a query foreach employee foreach company!! (to retrieve the corresponding object and update it)
Is it possible (and would it be better) to use the ArrayCollection? I mean: fetch the employees ArrayCollection ONE TIME and then, work with it. Search if there is already an employee record with a specific badge_number and eventually update it and persist it to the database?
So, basically, I would like to do everything I did in the code above but using Array_Collection instead of separate queries.
But only if this new approach is faster/better.
If it is indeed possible (and faster), could you please write some mockup code to better understand HOW to manipulate an ArrayCollection and do what I want?
//Fetch the local db employees ArrayCollection
$employees_ar_coll = $company->getEmployees();
//What now???? =)
P.s. The API works like this, can't change that.

Laravel, do I need multiple database tables for votes on different models

I have a Question model which has a one to many relationship with an Answer model.
Now I want to add upvote/downvote funcionality to both of these models, do I need to create two tables like VotesQuestions and VotesAnswers or can I somehow manage with one? If so, how?
You can use a polymorphic relationship. This is built into Laravel. Documentation is here. The code shown here is for Laravel 4, but the functionality is the same for Laravel 5.
Create a votes table, and make sure it has at least two specific fields: votable_id and votable_type. In a database migration, you would use the statement $table->morphs('votable');, and it will create the two fields. You can have as many other fields as you like, but to make sure the relationship works, those two fields are required.
Next, setup the Vote model with the votable relationship. The name of this relationship should match the base name of the fields you created:
class Vote extends Eloquent {
public function votable() {
return $this->morphTo();
}
}
With this setup, you can now associate votes to any model you want. Go ahead and add the votes relationship to the Question and Answer models:
class Question extends Eloquent {
public function votes() {
return $this->morphMany('Vote', 'votable');
}
}
class Answer extends Eloquent {
public function votes() {
return $this->morphMany('Vote', 'votable');
}
}
You can now access the votes for any question/answer through the relationship:
$q = Question::first();
$qVotes = $q->votes; // Collection of votes for the question.
$a = Answer::first();
$aVotes = $a->votes; // Collection of votes for the answer.
You can also get the related question/answer model through the vote, if you ever need to:
$v = Vote::first();
$vRelated = $v->votable; // Will automatically be a Question or Answer object, depending on what the vote was for.
I would do an table for the question and when you want to up/downvote the question there should be a count column for both, otherwise you want to log it that an user can only vote for it once, so you need another table for user_id, question_id and type (up/down).
ofc you can handle it with one table, but that is really worth because you save many things that are not necessary.
you can create a table with an internal id, 1,2,3,4 and 1 is always the question or 0 and 2-xx (1-xxx) are always the answers. so you can handle it with one table
You could create a generic Votes model/table which has a field called "model" and "model_id" and then use reflection to get the correct object.

Interface or type-hint for single object and multiple object class in php

Recently started working with OOP in PHP. Following the "code to an Interface" principle, i got confused as to the type hint to use when passing a single object or multiple as argument to a method.
Currently, i have a "Student" class - represents a row in my students table, i also have a "Students" class that holds multiple student objects in an array.
To fetch the profile of one student, i pass the Students object (holding a single student object) to the profile class. I set a Students type hint in the profile class.
Now i feel this is bad code as i have lines like this
student = new Students();
and students = new Students();
question is,
am i on the right path?
if i remove the Students class and work with Student alone, based on the principle, how do i pass multiple Student objects (assuming array) to the profile class if it accepts a Student type hint?
what options do i have?
Thanks.
If by Students you mean a collection of Student objects, perhaps a better name would be StudentCollection or StudentSet.
There are two ways around the type hint problem:
Introduce a method on StudentCollection called ->getProfiles(); it would return an array of profiles for each Student instance it's managing by calling methods on Profile.
Introduce a (static) method on Profile that operates on a StudentCollection instance.
The first option has feature envy, which is why I've included a workaround.
Instead of reinventing the wheel you might want to try Doctrine or at least take a look at its architecture.
I'm not sure if I get your exact issue... But if you want to go for your own code I would first abstract the DB layer as well and have some base classes like Database, Table, Row, Field that an describe the DB stack and extend them as needed with some magic methods. So when you do Student extends Table it would automatically check for a "students" table or whatever else convention you like to implement. Alternatively you could just pass the table name as arg.
Whatever Object is returning the result set from the database would have to construct a single Row object for each row and add it to a collection of rows that I would name ResultSet and contains all the row objects and return that collection.

CodeIgniter: datamapper ORM delete() a relation;

I have a tables called users, countries, and countries_users.
The documentation states that to delete a simple relationship you perform:
// Get user foo
$u = new User();
$u->where('username', 'foo')->get();
// Get country object for Australia
$c = new Country();
$c->where('name', 'Australia')->get();
// Delete relation between user foo and country Australia
$u->delete($c);
This would remove the corresponding row from the countries_users table.
My question is, what if I have no relevant Country() object to construct?
If countries and users are a one-to-many relationship, then certainly knowing the username attribute is enough to disassociate him with a country.
All the delete functions seem to require at least two objects... What is the best way to accomplish the deletion of this type of relation using the DataMapper ORM functions?
"All the delete functions seem to require at least two objects"
Not totally true, a delete() can be preformed on a single object without the need to explicitly delete the object's relationships, it is handled automatically.
From the user guide:
Note: When you delete an object, all its relations to other objects will also be deleted. Free house cleaning! :)
In addition, you may use a column in the users table for the country id instead of a separate countries_users table for relationships, assuming it is a one(country)-to-many(users) relationship.
My question is, what if I have no relevant Country() object to construct?
Then you don't have to worry about anything. If there are no relationships to delete, attempting to delete them will not cause any harm.
There is a relationship to delete! I want to pass the user_id into my Controller and disassociate him with a country in the countries_users table. To accomplish this using the documented functions, I would have to also pass in the country_id... Which IMO is irrelevant for this operation.
You don't have to look up the country id unless you specifically want to delete a particular relationship. In your case, you're working with a relationship where a user can only have one country, so you don't need to specify which related country to delete. Here are two options off the top of my head:
Assigning a new country (removes the previous one)
$c = new Country();
// Get all countries named "Wonderland"
// Usually we'll use an id instead, there could theoretically be more than one
$c->where('name', 'Wonderland')->get();
$user->save($c);
Just delete all related countries (there is only one of course)
$c = new Country();
// Get all countries
$c->get();
$user->delete($c); // You may need $c->all here
If we were working with a many to many relationship, you would of course have to know which ones to delete, but since there is only one - deleting them all is sufficient.
Believe it or not, I was unable to remove the relationship using the code Wesley has provided.
However, this seemed to work:
$u = new User();
$u->where('id', $id)->include_related('country', 'id', TRUE, TRUE)->get();
$c = new Country();
$c->where('id', $u->country->id)->get();
$c->delete($u);

Categories