Yii 2, active record, with - activerecord

how can i get a set of data, based on condition in relation table?
In Yii 1 i could use with() and 'on' statement. This doesn't work in Yii 2, or i can't find any good example.
For example in Yii 1 i could write this:
$criteria = new CDbCriteria();
$criteria->with = array('works'=>array('on' => 'works.user_id=t.id AND (works.work_id=$SOMEVALUE OR ...)'));
I tried something like this (userRight is my relation):
Foo::find()->with(['userRight'=>['on'=>['user_r'=>$this->id]]]);
Is there any solution in Yii 2?

From official example:
$orders = Order::find()->innerJoinWith([
'customer' => function ($query) {
$query->where('customer.created_at > ' . (time() - 24 * 3600))
->onCondition(['category_id' => 1]);
}
])->all();
See this link

if in your table have a relation and using gii to generate models, controller and view it will make function for the relation.
if no you can make function to declare relation 2 tables in model
public function getWorks()
{
return $this->hasOne(Works::className(), ['id' => 'works_id']);
}
if hasMany just flip id.
and call the function
Foo::find()->joinWith('works')->all();

Related

Data filtering query in Laravel many-to-many relationship

there is a table named products and another table named features that have a many-to-many relationship.
I want to write a query that returns products that, for example, have features 2, 3, and 11 at the same time. Now I wrote the following command
$params = [2,3,11];
$products = Product::with('photos')
->whereHas('features', function ($q) use ($params) {
$q->whereIn('feature_id' , $params);
})
->whereIn('category_id', $ids)
->orderByRaw($sortBy)
->paginate($paginate);
when I use whereIn, it works in the form of OR and shows me products that either have the feature 2 or 3 or 11..
I want it to be in the form of AND, which means it will only find products that have all the desired features together
$products = Product::with('photos')
->whereHas('features', function ($q) use ($params) {
foreach($params as $p) {
$q->where('feature_id', $p);
}
})
->whereIn('category_id', $ids)
->orderByRaw($sortBy)
->paginate($paginate);
and this query that I wrote returns empty data.

How can I use laravel db query ->update() method in if statement

I want to check something in if, and if that condition is true I want to update the record that was fetched before.
$resultQuery = DB::table('cards')->where('api_id', $card->id)->first();
if (this condition will pass I want to update this record) {
$resultQuery->update(array('price_usd' => $card->prices->usd));
}
When I use the ->update() like this, I get an error:
Call to undefined method stdClass::update();
How can I do this ?
The first() function on laravel query builder returns a stdClass meaning Standard Class.
There is no function called update() in stdClass in php. You have called update() on stdClass, and that causes the error.
There are several ways to achieve your goal.
Use Laravel query builder update() function.
$resultQuery = DB::table('cards')->where('api_id', $card->id)->first();
if (your_condition) {
Db::table('cards')
->where('api_id', $card->id)
->update([
'price_usd' => $card->prices->usd
]);
}
If you don't want to fetch the card data, don't call first()
$resultQuery = DB::table('cards')->where('api_id', $card->id);
if (your_condition) {
$resultQuery
->update([
'price_usd' => $card->prices->usd
]);
}
Use Eloquent models (Laravel's preferred way)
Create an Eloquent model for Cards (if you have not done already).
public class Card extends Model
{
}
Use eloquent query builder to fetch data. And use model update() function to update data.
$resultingCard = Card::where('api_id', $card->id)->first();
if (your_condition) {
$resultingCard->update([
'price_usd' => $card->prices->usd,
]);
}
If you're using model
You can add in card controller
$card = Card::where('api_id', $card->id)->first();
if (someConditional)
{
// Use card properties, number is a example.
$card->number = 10
// This line update this card.
$card->save();
}
You can learn more about eloquent here.
Something like this:
$resultQuery = DB::table('cards')->where('api_id', $card->id);
if ($resultQuery->count()) {
$object = $resultQuery->first();
$object->price_usd = $card->prices->usd;
$object->save();
}
Or look for an alternative solutions here: Eloquent ->first() if ->exists()

Laravel firstOrCreate without Eloquent

Eloquent has a firstOrCreate method which gets a model based on a condition, or creates it if it doesn't exist.
Is there any equivalent method in Laravel's query builder (i.e. NOT in Eloquent)? For example:
$row = DB::table('users')->where('user_id', 5)->firstOrCreate('name' => 'Peter', 'last_name' => 'Pan');
That would try to get a row from users with 'user_id'==5. If it doesn't exist, it would insert a row with that id number, plus the other mentioned fields.
EDIT: I'm not trying to apply my question with users. I used users as an example to make as clear as possible what I'm looking for.
updateOrInsert function with empty values give me the result like firstOrCreate
Nope, Laravel firstOrCreate is function, that says next:
public function firstOrCreate(array $attributes, array $values = [])
{
if (! is_null($instance = $this->where($attributes)->first())) {
return $instance;
}
return tap($this->newModelInstance($attributes + $values), function ($instance) {
$instance->save();
});
}
But you can add it with query micro:
DB::query()->macro('firstOrCreate', function (array $attributes, array $values = [])
{
if ($record = $this->first()) {
// return model instance
}
// create model instance
});
So than you will be able to call it same way you do with Eloquent.
$record= DB::table('records')->where('alias', $alias)->firstOrFail();
Yeah of course! Just use normal SQL and ->selectRaw( your conditions ) and look for if there is a entry where your specifications are.
https://laravel.com/docs/5.7/queries#raw-expressions

Link two tables in one in Laravel 5.5

$category = Category::all();
$product = Product::all()->where('category_id', $category->name)->get();
Change category id from its name and link two tables in one in Laravel 5.5.
kindly refer to Laravel documentation regarding setting up relationships:
https://laravel.com/docs/5.5/eloquent-relationships
The relation between Category & Product is one to many, so it will be:
// app/Category.php
public function products()
{
return $this->hasMany(Product::class);
}
You need to return a view and pass the data instead of returning a collection:
return view('some.view', [
$category => Category::all();
$product => Product::where('category_id', $category->name)->get();
]);
https://laravel.com/docs/5.5/views#passing-data-to-views
Also, when you do this:
$product=Product::all()->where('category_id',$category->name)->get();
You're loading all products from DB into memory and then filtering them because all() is executing the query. Do not do this.

Search With Filters from Other Tables

I try to build a search query with different params but some of the filters columns comes from other tables who are in relation with another table , i don't know how to achieve that
For exemple the column "compet_id" comes from my table Rencontre.
In my table RencontreOfficiel i have rencontre_id to make the relation with "Rencontre"
I'm not sure if my clear it's a little bit difficult to explain ; hope someone could see and help .
here my controller :
$query = RencontreOfficiel::query();
$filters = [
'compet_id' => 'compet_id',
'structure_id' => 'structure_id',
'catg_compet_id' => 'dt_rencontre',
'fonction_id' => 'dt_rencontre',
'bareme_id' => 'bareme_id',
'dt_min_rencontre' => 'dt_rencontre',
'dt_max_rencontre' => 'dt_rencontre',
];
$dt_min = $request->input('dt_rencontre_min');
$dt_max = $request->input('dt_rencontre_max');
foreach ($filters as $key => $column) {
$query->when($request->{$key}, function ($query, $value) use ($column , $dt_min , $dt_max) {
$query->where($column, $value)->orWhereBetween('dt_rencontre' , [$dt_min , $dt_max]);
});
}
You can use whereHas and with keyword in Eloquent search.
for example you have Blog method that connected to User model. every Blog send by user . If you want to have search in User according to his blogs you can use this :
$user = User::where(function($query){
$query->where('age','>=',18);
})->whereHas('blogs', function ($query){
$query->where('text', 'LIKE', '%game%');
});
In this code blogs in whereHas method is name of Eloquent method in User model.
Result : this code return users older than 18 years that have blogs with title like game.

Resources