Laravel : How to get the first record of each collections in a 'with' function query - sql

I want to get a collection of all artists with their latest image only.
The following code returns a collection of all artists but with only one image associated with the first artist.
$data = Artist::with(['images' => function($q){
$q->first();
}])
->get();
return $data;
My models:
class Artist extends Model {
public function images()
{
return $this->belongsToMany('App\Image');
}
}
class Image extends Model {
public function artists()
{
return $this->belongsToMany('App\Artist');
}
}

You can set in you modal:
public function FirstImage()
{
return $this->hasOne('image');
}
then:
$data = Artist::with('FirstImage')->get();

Related

How to get the default $id from another table using laravel model relationship?

I am facing the problem whereby I don't know the syntax of letting the id of my property model equals to property_id value in property_doc table.
In PropertyDoc model
public function property()
{
return $this->belongsTo(Properties::class, 'property_id');
}
In Properties model
public function property_id()
{
return $this->hasMany(PropertyDoc::class, 'property_id');
}
In PropertyController
public function StoreInfoProperty(Request $request)
{
$propertyInfo = new PropertyDoc;
$propertyInfo->property_id = $property_id;
}
I am stuck at retrieving the default id value in properties database to be equal to the property_id in property_docs database. Thank you.
You should change the naming of the relationship, see my example below:
In Properties model
public function propertyDocs()
{
return $this->hasMany(PropertyDoc::class, 'property_id', 'id');
}
In PropertyDoc model
public function property()
{
return $this->belongsTo(Properties::class, 'property_id', 'id');
}
In controller
public function StoreInfoProperty(Request $request)
{
$propertyDoc = PropertyDoc::with(['property'])->where('...logic here');
$property_id = $propertyDoc->property->id;
}
hope can help you and happy coding !

Flatten laravel nested relationship (parent to descendants) get all childerns

This is my Controller
$categoryIds = Category::select('id')->with('childrenRecursive')->where('id', 1)->get();
Ad::whereIn('category_id', $categoryIds)->get();
This is my model
public function parent() {
return $this->belongsTo(Category::class, 'parent_id');
}
public function childs() {
return $this->hasMany(Category::class, 'parent_id');
}
public function Ads() {
return $this->hasManyThrough(Ad::class, Category::class, 'parent_id', 'category_id', 'id');
}
How get all childern categories ides
I solved this problem with this solution
My Controller
public function index()
{
$parent = Category::with('descendants')->find(1);
$descendants = $this->traverseTree($parent, collect([1]));
$ads = Ad::whereIn('category_id',$descendants)->get();
return response($ads);
}
protected function traverseTree($subtree, $des)
{
$descendants = $des;
if ($subtree->descendants->count() > 0) {
foreach ($subtree->descendants as $descendant) {
$descendants->push($descendant);
$this->traverseTree($descendant, $descendants);
}
}
return $descendants;
}
I'd do it with Laravel's Subqueries approach.
$parentId = 4;
Ad::whereIn('category_id', function($q) use ($parentId) {
$q->select('id')
->from('categories')
->where('parent_id', $parentId);
});
If you want to add the parent model, you can chain with():
Ads::whereIn('category_id', function($q) use ($parentId) {
$q->select('id')
->from('categories')
->where('parent_id', $parentId);
})
->with('category.parent')
->get();
Your code chunks are not clear so you may need to tweak my code example.
If I understand your question properly you need to get ads corresponding to id's of all related records also, for a given category record.
$category = Category::with('childs:id,parent_id')
->where('id', 1)
->firstOrFail();
$categoryIds = collect([$category->parent_id, $category->id]);
$category->childs->map(fn($child) => $categoryIds->push($child->id));
$ads = Ads::whereIn('category_id', $categoryIds->filter()->all())
// Can eager load the product(s) if needed
//->with('products')
->get();

Laravel Convert Mysql query to Eloquent

I'm new to Laravel and I can write simple eloquent queries but have no idea how to convert this query to eloquent. Can anyone give any idea, is it possible to convert this to eloquent or I have to write raw query?
"Select categories.id, categories.name, Sum(likes.liked) as liked
FROM categories, likes
WHERE likes.material_id IN (SELECT category_material.material_id
FROM category_material
WHERE category_material.category_id = categories.id)
GROUP BY categories.id";
Here my Models
class Material extends Model
{
public function categories(){
return $this->belongsToMany(Category::class,'category_material');
}
public function likes(){
return $this->hasMany(Like::class);
}
////////////////////////////////////////////////////////////
class Like extends Model
{
protected $table = 'likes';
public function user(){
return $this->belongsTo(User::class);
}
public function material(){
return $this->belongsTo(Material::class);
}
//////////////////////////////////////////////////////
class Category extends Model
{
public function materials(){
return $this->belongsToMany(Material::class,'category_material');
}
You can define a likes relationship in your Category model like so:
public function likes()
{
return $this->belongsToMany(Like::class, 'category_material', 'category_id', 'material_id', 'id', 'material_id');
}
Then to achieve what you're after with Eloquent you can use a mixture of has() and withCount, however, we're going to modify the withCount call to return a sum() instead:
$catrgories = Category::has('likes')->withCount([
'likes as liked' => function ($query) {
$query->select(DB::raw('SUM(likes.liked)'));
},
])->get();
If you're wanting to return categories that don't have any likes you can remove the has() method, and introduce the COALESCE() function to your raw query:
$catrgories = Category::withCount([
'likes as liked' => function ($query) {
$query->select(DB::raw('COALESCE(SUM(likes.liked), 0)'));
},
])->get();
Alternatively, you could simply load the necessary relationships and then use that fact that Eloquent returns collection to get the value after you've retrieved the results from the database:
$categories = Category::with('materials.likes')->get()->map(function ($item) {
$item->setAttribute('liked', $item->materials->map(function ($item) {
return $item->likes->map->sum('liked')->sum();
})->first());
$item->unsetRelation('materials');
return $item;
});
This would mean that you don't have to add the custom relationship.

How to validate two dimensional array in Yii2

How to validate two dimensional array in Yii2.
passenger[0][name] = bell
passenger[0][email] = myemail#test.com
passenger[1][name] = carson123
passenger[1][email] = carson###test.com
how to validate the name and email in this array
Thanks
Probably the most clean solution for validating 2-dimensional array is treating this as array of models. So each array with set of email and name data should be validated separately.
class Passenger extends ActiveRecord {
public function rules() {
return [
[['email', 'name'], 'required'],
[['email'], 'email'],
];
}
}
class PassengersForm extends Model {
/**
* #var Passenger[]
*/
private $passengersModels = [];
public function loadPassengersData($passengersData) {
$this->passengersModels = [];
foreach ($passengersData as $passengerData) {
$model = new Passenger();
$model->setAttributes($passengerData);
$this->passengersModels[] = $model;
}
return !empty($this->passengers);
}
public function validatePassengers() {
foreach ($this->passengersModels as $passenger) {
if (!$passenger->validate()) {
$this->addErrors($passenger->getErrors());
return false;
}
}
return true;
}
}
And in controller:
$model = new PassengersForm();
$model->loadPassengersData(\Yii::$app->request->post('passenger', []));
$isValid = $model->validatePassengers();
You may also use DynamicModel instead of creating Passanger model if you're using it only for validation.
Alternatively you could just create your own validator and use it for each element of array:
public function rules() {
return [
[['passengers'], 'each', 'rule' => [PassengerDataValidator::class]],
];
}
You may also want to read Collecting tabular input section in guide (unfortunately it is still incomplete).

Phalcon query builder can't get joined table data

I have 2 table 'sanpham' and 'danhmuc'. I use phalcon query builder to get data from 2 tables.
$laytin = $this->modelsManager->createBuilder()
->from("sanpham")
->innerJoin('danhmuc','sanpham.danhmuc=danhmuc.sodanhmuc')
->where('sanpham.sosanpham = '.$id.'')
->getQuery()
->getSingleResult();
$breadcrumbs = array('/' => Tool::getTranslation()->_('trangchu'),"/Loai-san-pham/".$laytin->tendep."/".$laytin->sodanhmuc => $laytin->tendanhmuc,'' => $laytin->tieudesanpham );
The query runs, but $laytin->tendep, $laytin->sodanhmuc, $laytin->tendanhmuc in 'danhmuc' table doesn't display. Every column in 'sanpham' table (such as: $laytin->tieudesanpham) displays properly.
You can add specific columns with:
$this->modelsManager->createBuilder()->columns('danhmuc.tend‌​ep, danhmuc.sodanhmuc')
With this method you will have to add each column you want in your output. QueryBuilder docs.
Another method is to query the Sanpham model.
For example:
class Sanpham extends \Phalcon\Mvc\Model
{
public static function findSomething($something)
{
// this is your actual query, it replaces the queryBuilder
return self::query()
->where('sanpham.sosanpham = :id:', ['id' => $something])
->innerJoin('danhmuc', 'sanpham.danhmuc = danhmuc.sodanhmuc')
->execute()->getFirst();
}
public function initialize()
{
// define the relation to danhmuc
$this->belongsTo('danhmuc', 'danhmuc', 'sodanhmuc');
}
}
class Danhmuc extends \Phalcon\Mvc\Model
{
public function initialize()
{
// there are other options besides "hasMany", like "hasOne".
// this is your relation to sanpham
$this->hasMany('sodanhmuc', 'sanpham', 'danhmuc');
}
}
class YourController extends \Phalcon\Mvc\Controller
{
public function testAction()
{
// get your first record in Sanpham matching "12345"
$sanpham = Sanpham::findSomething(12345);
// from your Sanpham object, get the related danhmuc object.
// this works because we defined the relations (belongsTo and hasMany)
$danhmuc = $sanpham->getRelated('danhmuc');
// now you have access to the values of danhmuc via the $danhmuc variable
$breadcrumbs = [
'/' => Tool::getTranslation()->_('trangchu'),
"/Loai-san-pham/" . $danhmuc->tendep => $danhmuc->tendanhmuc,
'' => $danhmuc->tieudesanpham,
];
}
}
Check the Phalcon model docs for more info on this.