Eloquent ORM query of type Model (not Collection) - laravel

I'm trying to get an object of type Model. I'm using Laravel 4.x with the Eloquent ORM.
If I do this, it doesn't work :
Liveshow::where('slug', $slug)->get();
And if I do this, it works and returns the Model object :
Liveshow::find(Liveshow::where('slug', $slug)->pluck('id'));
I'm wondering if there is a better way to go.
I need the Object to be of type Model because I'm doing this after :
$userLiveshow = new UserLiveshows;
$userLiveshow->user()->associate($user);
$userLiveshow->liveshow()->associate($liveshow);
$userLiveshow->started_at = Carbon::now();
$userLiveshow->watched = 0;
Thanks for your help.
John

If you expect only one model to match your query and therefore don't want a collection as result, just use first():
$liveshow = Liveshow::where('slug', $slug)->first();

Related

Laravel Model hasMany - getting too may results

I'm learning Laravel, so I'm quite new.
I have 2 Models: House and Translation.
My House Model:
use HasFactory;
protected $guarded = ['id'];
public function trans(){
return $this->hasMany(Translation::class);
}
}
My Translation Model:
function House(){
return $this->belongsTo(House::class);
}
}
When I do in the controller something like ($id=2 e.g) :
$house = House::find($id)::with('trans')->get();
I get a result with all houses (there are currently 2 in the DB).
When I just do the query "House::find($id)->get()" it works fine.
What part am I missing?
::with('trans') returns completely new query and forgets everything about your ::find($id)
you need to use load method.
$house = House::find($id);
$house->load('trans');
What happens is, House::find($id) is a method that returns the element by its primary key.
Then, the ::with('trans') gets the result, sees the House class and starts creating a new query builder for the Model.
Finally, the ->get() runs this new query and the end result is what is return for the $house value.
You have two options that will result to what you want to do.
First one is, to find the house entry and then load its relation
$house = House::find($id);
$house->load('trans');
The second option is this:
$house = House::where('id',$id)->with('trans')->first();
The second one is a query builder that results to the first element with id = $id,
and load its relation with translations.
You can check for more details in the laravel documentation. They have a very well-written documentation and the examples help a lot.

Laravel avoid relationship query on laravel after object creation

How to avoid querying relationship after object creation?
$store = new Store();
$store->name = 'Store 1';
$store->save();
return response()->json($store->products());
Laravel is querying products table. I would like to avoid that since I know there is none. This is just an example.
return response()->json([]); is not an option. In real world I really need to use $store->products().
Use the wasRecentlyCreated property of model to identify if the model was inserted during the current request lifecycle.
$data = $store->wasRecentlyCreated ? [] : $store->products();

Adding data to an eloquent collection?

Im getting various data out of my database.
Product::with('users');
I also have toe execute a complex raw query to get back some information. This is returned as an array.
In my method I would like to get products with users and then add on the data from my raw query to this collection, but this data comes back as an array. Something like:
Product::with('users');
Product->extraData = $rawQuery;
How can I add the raw query output to my Product Collection?
By using Eloquent Facade like Product:: you will get an Eloquent Model object as a result or an Eloquent Collection object as a result, including results retrieved via the get method or accessed via a relationship.
Now, if i understand correctly, you need to add a single extraData property to Eloquent Collection model alongside with Collection items? Or you need to add extraData for each Product ?
If you need to add additional property to Eloquent Collection object, maybe it is a good idea to use a Custom Collection. Please read this section: http://laravel.com/docs/5.1/eloquent-collections#custom-collections .
<?php namespace App;
use App\CollectionWithExtraData;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
public function newCollection(array $models = [])
{
return new CollectionWithExtraData($models);
}
}
And maybe your CollectionWithExtraData can have let's say a
public function setExtraData() {
}
or
public $extraData = array();
If you need extraData for each Product Eloquent Model, just create a new attribute within your Eloquent Model, make it public and set your extra data when needed. Make use of setExtraData() method and $extraData property from above

About the laravel eloquent model

The laravel API document: Illuminate\Database\Eloquent\Builder::first() description that:
Model|Builder|null first(array $columns = array('*'))
Execute the query and get the first result.
Parameters
array $columns
Return Value
Model|Builder|null
I can't understand the mean of the return value, In which case it will return Model and In which case it will return Builder?
When you have used eloquent model for retrieving first record it return response in Model, and not sure about builder but when you retrieve records using builder it return builder object.
for example, consider we have states table and we are going to retrieve first record using two different method
1) Query Builder
$state_builder = DB::table("states")->first();
2) Eloquent Model
$state_eloquent = State::first();
you can check the difference between both response, and when no record found it will return null.

Doctrine Query Builder - How to select a many-to-many relationship?

I have a form in Symfony2 that needs to have an entity choice field filled with a collection of Players in a particular tournament. I create the form Type and pass the tournament ID to the query_builder property of the correct field. In the entity repository I have this method:
public function allPlayersInTournamentQuery($tournament_id)
{
$repo = $this->getEntityManager()->getRepository('GameBundle:Tournament');
$tournament = $repo->find($tournament_id);
$players = $tournament->getPlayers();
$playersIds = array();
foreach ($players as $player) {
$playersIds[] = $player->getId();
}
$playersQuery = $this->createQueryBuilder('p')
->in('p.id', $playersIds)
->orderBy('p.real_name', 'ASC');
return $playersQuery;
}
The function in() does not exist in the query builder. I hope the method shows what I am trying to do. Im tying to return the query builder that selects the correct players found in the given tournament.
How can I achieve this?
Thanks!
You can use the helper methods provided by the query builder $playersQuery->expr()->in('p.id', $playersIds)
Your query will be something like that:
$playersQuery = $this->createQueryBuilder('p');
$playersQuery->where($playersQuery->expr()->in('p.id', $playersIds))
->orderBy('p.real_name', 'ASC');
More information about the helper methods here

Resources