I have created method in the Yii2 model Users to get all the replies for the current user
public function getAllRepliesForUsers() { return $this->hasMany(Replies::class, ['user_id' => 'id'])->viaTable('replies_links', ['replies_id' => 'id'])->where(['entity'=>'user']); }
My replies table
My users table
and the final table that links these two tables
Is my method is correct?
Here's the relationship of Users to the Replies. You can use the Model generator of Gii module so you won't get confused by manually typing them.
public function getReplies()
{
return $this->hasMany(Replies::className(), ['id' => 'reply_id'])->viaTable('rply_links', ['user_id' => 'id']);
}
(May I know what do you intend to do with the condition ->where(['entity'=>'user'])?).
Related
In Laravel After recording last row to a DB table, can I safely access same recorded data right after recording it by calling latest() queries? Because transactions by other users may occur at the same time, and it may not really be the last record anymore?
Edit:
For example:
Public function StoreNotif($data){
auth()->user()->Notif()->create(store $data here..)
}
Public function SendNotif(){
$data="123";
$this->StoreNotif($data)
event(new Notification(stored Notif instance?));
}
No, you cannot rely on the database to return the record from your current script.
The ->latest() method will always sort the records with the most recent created_at date first.
https://laravel.com/docs/6.x/queries#ordering-grouping-limit-and-offset
But you haven't provided any code or explanation as to why this is a concern. If you just created a new record, why do you need to query it again? You should already have access to an instance of the model.
EDIT: I've made a few edits to demonstrate how you would pass the model from a controller to an event as referenced in the comments. Please post your code if you want more specific help.
SomeController.php
function store()
{
$model = Model::create([
'some_data' => 1
]);
// fire an event with the newly created model
event(new SomeEvent($model));
dd($model);
}
------------------------
Model {
// ...
attributes: [
'id' => 101,
'some_data' => 1
'created_at' => '2019-10-06 12:48:01',
'updated_at' => '2019-10-06 12:48:01',
]
// ...
}
SomeEvent.php
<?php
namespace App\Events;
use App\Model;
use Illuminate\Queue\SerializesModels;
class SomeEvent
{
use SerializesModels;
public $model;
public function __construct(Model $model)
{
$this->model = $model;
// ...
}
}
EDIT: Per your newly added code, you just need to pass the new model back to the original method. You could do something like this.
Public function StoreNotif($data)
{
// add a return statement
return auth()->user()->Notif()->create(store $data here..);
}
Public function SendNotif()
{
$data="123";
// store the returned data to a variable
$model = $this->StoreNotif($data);
// call the event with the model instance
event(new Notification(model));
}
I'm not sure what 'latest' is but I do know that MySQL uses SELECT LAST_INSERT_ID as the query to get the 'per-connection' id of the last inserted item. Under the covers it's using mysql_insert_id so if you are in a language that supports it, you could use that too.
I want to receive data like this:
categories
----category1
----category2
topProducts
----product1
--------photo1
--------photo2
----product2
--------photo1
--------photo2
I need get all categories and top x products.
Each product has two photos.
How can i do this by using yii2 restful?
Thanks.
the query shold look something like this
Category::find()
->with(['subcategories','topProducts', 'topProducts.images'])
->all();
you can use joinWith if you absolutely want a single query
if you retrieve your data with an ActiveController, you need to specify extraFields to the Category model. (here's a rest-specific usage example - rest of the guide should prove usefull as well)
Category model:
public function extraFields() {
return ['subcategories', 'topProducts'];
}
// product relation
public function getTopProducts(){
return $this->hasMany(Product::className(), ['category_id' => 'id'])
// ->order()->where() // your criterias
->limit(10);
}
// subcategories
public function getChildren(){
return $this->hasMany(Category::className(), ['id' => 'parent_id']);
}
Product model:
public function extraFields() {
return ['iamges'];
}
public function getImages(){
return $this->hasMany(Image::className(), ['product_id' => 'id'])
}
ps. since you haven't posed any code or table structure, all relations in my example are based on standard naiming convention
I am using backpack CRUD package to create my website project in laravel 5.2
I want to establish a relationship between two tables. First table is called customer and second table is called transaction. Each customer has many transaction(1:N relationship).
Customer table record:
ID Name
123456 xyz
Transaction table record:
ID CustomerID
101010 123456
I know that I have to specify the relation in the customer model. But, how can I display the result of the relationship in CRUD ?
You should have relationships on both the Transaction and the Customer models, so you can do $customer->transactions and $transaction->customer:
class Customer extends Model
{
/**
* Get the comments for the blog post.
*/
public function transactions()
{
return $this->hasMany('App\Transactions', 'CustomerID', 'ID');
}
}
and
class Transaction extends Model
{
/**
* Get the comments for the blog post.
*/
public function customer()
{
return $this->belongsTo('App\Customer', 'CustomerID', 'ID');
}
}
Spend some time in the Eloquent Relationships Documentation. It's really important to understand them if you want to be a Laravel developer.
In order to display the relationship in the CRUD, you can then use Backpack's select column type to display it in the table view and select or select2 field types to display it in the add/edit views. Read the CRUD Example Entity to better understand how that works.
First of all when you are creating migrations for both tables, table which contain Foreign Key (FK) must have field like this:
public function up(){
$table->increments('id');
$table->integer('customerID')->unsigned();
}
After that you are need to call next command into console
php artisan migrate
Next is going next commands:
php arisan backpack:crud customers
php arisan backpack:crud transactions
After that you need to define functions in models which returns values from other tables. Customer models need to have next function
public function transactions(){
return $this->hasMany('Transaction');
}
Transaction model must have next function
public function customer() {
return $this->belongsTo('Customer');
}
Next you must add CRUD field in Customer controller to display
transactions in select box.
$this->crud->addField([
'label' => 'Transactions', // Label for HTML form field
'type' => 'select2', // HTML element which displaying transactions
'name' => 'customerID', // Table column which is FK for Customer table
'entity'=> 'customer', // Function (method) in Customer model which return transactions
'attribute' => 'ID', // Column which user see in select box
'model' => 'Transaction' // Model which contain FK
]);
Hope this helps :)
After you built onetomany relationship with transaction, you can get the results.
$customer=Customer::where(['id'=>'123456'])->with('transaction')
->first();
print_r($customer->Name); // gives the customer name
foreach($customer->transaction as $cid)
{
print_r($cid->CustomerID); // gives the customer id
}
Laravel Relationships Documentation is always helpful. Go through it.
here is my table association code:
class UserMastersTable extends Table {
public function initialize(array $config) {
parent::initialize($config);
$this->table('user_masters');
$this->hasOne('person_masters', [
'className' => 'person_masters',
'foreign_key'=>'user_master_id',
'dependent' => true
]);
}
}
when in controller i am using:
$this->UserMasters->get($id);
it results only user_masters table data..
so how can i also get Associated tables data??
Use contain()
Copy-Paste from the manual:
You should use contain() when you want to load the primary model, and
its associated data. While contain() will let you apply additional
conditions to the loaded associations, you cannot constrain the
primary model based on the associations. For more details on the
contain(), look at Eager Loading Associations.
// In a controller or table method.
// As an option to find()
$query = $articles->find('all', ['contain' => ['Authors', 'Comments']]);
// As a method on the query object
$query = $articles->find('all');
$query->contain(['Authors', 'Comments']);
Read the manual before jumping into trial and error driven development! If you would have done one of the tutorials in the manual before this would be clear. So do them now, they'll cover a lot more of the basics.
I try to create a polymorphic association, what is common in Rails but unfortunately not in Yii2. As part of the implementation I need to define the relation:
public function getImages()
{
return $this->hasMany(RecipeImage::className(),
['imageable_id' => 'id', 'imageable_type' => 'Person']);
}
But this doesn't work, because 'Person' is treated as an attribute of the current model, but it is a constant (class name for the polymorphic association).
If I try to use 'andWhere' it adds the condition of course in a WHERE clause instead of the ON clause, causing that only records with existing image returned.
public function getImages()
{
return $this->hasMany(RecipeImage::className(), ['imageable_id' => 'id'])->
andWhere(['imageable_type' => 'Ingredient']);
}
How can I define the relation? There is no andOn method.
In this case you can modify ON condition with andOnCondition method:
public function getImages()
{
return $this->hasMany(RecipeImage::className(), ['imageable_id' => 'id'])
->andOnCondition(['imageable_type' => 'Person']);
}
Official docs:
andOnCondition: