How to convert MySQL query to Eloquent Relationships? - relationship

I don't really know what words or terms I would search. I have also read the documentation in laravel 5.7, https://laravel.com/docs/5.7/eloquent-relationships#many-to-many-polymorphic-relations.
But still I couldn't find the thing that I want.
The result that I am expecting is this in MySQL:
SELECT id as product_id, (SELECT name FROM products WHERE id = transactions.product_id), created_at FROM transactions WHERE user_id = 1
This is the result of the mysql query:
I already have a model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Transactions extends Model
{
protected $table = 'transactions';
protected $fillable = [
'user_id', 'product_id'
];
public function product()
{
return $this->hasOne('App\Products')->select('name');
}
}
?>
Then in my controller:
public function transactions()
{
$transactions = new Transactions::where('user_id',Auth::id())->product;
return view('transactions', ['transactions' => $transactions]);
}

You should use belongsTo() relation. Transaction belongs to one product, product has many transactions.
Also, you can (or better should) rename model to a singlular. Then you don't need to use protected $table.
It is not necessarily to select only name.
Transaction model:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Transaction extends Model
{
protected $fillable = ['user_id', 'product_id'];
public function product()
{
return $this->belongsTo('App\Product');
}
}
Controller:
public function transactions()
{
$transactions = Transaction::with('product')
->where('user_id', Auth::id())
->get();
return view('transactions', ['transactions' => $transactions]);
}
View:
#foreach($transactions as $transaction)
echo $transaction->product_id; //attribute product_id of transaction
echo $transaction->product->id; //attribute id of product
echo $transaction->product->name; //attribute name of product
#endforeach

Related

Jessneggers / Laravel MongoDB whereRaw lookup not working

I migrated my database from Sql Server to MongoDB
I want to Join existing customer Table with contact Table .
Customer have multiple contacts . I tried whereRaw lookup
customer collection
{
"_id": 77,
"custid": 93
}
Contact Collection
{"_id":77,"contactid":77,"custid":93,"firstname":"Christy ","lastname":"Lambright" }
{"_id":79,"contactid":79, "custid":93,"firstname":"Marlys ","lastname":"Barry" }
Customer Modal
class custt extends Model
{
use Notifiable;
protected $primaryKey = 'id';
}
Contact Modal
class contact extends Model
{
use Notifiable;
protected $primaryKey = 'id';
In Controller
$cnt = DB::collection("custts")->raw(function($collection)
{
$more_where = [];
$more_where[]['$lookup'] = array(
'from' => 'contacts',
'localField' => 'custid',
'foreignField' => 'custid',
'as' => 'country',
);
return $collection->aggregate($more_where);
});
Error comes --
Empty Results
I tried Lots of options for hasMany and belongstoMany . Not working ...
please suggest
ok , finally found it working
source - https://github.com/jenssegers/laravel-mongodb/issues/841
$cnt = custt::raw(function($collection)
{
return $collection->aggregate(
[[
'$lookup' => [
'as'=>'info',
'from'=>'contacts',
'foreignField'=>'custid',
'localField'=>'custid'
]
]]
);
});

Sorty by calculated field with active record yii2

I have threads and messages on thread
I want to return all threads with the last message time, so I added a new field like this on thread model
public function fields()
{
$fields= ['idThread', 'idUser', 'title', 'unread', 'username','lastMesageTime'];
return $fields;
}
now with this method I get the calculated value lastMessageTime
public function getLastMessageTime()
{
return $this->hasMany(Messages::className(), ['idThread' => 'idThread'])
->select('time')->orderBy('time DESC')->limit(1)->scalar();
}
on my index method using active record like this
return Thread::find()->select('idThread, title, idUser')->all();
this works and I get lastMessageTime with the right value, but I want to order by so I can get the thread with the most recent lastMessageTime the first one, I tried with the following code
public function scopes() {
return array(
'byOrden' => array('order' => 'lastTimeMessage DESC'),
);
}
any idea?
Edit:
this workaround works, but I think this is not a good way because I'm not using active record so fields like username that I had defined on Thread model I had to fetch it again
$query = (new \yii\db\Query());
$query->select('*, (SELECT max(time) as lastMessageTime from messages where messages.idThread = thread.idThread ) lastMessageTime,
(SELECT name from users where users.idUser = thread.idUser) as name ')
->from('threads')
->where(['idUser'=>$idUser])
->orderBy('lastMessageTime DESC');
$rows = $query->all();
return $rows;
You can define extra fields as model properties, then override find method to load data for them.
class Thread extends \yii\db\ActiveRecord
{
public $lastMessageTime;
public static function find()
{
$q = parent::find()
->select('*')
->addSelect(
new \yii\db\Expression(
'(SELECT max(time) FROM messages WHERE messages.idThread = thread.idThread) AS lastMessageTime'
);
return $q;
}
}
Then you can load and order models like this:
$rows = Thread::find()->orderBy(['lastMessageTime' => SORT_DESC])->all();

How to insert into a table based on an Eloquent relationship an array of foreign keys

I have two models TeamMember and ProjectRequest.
A TeamMember can have one ProjectRequest, that is why I created the following Eloquent relationship on TeamMember:
class TeamMember extends Model {
//
protected $table = 'team_members';
protected $fillable = ['project_request_id'];
// Relations
public function projectTeam() {
return $this->hasOne('\App\Models\ProjectRequest', 'project_request_id');
}
}
In my Controller I want to query both tables, however it returns the failure message.
What is important to know is that $request->projectTeam is an array of emails, looking like this:
array:2 [
0 => "mv#something.com"
1 => "as#something.com"
]
Meaning that I need to bulk insert into team_members table the project_request_ id for each team member where the emails are in the array.
How can I do that in the right way? The following is my attempt:
public function createProjectTeam(Request $request){
try {
$title = $request->projectTitle;
$TeamMember = $request->projectTeam;
$projectRequest = ProjectRequest::create(['project_title' => $title]);
$projectRequestId = $projectRequest->id;
$projectTeam = $this->teamMembers->projectTeam()->create(['project_request_id'=> $projectRequestId])->where('email', $TeamMember);
//$projectTeam = TeamMember::createMany(['project_request_id' => $projectRequestId])->where($TeamMember);
//dd($projectTeam);
return $projectRequest.$projectTeam;
} catch(\Exception $e){
return ['success' => false, 'message' => 'project team creation failed'];
}
}
There are a few things you can do.
Eloquent offers a whereIn() method which allows you to query where a field equals one or more in a specified array.
Secondly, you can use the update() method to update all qualifying team members with the project_request_id:
public function createProjectTeam(Request $request)
{
try {
$projectRequest = ProjectRequest::create(['project_title' => $request->projectTitle]);
TeamMember::whereIn('email', $request->projectTeam)
->update([
'project_request_id' => $projectRequest->id
]);
return [
'success' => true,
'team_members' => $request->projectTeam
];
} catch(\Exception $e) {
return [
'success' => false,
'message' => 'project team creation failed'
];
}
}
I hope this helps.

Laravel UUID from SQL Server Database Errors

I am having issues with a Laravel application using an existing database where MS SQL UUIDs are used. My application has a customer:
class Customer extends Model
{
protected $table = 'ERP.Customer';
public $timestamps = false;
protected $primaryKey = 'CustID';
protected $keyType = 'string';
protected $fillable = [
'CustID',
'SysRowID',
'CustNum',
'LegalName',
'ValidPayer',
'TerritoryID',
'Address1',
'Address2',
'Address3',
'City',
'State',
'Zip',
'Country',
'SalesRepCode',
'CurrencyCode',
'TermsCode',
'CreditHold',
'FaxNum',
'PhoneNum',
'CustomerType'
];
public function SalesTer()
{
return $this->belongsTo(SalesTer::class,'TerritoryID', 'TerritoryID');
}
public function Shipments()
{
return $this->hasMany(Shipment::class, 'CustNum', 'CustNum');
}
public function Equipments()
{
return $this->hasMany(Equipment::class,'CustNum', 'CustNum');
}
public function Customer_UD()
{
return $this->hasOne(Customer_UD::class,'ForeignSysRowID', 'SysRowID');
}
}
Which (in the native ERP application) has a UD table which end users can used to customise the Customer entity:
class Customer_UD extends Model
{
protected $table = 'ERP.Customer_UD';
protected $primaryKey = 'ForeignSysRowID';
public $timestamps = false;
public $incrementing = false;
protected $keyType = 'string';
protected $fillable = [
'ForeignSysRowID',
'MakesCans_c',
'MakesEnds_c',
'Industry_c'
];
public function Customer()
{
return $this->hasOne(Customer::class,'SysRowID', 'ForeignSysRowID');
}
}
CustomerController:
public function show($CustID)
{
if(Customer::find($CustID))
{
$Customer = Customer::find($CustID);
$Customer_UD = $Customer->Customer_UD()
->get();
$Shipments = $Customer->Shipments()
->where('Voided', '0')
->get();
$Equipments = $Customer->Equipments()
->with('Part') // load the Part too in a single query
->where('SNStatus', 'SHIPPED')
->get();
return view('Customer.show', ['NoCust' => '0'],
compact('Equipments', 'Customer','Shipments', 'Parts', 'Customer_UD'));
}
else
{
return view('Customer.show', ['NoCust' => '1']);
}
}
The Customer has (for whatever reason) a CustID (which people use to refer to the customer) a CustNum (which is not used outside of the database and a SysRowID. The SysRowID is used to link the Customer table with the Customer_UD table.
An example row from Customer_UD is:
My issue is that when trying to return the UD fields along with the Customer fields I get an error:
SQLSTATE[HY000]: General error: 20018 Incorrect syntax near ''.
[20018] (severity 15) [select * from [ERP].[Customer_UD] where [ERP].
[Customer_UD].[ForeignSysRowID] = '���_�X�O�Q׊3�^w' and [ERP].
[Customer_UD].[ForeignSysRowID] is not null]
I thought it was odd, so I commended out the Customer_UD lines in the CustomerController and simply tried to display the Customer UUID field in the show blade:
SysRowID: {{$Customer->SysRowID}}
I get nothing, no errors but no data. I created a controller and index blade for the Customer_UD model and can display all of the Customer_UD database fields apart from the UUID field.
I don't actually want to display the UUID fields - but do need to use them to build the relationships. Can anyone help point me in the right direction?
I found that adding:
'options' => [
PDO::DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER => true,
],
To the database configuration in config\database.php resolved the issue.

CakePHP 3 Entity default field value

I have a entity named "View" and this entity has a attribute named "datetime" (the name of entity and field are not relevant).
I would like to set a default value to it inside CakePHP instead of defining it on database.
On my entity class I defined:
namespace App\Model\Entity;
use Cake\ORM\Entity;
use Cake\I18n\Time;
class View extends Entity
{
protected $_accessible = [
'*' => true,
'id' => false,
];
protected function _getDatetime($datetime)
{
return Time::now();
}
}
And when I try to save it in a method of Model Table class (ViewTable):
public function registerView(User $user){
$view = $this->newEntity();
$view->user = $user;
$this->save($view);
}
Nothing happens, my "datetime" field is saved as '0000-00-00 00:00:00'.
My question is: How can I set a default value for a entity so when I call $this->newEntity() the field comes with this default value?
I would do it in ViewsTable::beforeSave
beforeSave($event, $entity, $options)
{
if(!$entity->isNew() && !$entity->datetime)
{
$entity->datetime = Time::now();
}
return true;
}

Resources