Is there a way to execute some code on Associate?
For example I would like to execute some operation where a Dog is associated to a Man with $dog->man()->associate($man);, is it possibile?
Related
I am writing a migration in Laravel to try and change the primary key of a table to another column. In order to work around the fact that the dropPrimary method doesn't work when one has a custom defined constraint name in PostgreSQL, I currently have the following line in my migration:
DB::statement('ALTER TABLE users DROP CONSTRAINT "idx_16618_primary";');
However, I am hitting issues with the fact that DB::statement commands are executed immediately, whereas all the Schema:: commands essentially build queries that are put into a commands array and executed later. I am assuming this because when I look at something like the renameColumn method in Blueprint.php, I can see that it runs addCommand, which puts the command into an array:
protected function addCommand($name, array $parameters = [])
{
$this->commands[] = $command = $this->createCommand($name, $parameters);
return $command;
}
This means all of the preparation I do before the DB::statement command have not executed yet. This preparation includes going to other tables and removing foreign key constraints that point to the primary key that I am trying to drop.
Is there a way to get trigger the execution of all of the built Schema commands mid-way through a migration (e.g. something like Schema::flush()), or do I either have to convert all my prep work into DB::statement commands, or split my current migration code across two migrations, in order to have the DB::statement command executed after the prep work has been done?
Is there a way to convert a pagination to a collection/array to get all items like:
Users::where(...)->paginate(15); //paginated
Output: 15 per page
Users::where(..)->get(); //not paginated
Output: all Users per page
So i is it possible to do something like that:
Users::where(...)->paginate(15)->removePagination();
Wanted output: all Users per page
You have 2 choices:
either retrieve the complete query result by chaining ->get()onto your query.
call ->paginate() to retrieve a pagination instance, which automatically retrieves the first page, and it automatically links the example.com?page=1 url param.
(there are also some other functions that complete the query like ->pluck() or ->value() which might not be applicable to you)
As far as I'm aware you cannot revert to the complete collection instance when you have the pagination retrieved (\Illuminate\Contracts\Pagination\LengthAwarePaginator), nor does it make sense to do so since the idea is to retrieve as little data as possible such that your application stays fast.
Maybe you should explain what you're trying to do; for instance you can retrieve the total count in the paginator using SomeModel::query()->paginate()->total(), among other things. You might not need the complete query after all.
I have defined a many-to-many relationship between Student and Seminar models. How can I find out if one particular student is attending one particular seminar? Non-working example of what I want to achieve is illustrated below:
$seminar->students()->contains($student->id);
The following error is shown when using the above code snippet:
BadMethodCallException with message 'Call to undefined method Illuminate\Database\Query\Builder::contain()'
Try instead:
$seminar->students->contains($student->id);
Presuming $student contains an instance of the Student model you can simplify it further and just use:
$seminar->students->contains($student);
When you add parentheses you're using the Laravel query builder, and you never completed the query. To do it in the manner you had originally you would need:
$seminar->students()->get()->contains($student->id);
This method could be useful if you wanted to add constraints when fetching your students.
But generally you can omit the parentheses and a Collection will be returned, allowing you to use methods like contains.
This has the additional benefit of not re-querying the database once the relationship is loaded, so will generally be a far more efficient means of fetching relationships.
If you haven't already loaded the students and want a database efficient method of checking you could instead use:
$seminar->students()->where('students.id', $student->id)->exists();
In your case the exception is you are calling 'contains()' function (which is for Laravel Collection) on 'Query Builder'. It should be
$seminar->students->get()->contains($student->id);
but this is inefficient since this will retrieve all the students of the seminar.
so instead,
$seminar->students()->wherePivot('student_id', $student->id)->exists();
this method will check in the intermediate table of many to many relationship for particular seminar-student pair, and will return whether exists or not.
The accepted answer is wrong. $seminar->students()->exists($student->id) does not check if the relationship exists. It only checks if the student exists. The student could belong to any seminar and it would still return true.
The correct way to check if a relationship exists without fetching records from the database would be:
$seminar->students()->whereId($student->id)->exists()
Check using query
$seminar->students()->whereKey($student->getKey())->exists();
Check after query (angry), can have memory problems if you have multiple attachments
$seminar->students->contains($student->getKey());
// or
$seminar->students()->get()->contains($student->getKey());
I have Question and Answer models. The Question hasMany Answers. Following commands run in the php artisan tinker mode invoke a database query for no apparent reason:
$q = new Question;
$q->answers[] = new Answer; // invokes the below query
// the executed query
select * from `answers` where `answers`.`question_id` is null and `answers`.`question_id` is not null
As you see, there is no need for database call whatsoever. How can I prevent it?
When you do $q->answers, Laravel tries to load all of the answers on the question object - regardless of whether they exist or not.
Any time you access a relationship on a model instance, you can either call it like answers() and get a query builder back, or you can call it like answers without parentheses and Laravel will fetch a collection for you based on the relationship.
You can prevent it easily by doing this:
$q = new Question;
$a = new Answer;
And then, when you're ready to save them, associate them with each other. In its simplest form, that looks like this:
$q->save();
$q->answers()->save($answer);
It's doing that because you're assigning it to the Question object. It wants to see if you're adding an extant record reference. All Laravel Eloquent models contain magic methods for properties, and trying to use them as temporary data storage is a really bad idea unless you've defined a property on them ahead of time for that specific purpose.
Just use a regular array instead and then associate them after the models have been prepared.
Documentation on one-to-many relationships:
https://laravel.com/docs/5.1/eloquent-relationships#one-to-many
I am writing my custom update queries like:
$upd = Mage::getSingleton('core/resource')->getConnection('core_write')->query($qry);
But with this, I am basically writing insecure normal sql queries. What can I change in that code above, to use prepared statements?
If you want to bind parameters which is what I think you mean, you can do this as you would normally with PDO and then pass in an array of parameters as your second argument to the query method.
See this similar question:
Using Magento Methods to write Insert Queries with care for SQL Injection