I try to display all location on page like:
{{$item->country()->first()->name}}, {{$item->city()->first()->name}}, {{$item->location()->first()->name}}
As you can see these values from relations country, city, location.
How to create accessor in this case? In which model to write accessor?
I tried this:
public function setTeacherNameAttribute()
{
$this->attributes['teacher_name'] = $this->country->name;
}
let say your $item model called Item so do this in it:
protected $appends = ['address'];
public function getAddressAttribute(){
$address = '';
if (!empty($item->country())) $address .= $item->country()->first()->name;
if (!empty($item->city())) $address .= $item->city()->first()->name;
if (!empty($item->location())) $address .= $item->location()->first()->name;
return $address;
}
then you can use it like this $item->address.
Note: change address to anything else if you already have column with that name.
Whether using relations or just plain models, accessors are always accessed through the final model. In your case in the country, city and location models.
The following method creates an accessor for the name attribute:
public function getNameAttribute($value) {
// do something with value, or not
return $value;
}
Related
I have 3 model in my project and i want to get a query or collection result as i say:
JewelsItem model:
protected $table = 'jewel_items';
public function jewel(){
return $this->belongsTo('App\Models\Jewel');
}
public function sellInvoice(){
return $this->belongsTo(SellInvoice::class,'sell_invoice_id');
}
2.Jewel model:
public function jewelsItems(){
return $this->hasMany('App\Models\JewelsItem');
}
3.sellInvoice model:
protected $table = "sell_invoices";
public function jewelsItems(){
return $this->hasMany(JewelsItem::class,'buy_invoice_id');
}
Query: i want to get all jewelsitems that has no sellInvoice and has jewel name like 'something'.
note: jewel model has a name attribute .and i want to add name of jewel to first of all the collection's items of result.
i know how to get all jewel with name of 'something' :
Jewel::where('name','like','something'.'%')->get();
but i can't get all jewelItem related to it an add name of jewel to first of them.
To look for condition in another relationship you can use whereHas() and whereDoesntHave()
$name = 'something';
$items = JewelsItem::whereHas('jewel', function($query) use ($name) {
$query->where('name', 'LIKE', "%{$name}%");
})
->whereDoesntHave('sellInvoice')
->with('jewel')
->get();
It reads: getting jewel items where jewel has $name in the name field
and doesn't have sell invoice
then add related jewel to the jewel item.
When you want to retrieve the name of the jewel, you can access its property like so.
foreach($items as $item) {
echo $item->jewel->name;
}
I have 2 two tables: one is an admission and the other is a class table. I am saving class id in admission class field of admission table by json_encode method.
My controller
public function store(Request $request)
{
$inputs = $request->all();
$admission = new Admission;
$admission->school_id = Auth::User()->id;
$admission->admission_classes=json_encode($inputs['admission_classes']);
$admission->save();
}
My index function
public function index(Request $request) {
$school_id= Auth::user()->id;
$admissions= Admission::where('school_id',$school_id)->orderBy('id','desc')->paginate(10);
return view('frontend.index',compact('admissions','active_class'));
}
My view
#foreach($admissions as $i => $admission)
{{ $admission->admission_classes }}
#endforeach
I am getting data in this way:-
["1","2","4","5","6","7","8","9"]
But I want to get in this format:
Nursery,Class 1, Class2, Class3 etc
My class controller
class Classes extends Authenticatable
{
use EntrustUserTrait;
use Billable;
use Messagable;
protected $fillable = [
'name','status'
];
}
You need to save integer value in as json array and do the following code
$integerIDs = array_map('intval', $inputs['admission_classes']);
$admission->admission_classes= json_encode($integerIDs);
public function index(Request $request){
$admissions = DB::select('SELECT a.*, GROUP_CONCAT(c.name) as classes FROM academy as a LEFT JOIN class c ON JSON_CONTAINS(a.classes, CAST(c.id as JSON), '$') WHERE a.school_id =2 GROUP BY a.id');
$admissions = $this->arrayPaginator($admissions, $request);
return view('frontend.index',compact('admissions','active_class'));
}
public function arrayPaginator($array, $request)
{
$page = Input::get('page', 1);
$perPage = 10;
$offset = ($page * $perPage) - $perPage;
return new LengthAwarePaginator(array_slice($array, $offset,
$perPage, true), count($array), $perPage, $page,
['path' => $request->url(), 'query' => $request->query()]);
}
I have not checked the code hope this will help u to continue.......
The best way to achieve this would be to have a one-to-many relationship with App\Classes.
However, since you already have something up and running, I would probably do it like this.
First, I would cast admission_classes to an array. This makes sure that admission_classes will always be casted to an array whenever it is fetched. It makes it easier for us to work with it.
protected $casts = [
'admission_classes' => 'array'
];
Finally, while fetching your admission records, you would also need to map over it and hydrate the Classes from its ids. This is how I'd try to achieve it.
$admissions = Admission::where('school_id',$school_id)
->orderBy('id','desc')
->paginate(10)
->map(function($admission) {
return array_map(function($class) {
$class = Classes::find($class);
return isset($class) ? $class->name : '';
}, $admission->admission_classes);
});
You will notice that I wrapped the Classes::find() method into the optional() helper. This is because, in case, a record is not found, it will not fail.
Finally, to print your class names in your blade, you would do something like this:
implode(',', $admission->admission_classes);
I am using Laravel 5.5.13.
I have a model called Thumb. This thumb is related to two things in a many-to-one relationship: Player and Comment.
I currently do things like this:
public function store(Request $request, Entity $entity, Player $player)
{
$thumb = new Thumb($request->all());
$thumb->player_id = $player->id;
$entity->thumbs()->save($thumb);
return response()->json($thumb, 201);
}
We see how I have to set $thumb->player_id AND I don't have to set the entity_id because I am doing $entity->thumbs()->save
Is there a way to do $entityAndPlayer->thumbs()->save? Or is the way I did it above the recommend way?
You cannot use relationships to set 2 foreign columns so they way you showed is the correct one. However you can make it a bit cleaner in my opinion.
Into Thumb model you could add:
public function setPlayer(Player $player)
{
$this->player_id = $player->id;
}
and then instead of:
$thumb->player_id = $player->id;
you could use:
$thumb->setPlayer($player);
Or you could add create setPlayerAttribute method and finally instead of:
$thumb = new Thumb($request->all());
$thumb->player_id = $player->id;
use just:
$thumb = new Thumb($request->all() + ['player' => $player]);
You can't save multiple relationships at once but, for many to one associations you can use the method associate() (Laravel docs) to save using the belongs to part of the relationship, for example:
public function store(Request $request, Entity $entity, Player $player)
{
$thumb = new Thumb($request->all());
$thumb = $thumb->save();
$thumb->player()->associate($player);
$thumb->entity()->associate($entity);
return response()->json($thumb, 201);
}
I have composite primary keys so Laravel's save() method didn't work. Therefore I need to override the save method. For example, my primary key is a composite key consisting of column_a and column_b. Can you give me example how to override the save method and where I put it?
My Primary Key: column_a, column_b
I've tried the followings:
protected function setKeysForSaveQuery(Builder $query)
{
parent::setKeysForSaveQuery($query);
$query->where('locale', '=', $this->locale);
return $query;
}
I found above code, but it causes 500 Internal Server Error even I call a method that only reads value from database. I have set $primaryKey = 'column_a' and 'locale' (inside where) to column_b. I didn't know what $this->locale refers to?
Here is another way I found, but it failed too
protected $secondaryKey = 'column_b';
function newQuery()
{
$query = parent::newQuery();
$query->where($this->secondaryKey, '=', $this->type);
return $query;
}
Again, I didn't know what $this->type refers to.
I have found the solution. In the model, add primaryKey variable and the following function
protected $primaryKey = array('column1','column2');
protected function setKeysForSaveQuery(\Illuminate\Database\Eloquent\Builder $query) {
if (is_array($this->primaryKey)) {
foreach ($this->primaryKey as $pk) {
$query->where($pk, '=', $this->original[$pk]);
}
return $query;
}else{
return parent::setKeysForSaveQuery($query);
}
}
Source: https://github.com/laravel/framework/issues/5517#issuecomment-113655441
You can override it. You can put it in your model, or you can put it in a trait and use this trate in multiple models if you want.
The original save() method is here (line 832), maybe this will help.
How does loadByCode() works? I have been adding a module to my new project and don't know how to use model uses loadByCode method with a given code.
When you look at magento model class it extends Mage_Core_Model_Abstract which intern extends Varien_Object.
The class Mage_Core_Model_Abstract has function like getId(), load(), save(), delete() etc...
Mysql4 resource files are used to perform database queries on tables.
Suppose we have the file Keyur_Test_Model_Mysql4_Test resource file.
<?php
class Keyur_Test_Model_Mysql4_Test extends Mage_Core_Model_Mysql4_Abstract
{
public function _construct()
{
$this->_init('test/test', 'test_id');
}
public function loadByField($field,$value){
$table = $this->getMainTable();
$where = $this->_getReadAdapter()->quoteInto("$field = ?", $value);
$select = $this->_getReadAdapter()->select()->from($table,array('test_id'))->where($where);
$id = $this->_getReadAdapter()->fetchOne($sql);
return $id;
}
}
And here is the model file Keyur_Test_Model_Test
<?php
class Keyur_Test_Model_Test extends Mage_Core_Model_Abstract
{
public function _construct()
{
parent::_construct();
$this->_init('test/test');
}
public function loadByField($field,$value){
$id = $this->getResource()->loadByField($field,$value);
$this->load($id);
}
}
In this file there are many new functions which have been used. Let’s take them one by one. In our model file, we have used this function -
$id = $this->getResource()->loadByField($field,$value);
$this->getResource() function returns the resource model’s object. So we are simply calling the loadyByField($field,$value) function in the resource model.
getTable() function
Now in our Mysql4 file, in the loadByField() function we have used $table = $this->getMainTable(); .This function returns the table name of the current model, i.e the one defined in the class’s constructor. If you want to get table name of another sql table in magento, we need to the getTable() call e.g
$table = $this->getTable(‘newsletter/subscribe’);
_getReadAdapter() function
Next we have:
$where = $this->_getReadAdapter()->quoteInto(“$field = ?”, $value);
Here the first function too see is the $this->_getReadAdapter() function. This function return an object which has function to perform database query, like fetch(), fetchAll(), query(), etc.
_quoteInfo() function
Another function we have used is quoteInto(): This function is used to create our where conditions.
In this the actual value is substituted into the question mark we have written. For e.g $this->_getReadAdapter()->quoteInto(“user_id = ?”, 3); translates to “user_id = 3″.
Another frequently used variation of quoteInfo() is
$where = $this->_getReadAdapter()->quoteInto("$field IN(?)", array(1,2,3));
this translates to “field in (1,2,3)”
Getting deeper into the quoteInto() function: If we have multiple where conditions we can use
$where = $this->_getReadAdapter()->quoteInto("$field = ? AND ", $value).$this->_getReadAdapter()->quoteInto("$field1 = ? OR ", $value1).$this->_getReadAdapter()->quoteInto("$field2 = ?", $value2);
Continuing on the loadByField function in our resource model, next we have
$select = $this->_getReadAdapter()->select()->from($table,array(‘test_id’))->where($where);
Here we have created the select query using the select(), and on that called the from() function.
from() function
The from() function takes many different parameters, if you want to fire a simple select * query, you need to only pass the table name like from($table).
But right now, I wanted to select just a single column that is test_id, so I passed an array with column name to
select. i.e array(‘test_id’).
If we want to select multiple column, we need to array(‘test_id’,’col1’,’col2’).
This will create a sql like “select test_id,col1,col2 from $table”.
But support we want a sql query like “select test_id as id,col1 as column1 from $table” , i would call -
from($table,array('id'=>'test_id','column1'=>'col1'));