In Laravel 4.2, I have this models
// models ticket.php
class Ticket extends Eloquent {
public function feedback()
{
return $this->hasMany('Feedback');
}
}
// models/feedback.php
class Feedback extends Eloquent {
public function ticket()
{
return $this->belongsTo('Ticket');
}
}
When I do:
$tickets = Ticket::with('feedback')->get();
It returns an array of all tickets with feedback in one array as expected.
Next I want to get one ticket with all related feedback:
$tickets = Ticket::find($id)->with('feedback')->get();
This returns also all tickets with their feedback.
I tried:
$tickets = Ticket::find($id)->with('feedback')->first();
This seems to work but ignores $id and always shows the first row/ticket in the table. $id is not empty, I checked that.
find() already runs a query. Then with()->get() runs another one without the where clause on the id. Do this instead:
$ticket = Ticket::with('feedback')->find($id);
Related
I have the following model with these relationsships:
class Site extends Model
{
use HasFactory;
public function tests() {
return $this->hasMany(Test::class,'requestedUrl','frontpage');
}
public function latestTests() {
return $this->tests()->latest()->take(1);
}
}
I have the following eloquent statement:
$sites = Site::
->with('latestTest')
->orderBy($sort, $direction)
->paginate($size);
But in the result it is only the first returned record that contains latestTest. I assume it's because of take(1) but if I remove that I will choke the server since it seems to be fetching all the tests (100k+ rows) before servering the latest (at least that is what I can see in my queries log).
So how do I get the latest test "the right way"?
I'm trying to get the clan members of the primary tournament, with only a season instance.
I fetch the primary tournament using a query on the tournaments relationship, I then call the clans relationship on the tournament model I just fetched.
Except.. it isn't a model anymore, I'm pretty sure its a query? Or a collection, sorry for my lack of understanding but in a simple explanation, I can no longer access relationships?
I need help in how I can do this with still being able to call clans after querying the tournament.
Here are my models.
class Season extends Model
{
public function clans() {
return $this->belongsToMany(Clan::class);
}
public function tournaments() {
return $this->hasMany('App\Tournament', 'season_id');
}
public function primaryTournament() {
return $this->tournaments->where('is_primary', '1');
}
}
class Tournament extends Model
{
public function clans() {
return $this->belongsToMany(Clan::class);
}
public function season() {
return $this->belongsTo('App\Season', 'season_id');
}
}
I'm trying to achieve this:
$season = Season::all()->last();
$tournament = $season->primaryTournament();
$teams = $tournament->clans; // this is what erorrs
What's stopping me?
Property [clans] does not exist on this collection instance.
try
$teams = $tournament->clans(); // with parenthesis
The problem is apparently in $tournament, which is a collection of Tournament class, and not an instance of a unique one (because it's obtained by ->where('is_primary', '1')),
you can select the first instance by ->first() methode
or loop through $tournament values and access clan property.
Try this $teams = $tournament->clans();
Clans is relation function on your model, you need to put parentheses. This should return a collection of the Clan class.
This is my Report Model
protected $fillable = [
'site_url',
'reciepients',
'monthly_email_date'
];
public function site()
{
return $this->belongsTo('App\Site');
}
This is my Site Model
public function report()
{
return $this->hasMany('App\Report');
}
This is my ReportController
public function showSpecificSite($site_name)
{
$records = DB::table('reports')
->select('email_date','url','recipient')
->whereHas('sites', function($query){
$query->where('site_name',$site_name);
})
->get();
return view('newsite')->with('records',$records)
->with('site_name',$site_name);
}
My Controller is not yet working as well.
The thing is I would like to copy all the three files from sites table to reports table.
Is it possible in insertInto ?
My code on ReportController shows you that I'm selecting data from reports table but I am the one who puts data to reports table to see the output but it is not yet working because of the it cant reach out the value of site_name even though I already put a relationship between the two tables.
You're not actually using Eloquent in your controller you're just using the Query Builder (DB). This will mean that you don't have access to anything from your Eloquent models.
Try:
$records = \App\Report::whereHas('site', function($query) use($site_name) {
$query->where('site_name', $site_name);
})->get(['id', 'email_date', 'url', 'recipient']);
I've added id to the list of columns as I'm pretty sure you'll need that to use whereHas.
NB to use a variable from the parent scope inside a closure you need to pass it in using use().
I have 3 tables: orders, codes, events
I want to be able to pull all events that an order has, but there's an intermediary table that acts as a pivot table. I've been trying to use hasManyThrough and belongsToMany (along with withPivot) without any luck.
Examples:
public function events()
{
return $this->belongsToMany('events'); // tried this, fails
return $this->hasManyThrough('events', 'codes'); // tried this, fails
return $this->hasManyThrough('events', 'codes', 'event_id', 'id'); // tried this, fails
}
Any pointers would be great!
That's a belongsToMany setup. First, the first parameter is the name of the related class. Second, since your pivot table doesn't follow the Laravel naming conventions, you need to specify the name of the pivot table in your relationship definition:
public function events()
{
// first parameter is the name of the related class
// second parameter is pivot table name
return $this->belongsToMany(Event::class, 'codes');
}
With this setup, you can do:
// get an order
$order = Order::first();
// has all the events related to an order
$events = $order->events;
There are many ways to do this. I will show a one you can get it done.
In Order.php model
public function codes(){
return $this->has('App\Http\Code');
}
In Code.php model
public function orders(){
return $this->belongsTo('App\Http\Order');
}
public function events(){
return $this->hasMany('App\Http\Event');
}
In Event.php model
public function codes(){
return $this->belongsTo('App\Http\Code');
}
Then in you Controller, call them to get required data.
In your case you can do it like below:
$orders = Order::with(['codes' => function($q){
$q->with('events');
})->get();
May be you can get them with nested manner(not sure about this because i didn't tried before posting):
$orders = Order::with('codes.events')->get();
put return $orders; in your controller to see the query.
Enjoy!
Now this, from what I can see, should have been simple.
I want to be able to delete multiple records from the database. I have the id's of all the records I wish to delete. I call the resource.destroy route using comma separated list of ids (id is of postgres type uuid), like so:
Request URL:http://foo.app/products/62100dd6-7ecf-4870-aa79-4b132e60c904,c4b369f1-d1ef-4aa2-b4df-b9bc300a4ff5
Request Method:DELETE
On the other end, my controller action looks like so:
public function destroy($id)
{
try {
$ids = explode(",", $id);
$org->products()->find($ids)->delete();
}
catch(...) {
}
}
This gives me the following error:
BadMethodCallException in Macroable.php line 81:
Method delete does not exist.
in Macroable.php line 81
at Collection->__call('delete', array()) in ProductsController.php line 251
at Collection->delete() in ProductsController.php line 251
at ProductsController->destroy('62100dd6-7ecf-4870-aa79-4b132e60c904,c4b369f1-d1ef-4aa2-b4df-b9bc300a4ff5')
I have verified that find() is returning a collection of products matching the specified ids.
What am I missing?
PS:
1. The model Product has several belongsTo relationships with other models.
2. The product.destroy code works fine if I pass it a single id
EDIT
I guess, I'm also trying to understand what the difference between:
$org->products()->find($ids)->delete()
and
$org->products()->whereIn('id', $ids)->get()->delete()
is? From what I see, both find and get are returning Collections
The issue is that you're calling delete() on a Collection, which does not have that method.
You have a couple options here.
Model Events
If you have event listeners for the deleting/deleted model events, you will need to make sure the deletion happens in a way that each model is loaded and then deleted.
In this case, you can use the destroy method on the model that takes a list of ids. It will load a new model for each id, and then call delete() on it. As you mention in a comment, it won't restrict the deletion to only those products in the organization, so you would need to filter out those ids before passing the list into the destroy() method.
public function destroy($id)
{
try {
$ids = explode(",", $id);
// intersect the product ids for the org with those passed in
$orgIds = array_intersect($org->products()->lists('id'), $ids);
// now this will only destroy ids associated with the org
\App\Product::destroy($orgIds);
}
catch(...) {
}
}
If you don't particularly like that approach, you will need to iterate your collection of organization products and call delete() on them individually. You can use a standard foreach, or you can use the each method on the collection:
public function destroy($id)
{
try {
$ids = explode(",", $id);
$org->products()->find($ids)->each(function ($product, $key) {
$product->delete();
});
}
catch(...) {
}
}
No Model Events
Now, if you don't have any model events that you need to listen for, things are a little easier. In this case, you can just call delete() on the query builder, and it will go straight to deleting the records without loading any model objects. So, you get cleaner code with better performance:
public function destroy($id)
{
try {
$ids = explode(",", $id);
// call delete on the query builder (no get())
$org->products()->whereIn('id', $ids)->delete();
}
catch(...) {
}
}
If you create a model of your products, it will help you with these types of operations.
For example:
the model Products.php
<?php
namespace App\Http\Models;
use Illuminate\Database\Eloquent\Model;
class Products extends Model
{
/**
* The table associated with the model.
*
* #var string
*/
protected $table = 'products';
protected $primaryKey = 'id';
protected $fillable = ['name', 'price', 'description'];
}
The controller Products.php
You can use the destroy method and pass one or more primary keys to it as arguments.
<?php
namespace App\Http\Controllers;
use App\Http\Models\Products;
class Products
{
public function destroy($id)
{
try {
$ids = explode(",", $id);
//$ids is a Array with the primary keys
Products::destroy($ids);
}
catch(...) {
}
}
}
You can also use this option to remove query results with a custom parameter
$deletedRows = Products::where('name', 'phones')->delete();
You can check the Laravel documentation https://laravel.com/docs/8.x/eloquent#soft-deleting
When you use the find method, it will find only a single ID. You should use a whereIn to match multiple ids
public function destroy($id)
{
try {
$ids = explode(",", $id);
$org->products()->whereIn('id', $ids)->get()->delete();
}
catch(...) {
}
}
This way you will find all the products with the given IDs and delete them all.
I also faced this problem. Let $orgs contains some records as a collection. Now you can easily delete these records using a loop like this-
foreach($orgs as $org)
{
$org->delete();
}