Select a specific column from laravel eloquent model - php

How do I select the column Field from the FormFactor model? I want to select only one column from the recordset.
public function ApiFormFactorDetails()
{
return $this->belongsTo('App\Model\FormFactor','formfactor_id')->select('name');
}

Eloquent models share pretty much the same syntax as the query builder. From the query builder documentation:
If you don't even need an entire row, you may extract a single value from a record using the value method. This method will return the value of the column directly:
$email = DB::table('users')->where('name', 'John')->value('email');
In your case:
public function ApiFormFactorDetails()
{
return $this->belongsTo('App\Model\FormFactor','formfactor_id')->value('name');
}

Actually, the way you are doing should work fine. You can keep the code in the function:
public function ApiFormFactorDetails()
{
return $this->belongsTo('App\Model\FormFactor','formfactor_id')->select('name');
}
And then, call it like this:
$object->ApiFormFactorDetails;
The return will have only name as attribute.

Related

Copying Data from table to another table and applying one to many relationship

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().

Laravel: Is there a way to remove DB query clauses?

Let us say my shop model has a products relationship as follows:
// shop model class
public function products()
{
return $this->hasMany(Model\Product::class)
->orderBy('name');
}
Is there a way that client code, such as my controller, can remove the orderBy() clause?
Yes there is a way to do that, say in your controller you want to fetch some of the products
\App\Products::latest()->getQuery();
getQuery() is a query builder method that contains all the groupings, selects, orders, wheres, joins etc for the query that you are accessing or trying to build.
So you could reset the ordering like so:
\App\Products::latest()->getQuery()->orders= [];
since in Laravel eloquent query builder selects, grouping, ordering are stored as arrays of key values you simply set that to an empty array to reset al the previous states.
For example grouping:
\App\Products::latest()->getQuery()->groupings =[];
For reset
$qry->getQuery()->groups = [];
$qry->getQuery()->wheres = [];
For remove last where or group by column
array_pop($qry->getQuery()->groups);
array_pop($qry->getQuery()->wheres);
public function products($isOrder = true)
{
$hasMany = $this->hasMany(Model\Product::class);
return ($idOrder) ? $hasMany->orderBy('name') : $hasMany;
}
but you can use this only having $shop instance;
$shop->products(false)->...; // your query to get result

get field value from eloquent relationship

I have this relationship on eloquent
public function Manufacturer() {
return $this->hasOne('App\Models\ManufacturerModel', 'id')->select('name');
}
And this returns correctly the manufacturer name:
{"id":1,"serialnumber":"123_1","buydate":"2018-01-26 00:00:00","offservice":null,"deleted":"0","manufacturer":{"name":"HP"}}
I want to retrieve the name not as JSON object but as a string
{"id":1,"serialnumber":"123_1","buydate":"2018-01-26 00:00:00","offservice":null,"deleted":"0","manufacturer":"HP"}
The best way to define the relationship is:
public function Manufacturer() {
return $this->hasOne('App\Models\ManufacturerModel', 'id');
}
Then you can get the manufacturer name this way:
$your_object->manufacturer->name;
Or adding a wrapper method:
public function ManufacturerName() {
return $this->manufacturer->name;
}
Notice that when you refer to the relationship without parenthesis the query is executed and what you are accessing is the result. If you don't want the entire record to be queried you can do this:
public function ManufacturerName() {
return $this->manufacturer()->select('name')->get()->name;
}
By accessing the relationship with parenthesis you are getting the relationship definition and you can modify it before executing the query.
Not directly but you can achieve the functionality using a little bit trick of php, for example, if you would like to use it in string context as given below:
// {{ $someModel->manufacturer }}
echo $someModel->manufacturer; // or echo Manufacturer::find(1);
Then you can do it using the __toString magic method in Manufacturer model as given below:
public function __toString()
{
return $this->name;
}
In this case, even on json_encode($manufacturer) will give you just name so why don't you just use $model->manufacturer->name;

Laravel get Eloquent relation by same name as its attribute

I have database tables like this:
shoot: id, name, programme
programme: id, name
The eloquent relationship in the shoot is defined like this:
public function programme() {
return $this->belongsTo('App\Programme', 'programme', 'id');
}
When using dd(), I can see this is working correctly:
dd(Shoot:where('id','=',1)->with('programme')->first());
// prints the object with programme listed under the relationship
However when I eager-load the shoot and attempt to get the programme object, I retrieve the shoot attribute "programme" instead. E.g.:
$shoot = Shoot:where('id','=',1)->with('programme')->first();
echo $shoot->programme; // returns 1, not App\Programme object.
Is there a solution to this without having to rewrite masses of the codebase?
You shouldn't use the same name for the both relationship and column name, else you'll receive always the column name so try to edit one of them, I think the easiest one here is the relationship name :
public function programmeObj() {
return $this->belongsTo('App\Programme', 'programme', 'id');
}
Then call it as :
echo $shoot->programmeObj;
NOTE : But if you want to follow conventions you should replace the name attribute by programme_id so :
public function programme() {
return $this->belongsTo('App\Programme', 'programme_id', 'id');
}
Hope this helps.
To achieve what you after you will need to do the following:
$shoot = Shoot:where('id','=',1)->with('programme')->first();
$variable = $shoot->programme; // returns 1
$obj = $page->getRelationValue('programme') // returns App\Programme object.
This will returns always the column in your database if it exists, that's ID 1.
When you call dump($shoot); you should get the array with all attributes. But when you run the following you should get the name:
Your model:
public function programmeData() {
return $this->belongsTo('App\Programme', 'programme', 'id');
}
And your controller:
$shoot = Shoot:where('id','=',1)->first();
return $shoot->programmeData->name; // returns name
Hope this works!

Laravel orWhere not working with hasMany

I have following code:
class Ingredient extends Eloquent
{
public function units()
{
return $this->hasMany('IngredientUnit')
->orWhere('ingredient_id', '=', -1);
}
}
I would expect query like:
select * from `ingredient_units` where `ingredient_id` = '-1' OR `ingredient_units`.`ingredient_id` in (...)
instead I get:
select * from `ingredient_units` where `ingredient_id` = '-1' and `ingredient_units`.`ingredient_id` in (...)
Why it use AND operator instead OR, when I used orWhere()?
Update 1:
And second question is how can I get a query which I was expected?
Update 2:
I want to use eagerloading for that
When you fetch a collection of objects through a relation on a model, the relation constraint is always included, hence the AND. And it makes perfect sense, otherwise you could get $model->units objects that are not related to $model.
I can see what you're trying to achieve here - fetch units related to that $model together with units not related to any models. You can achieve it by adding the following method to your model:
public function getAllUnits() {
$genericUnits = IngredientUnit::whereIngredientId(-1);
return $this->units()->union($genericUnits)->get();
}
OR
public function getAllUnits() {
return IngredientUnit::whereIn('ingredient_id', [$this->id, -1])->get();
}
The only issue here is that it won't be used by eager loading logic but would result in separate query for every model for which you want to return units. But if you always fetch that for a single model anyway, it won't be a problem.
One suggestion: store NULL in ingredient_id instead of -1. This way you'll be able to make use of foreign key constraints.

Categories