Join multiples fields from different tables with Laravel Model - laravel

i try return multiples fields from different tables in just one request, example
properties table
-id
-name
-address
rules table
-id
-checkin
-propertyId
i hope a response just like that
[
id=>123,
name=>Name,
address=>Main Street,
checkin:10:00
]
And i would like that this can be used by default in all futures request, all(), first(), get()
Note: I can't use relationship because I need to join two tables in just one

Simple solution set the default with on the property class to include the rule.
protected $with = ['rule'];
To fill you exact spec, add a checkin getter on the property model and use the append property to add it to the serialization.
protected $appends = ['checkin'];
public function getCheckinAttribute()
{
return $this->rule->checkin;
}

Extending the query builder
Laravel Eloquent Query Builder Default Where Condition
Applying logic for all your model queries
Or for the default scope
You could do it this was
https://laraveldaily.com/model-default-ordering-assigning-global-scope/

Related

Laravel eloquent make visible only given attribute in one instance of model

i have instance model from
$model = Model::find(1);
for example this instance always return these attribute (some is from $append):
-id
-name
-countRelation
-description
-created_at
-updated_at
what i want is to only retrive name and description from this instance;
makeVisible only work to show hidden attribute; i don't want use makeHidden because the result of find may change if on model i add new append attribute;
Since you are appending accessors limiting the SELECT statement won't stop those from being appended to the serializied output. You can use setVisible to do this though:
$model->setVisible(['name', 'description']);
Setting what is visible this way will limit the attributes, appends and relationships that are returned in the serialized output of the Model.
You can use select to only retrieve some column in your database, it will not affect append, see the doc for more info Eloquent
$model = Model::find(1);
// to this
$model = Model::select('name', 'description')->find(1);
See Query Builder for more insight about grabbing data from database.
if you retrieve name and description only, then you may use
$model = Model::select(['name', 'description'])->find(1);
You can use select() to select only certain columns in your query.
$model = Model::select('name', 'description')->find(1);
https://laravel.com/docs/8.x/queries#specifying-a-select-clause
You can also get the Model and use functions on the model. If you have a single Model you can use get().
$model = Model::find(1)->get('name', 'description');
If you have a collection you can use ->map->only(). This maps the only function as a callback for each Model in your Collection.
$models = $models->map->only(['name', 'description']);

Eloquent join with where clause

I have problems to build a relationship with eloquent.
I have two models created, Spielplan and Verein. In model Spielplan I have the fields Team_ID and Spiel_ID. In model Verein I have the field V_ID and Name. Now I need to join this two tables about Team_ID = V_ID.
This is my model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Spielplan extends Model
{
protected $table = 'Spielplan';
public function vereinFunction(){
return $this->hasOne('App\Verein', 'V_ID');
}
}
And this is a function in my web route where I want to get Spiel_ID and Name.
Route::get('test', function(){
$spieleT = App\Spielplan::where('Spiel_ID', '=', 30)->get();
foreach($spieleT as $da){
echo $da->Spiel_ID;
echo $da->vereinFunction->Name;
}
});
The first echo works and I get back Spiel_ID but the second echo gives back ErrorException Trying to get property of non-object.
What is wrong with my code?
Try editing this line:
$spieleT = App\Spielplan::with('vereInFunction')->where('Spiel_ID', '=', 30)->get();.
The with() allows you to fetch the association at the time you use get(). After using get(), you're working with a collection, and can't query the database again.
Try specifying the model primary key as a third argument, because if not, Laravel will assume it is named id, which is not the case.
Allow me to suggest you something: I used to name the tables and fields like you do (in the days I use Codeigniter) but since I started using Laravel around three years ago, I follow Laravel convention (which is recommended, but not imposed). I now name the tables in lowercase, (snakecase) plural, table fields also snakecasm lowercase. Models singular, camelcase similar corresponding table, relation function names as related model, being singular if relation is to one, plural if to many, etc. The advantage of this is among other reflected in model relationship declaration, which is a lot simpler and easier to define.
For instance (only as demonstration of stated above),
tables (with relation one to many:
managers (primarykey: id, name, ......)
technicians (primary key: id, foreingkey: manager_id (related table name in singular plus underscore plus id), name, .....)
models:
Manager:
/* relationships */
public function technicians () // see name as related table, plural due to as many relationship)
{
return $this->hasMany(Technician::class); // as naming convention has followed, you don't need to specify any extra parameters;
}
Techician:
/* relationship */
public function manager() // named as related table, singular due to to one relationship
{
$this->belongsToOne(Manager::class); // again, as naming convention has followed, you don't need to specify any extra parameters;
}
Therefore you can do this:
$manager::find(1);
echo $manager->technicians->first()->name,
or
foreach ($manager->technicians as $technician) {
echo $technician->name;
}
as well as:
$technician->manager->name;
Remember, a proper model relationship definition will save a lot of headache along the way, like the one you have
Hope this help in anyway

Laravel Eloquent Model Dynamic Stored Properties from and to a single serialized field

Using Eloquent L5.1
I'd like to not have to define a set of properties for a model. Instead having everything stored within the database as a serialized column.
In other words any property that is set to this model should before save be removed from the object and added to an array to be serialized and then saved in db to a "data" column.
In turn after retrieving the object from db the model should be hydrated with the de-serialized parameters from the data column.
I could override a good number of Illuminate\Database\Eloquent\Model methods to accomplish this and I'm willing to do so, was curious if anyone had an example of this.
An example of this might be for configuration objects that have virtually unlimited unknown values that have multiple itterations for different objects or for different users.
Put these accessors and mutators in your Model:
class YourModel extends Model
{
public function getDataAttribute($data)
{
return collect(json_decode($data,true));
}
public function setDataAttribute($data)
{
$data = (is_array($data) || is_object($data)) ? json_encode($data) : $data;
return $this->attributes['data'] = $data;
}
}
Now when you can pass data as json string, array or object
YourModel::create(['data'=>'{"working":"ok"}']);
YourModel::create(['data'=>['working'=>'ok']]);
It will work in all three cases.

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

Querying ORM with WHERE clause - Eloquent/Laravel 4

The relevant code is at: https://gist.github.com/morganhein/9254678
I have nested resource controllers, which query similarly structured tables in a database.
If I go to www.example.com/v1/jobs/1/departments, I want to query all departments that are associated with job 1. However I cannot figure out how to do that using the ORM.
Help?
I didn't test, but I would suggest you to try something like this:
Route::resource('/v1/jobs/{id}/departments', 'DepartmentController');
Route::resource('/v1/jobs', 'JobController');
After that, your DepartmentController methods will receive one argument, which is job id in your case. It is easier to use find() method if you are using id to retrieve any specific model. When you found the model you can get access to related models.
class DepartmentsController extends BaseController {
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index($jobId)
{
Clockwork::startEvent('List_Default_Departments', 'Starting.');
$positions = Auth::user()->jobs()->find($jobId)->departments;
Clockwork::endEvent('List_Default_Departments', 'Done.');
return Response::json($positions->toArray());
}
}
Note: There is a different between $job->departments() (returns Builder object to create more complex queries) and $job->departments (returns Collection object directly).
Also if you would like to get the list of jobs with all related departments you can always call:
$jobs = Auth::user()->jobs()->with('departments')->get();

Resources