Getting unknown empty property after joining relation in search model Yii2 - php

I added
$query->joinWith('projectParticipants');
in search model but got this error:
relation is correct and returns data if I var_dump in view.
Tried as well
->leftJoin('project_participants', 'project_participants.user_id = user_cards.id')
but the same error. :(
With different relations the same problem and in Yii Debugger all queries are correct.
Where I could go wrong?
What is this empty property?
In model relation looks:
public function getProjectParticipants()
{
return $this->hasMany(ProjectParticipants::className(), ['user_id' => 'id']);
}
UPDATED
public function search($params)
{
$query = UserCards::find();
$query->joinWith('projectParticipants');
$dataProvider = new ActiveDataProvider([
'query' => $query,
'pagination' => array('pageSize' => 45),
]);
$this->load($params);
if (!$this->validate()) {
// uncomment the following line if you do not want to any records when validation fails
// $query->where('0=1');
return $dataProvider;
}
$query->andFilterWhere([
'project_participants.proj_id' => $this->projects,
]);
$query->andFilterWhere(['ilike', 'name', $this->fullName ])->orFilterWhere(['like', 'surname', $this->fullName ]);
return $dataProvider;
}

The issue was with primary key - user_cards model was generated from db view where is no pk.
So the solution was to add
public static function primaryKey(){
return array('id');
}
in model.

Related

How to display user name inside product table ? API laravel 8 use eloquent

I have 2 tables:
Table User:
Table Product:
And I have the model relationship:
User model:
public function product() {
return $this->hasMany(Product::class);
}
Product model:
protected $fillable = [
'user_id',
'nama',
'harga',
'deskripsi',
'kategori_id',
'gambar',
];
public function user()
{
return $this->belongsTo(User::class);
}
This is my controller:
class GetProductController extends Controller
{
public function index() {
$product = Product::with(['user'])->get();
if($product) {
return response()->json([
'success' => 1,
'message' => 'success get data',
'products' => collect($product)
]);
} else {
return response()->json([
'success' => 0,
'message' => 'failed get data'
]);
}
}
}
This is my route Api :
Route::get('getproduct', [GetProductController::class, 'index']);
I want use the API for mobile app.. not Api web..
The question is: how to display only column name in table user inside table product?
The output I got is :
What should I change in my controller? Thanks in advance... :) I am new in laravel
Join approach:
class GetProductController extends Controller
{
public function index(){
$product = Product::join('users', 'users.id', 'products.user_id')
->select('users.name as user_name', 'products.*')->get();
if($product){
return response()->json([
'success' => 1,
'message' => 'success get data',
'products' => collect($product) //get() method returns a collection, no need to collect again
]);
} else {
return response()->json([
'success' => 0,
'message' => 'failed get data'
]);
}
}
}
In the past, you could pass a select closure into the query to just get the needed columns:
$product = Product::with(['user' => function($query) {
$query->select('id', 'name');
])
->get();
However, with Laravel 8, you can now eager load the columns quicker
$product = Product::with(['user:id,name'])->get();
Pay attention to the note in the documents
When using this feature, you should always include the id column and any relevant foreign key columns in the list of columns you wish to retrieve.
Add Product Model
public function getUser()
{
return $this->hasOne('App\Models\User', 'id', 'user_id');
}
Controller
$product = Product::with(['getUser'])->get();
View
#foreach ($product as $item)
{{ $item->getUser->name }}
#endforeach

Laravel - Eloquent attach() not working for models

TL;DR
Trying to get three models to interact using eloquent for a rest api.
User - belongsToMany(pulls)
Pull - belongsToMany(user) && belongsToMany(boxes)
Box - belongsToMany(pulls)
The pull_user table is working perfectly, I can just attach a user after I save a pull. Saving a box works fine but the attach doesn't work/enter anything into the pivot table (I get no errors though).
The Problem
I can't get a pivot table that associates two of my models together to attach() after a save. I have the three models listed above, the pivot is working for pull_user but not for pull_box even though the save for box is working perfectly. I am able to save a box without an error but the association just never occurs (no error).
The Code
pull_box.php
class PullBox extends Migration
{
public function up()
{
Schema::create('pull_box', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->integer('pull_id');
$table->integer('box_id');
});
}
public function down()
{
Schema::dropIfExists('pull_box');
}
}
Pull.php
class Pull extends Model
{
protected $fillable = ['from', 'to', 'runit_id', 'start_time', 'end_time', 'box_count', 'pull_status', 'audit_status', 'status', 'total_quantity', 'accuracy'];
public function users(){
return $this->belongsToMany('App\User');
}
public function boxes(){
return $this->belongsToMany('App\Box');
}
}
Box.php
class Box extends Model
{
protected $fillable = ['user_id','from', 'to', 'runit_id', 'start_time', 'end_time', 'pull_id', 'total_quantity', 'status', 'accuracy'];
public function pulls(){
return $this->belongsToMany('App\Pull');
}
}
BoxController.php
public function store(Request $request)
{
$this->validate($request, [
'user_id' => 'required|integer',
...
]);
$user_id = $request->input('user_id');
...
$box = new Box([
'user_id' => $user_id,
...
]);
$pull = Pull::whereId($pull_id)->first();
if($box->save()){
$pull->boxes()->attach($box->id);
$box->view_box = [
'href' => 'api/v1/box/' . $box->id,
'method' => 'GET'
];
$message = [
'msg' => 'Box created',
'box' => $box,
'pull' => $pull_id
];
return response()->json($message, 201);
}
$response = [
'msg' => 'Box creation error, contact supervisor',
];
return response()->json($response, 404);
}
The Solution
I need to know how I can get this association working. I am going to need to add a new layer in under the pull for Item, but I don't want to move one before I solve this. I think that my problem has to stem from a syntactical/logical error on my part but I can't see it. There are a bunch of questions on SO that are very close to giving me a solution, but after reading them I wasn't able to solve my problem.
Any help is appreciated.
Try renaming your pull_box table to box_pull, pivot tables on laravel must be in alphabetical order. If you want to use custom name on pivot table you have to extends your pivot, for example:
<?php
namespace App;
use Illuminate\Database\Eloquent\Relations\Pivot;
class PullBox extends Pivot
{
protected $table = 'pull_box';
}
And your many to many relationships:
class Pull extends Model
{
protected $fillable = ['from', 'to', 'runit_id', 'start_time', 'end_time', 'box_count', 'pull_status', 'audit_status', 'status', 'total_quantity', 'accuracy'];
public function users(){
return $this->belongsToMany('App\User');
}
public function boxes(){
return $this->belongsToMany('App\Box')->using('App\PullBox');
}
}
class Box extends Model
{
protected $fillable = ['user_id','from', 'to', 'runit_id', 'start_time', 'end_time', 'pull_id', 'total_quantity', 'status', 'accuracy'];
public function pulls(){
return $this->belongsToMany('App\Pull')->using('App\PullBox');
}
}

Yii2 restful api without page limit

Am using yii\rest\ActiveController without pagelimit
This is how am doing it
<?php
namespace rest\modules\v1\controllers;
use yii\rest\ActiveController;
class CompanyController extends ActiveController
{
public $modelClass = 'frontend\models\TblDeliveredCompanies';
}
The above returns only 20 records how do i improve it to return all
You can override prepareDataProvider() inside the controller to return a custom data provider from index action:
public function prepareDataProvider()
{
$query = \frontend\models\TblDeliveredCompanies::find();
$dataProvider = new \yii\data\ActiveDataProvider([
'query' => $query,
'pagination' => ['pageSize' => 0]
]);
return $dataProvider;
}
Check documentation at http://www.yiiframework.com/doc-2.0/guide-rest-controllers.html#extending-active-controller
The limit for 20 could be related to the default pagination values for dataProvider so in your controller/action or in the model where the $dataProvider is create you shoul redefine the function assign the pagination as false
$dataProvider->pagination = false;
or
$dataProvider = new ActiveDataProvider([
'query' => $your_query,
'pagination' => false,
]);
Check the code in the model class 'TblDeliveredCompanies' present at 'frontend\models\TblDeliveredCompanies' it must have the SQL query containing the limit 20, change it to 'SELECT * from yourtbl where %yourcond%'
Other solution
public function actions()
{
$actions = parent::actions();
$actions['index']['pagination'] = false;
return $actions;
}

Laravel Eloquent Foreign Key Relation

I have question about Laravel Eloquent. I created few tables and models, ~like this:
Trip
id
name
user
User
id
email
Message
id
content
trip
user
How can I get all message for single user with all foreign keys? You know, all data from this tables. Like this:
[
1 => [
'content',
'trip' => [
'name'
],
'user' => [
'email'
]
]
]
It's possible, to get in easy way all data?
My models:
// Message.php:
public function user()
{
return $this->belongsTo('App\User');
}
public function trip()
{
return $this->belongsTo('App\Trip');
}
// Trip.php:
public function user()
{
return $this->belongsTo('App\User');
}
// User.php:
public function trips()
{
return $this->hasMany('App\Trip');
}
public function messages()
{
return $this->hasMany('App\Message');
}
My Code
dd(
User::with([
'sent',
'recipient'
])->find(2)->toArray()
);
And what I want to get:
screen
I believe you are looking for the load method.
Lets say you have a user
$user->load('messages'); // var_dump($user);
If you vardump your user object you will see the related messages were loaded.
Use eager loading to achieve that.
Try this:
$users = User::with([
'messages.trip',
])->get();
dd($users);
Ref: https://laravel.com/docs/5.3/eloquent-relationships#eager-loading

Yii2 dataprovider with manytomany relation

I try to build a grid view with many-to-many relations. So I need a query for the ActiveDataProvider .
I have a table 'ressource', a table 'type' and between them a table 'historique'.
I have the good relation in my models but I don't know how to create the dataProvider.
In my model Ressource :
public function getHistorique()
{
return $this->hasMany(Historique::className(), ['idType' => 'idType']);
}
public function getType()
{
return $this->hasMany(Type::className(), ['idType' => 'idType'])
->viaTable(Historique::className(), ['idRessource' => 'idRessource']);
}
In my model Historique :
public function getType()
{
return $this->hasOne(Type::className(), ['idType' => 'idType']);
}
public function getRessource()
{
return $this->hasOne(Ressource::className(), ['idRessource' => 'idRessource']);
}
and finally in my model Type :
public function getHistorique()
{
return $this->hasMany(Historique::className(), ['idType' => 'idType']);
}
public function getRessource()
{
return $this->hasMany(Ressource::className(), ['idRessource' => 'idRessource'])
->viaTable(Historique::className(), ['idType' => 'idType']);
}
So in the Controller (in fact my ModelSearch), I want to have ressources with type from the table historique. I don't know what I have to add after
Ressource::find();
I think you use RessourceSearch()->search() method. So inside it you have something like this:
$query = Ressource::find();
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
if (!($this->load($params) && $this->validate())) {
return $dataProvider;
}
// Here is list of searchable fields of your model.
$query->andFilterWhere(['like', 'username', $this->username])
->andFilterWhere(['like', 'auth_key', $this->auth_key])
return $dataProvider;
So, basically, you need to add additional Where you your query and force to join relation table. You can do that using joinWith method to join additional relation and andFilterWhere using table.field notation for adding filter parameters. For example:
$query = Ressource::find();
$query->joinWith(['historique', 'type']);
$query->andFilterWhere(['like', 'type.type', $this->type]);
$query->andFilterWhere(['like', 'historique.historique_field', $this->historique_field]);
Also do not forget to add rules for additional filters in your search model. For example above, you should add to your rules() array something like that:
public function rules()
{
return [
// here add attributes rules from Ressource model
[['historique_field', 'type'], 'safe'],
];
}
You can use any additional validation rules for that fields

Categories