storing and updating has-many relationships laravel - laravel

i m about storing datas using haMany Relatiions
where Cars may have more than picture
and each picture can have only one car
Car Modem Car.php
class Car extends Model
{
protected $table = 'cars';
public $timestamps = true;
use SoftDeletes;
protected $dates = ['deleted_at'];
protected $fillable = array('Marque', 'Model', 'sieges', 'climatisation', 'portes', 'transmition', 'price','url','car_id');
public function cars_images()
{
return $this->hasMany(CarsImage::class);
}
CarsImage Model
class CarsImage extends Model
{
protected $table = 'cars_images';
public $timestamps = true;
use SoftDeletes;
protected $dates = ['deleted_at'];
protected $fillable = array('url');
public function cars()
{
return $this->belongsTo(Car::class);
}
}
MyController :
public function store(Request $request) {
$car = new Car;
$car->Marque = Input::get('Marque');
$car->Model = Input::get('Model');
$car->sieges = Input::get('sieges');
$car->climatisation = Input::get('climatisation');
$car->portes = Input::get('portes');
$car->transmition = Input::get('transmition');
$car->price = Input::get('price');
$img = new CarsImage;
$img->url = 'jean Luc Picard';
DB::transaction(function() use ($car, $img) {
$car = $car->save();
Car::find($car->id)->cars_images()->save($img);
});
return 'ok';
}
the problem is the car is saved and the url also is saved but with not the car_id
Any help please ?

just use create method:
$car = Car::create([
'Marque' => $request->Marque,
//other fields...
]);
$image = $car->cars_images()->create([
'url' => 'jean Luc Picard'
]);
and don't forget to use $fillable in your models.

Related

Laravel Multiple Table Subquery

I'm using Laravel 6.0
I have 4 different tables.
Tables:
post_category
id
relation_post_id
post_type
category_id
photo_post
id
title
image
created_at
text_post
id
title
content
created_at
video_post
id
title
video_source_url
created_at
I'd like to list posts in two date ranges from the post_category table. For example
PostCategory::whereBetween('created_at',[$from, $to])->get();
The result should be:
Result
https://i.ibb.co/y53PmJ9/image.png
How can I do that?
Models:
PostCategory
class PostCategory extends Model
{
use SoftDeletes;
protected $table = 'post_category';
public $timestamps = true;
protected $fillable = [
'relation_post_id',
'post_type', // 1: text, 2: photo, 3: video
'category_id',
];
public function text()
{
return $this->belongsTo('App\TextPost','relation_post_id','id');
}
public function photo()
{
return $this->belongsTo('App\PhotoPost','relation_post_id','id');
}
public function video()
{
return $this->belongsTo('App\VideoPost','relation_post_id','id');
}}
TextPost
class TextPost extends Model
{
use SoftDeletes;
protected $table = 'text_post';
public $timestamps = true;
protected $fillable = [
'title',
'content',
];
}
PhotoPost
class PhotoPost extends Model
{
use SoftDeletes;
protected $table = 'photo_post';
public $timestamps = true;
protected $fillable = [
'title',
'image',
];
}
Video Post
class VideoPost extends Model
{
use SoftDeletes;
protected $table = 'video_post';
public $timestamps = true;
protected $fillable = [
'title',
'video_source_url',
];
}
Sure, it's possible. But since we just know your database design but not your codebase, it's hard to say. Intuitively I'd go with a polymorphic relationship.

How can I use parent relation attribute in sub query in laravel eloquent

$order_detail = Order::where([['user_id', $user->id], ['updated_at', '>', $updated_at]])
->with([
'currency' => function ($query) {
$query->select('currency_code', 'currency_symbol', 'ex_rate_with_base');
},
'orderList' => function ($query) {
$query->select('id', 'order_id', 'product_code', 'qty',
DB::raw('(unit_price*orders.ex_rate_with_base) as unit_price_new'), 'status');
},
])->get();
Please help,
How can I use the attribute ex_rate_with_base from order table in sub query.
I do not want to use DB query. Please solve it with eloquent.
I would have done it like this 👇
Database Structure:
ModelCurrency.php
class ModelCurrency extends Model
{
public $timestamps = true;
protected $table = 'currency';
protected $guarded = [];
}
ModelOrderList.php
class ModelOrderList extends Model{
public $timestamps = true;
protected $table = 'order_list';
protected $guarded = [];
}
ModelOrderDetail.php
class ModelOrderDetail extends Model{
public $timestamps = true;
protected $table = 'order_detail';
protected $guarded = [];
public function scopeOfUser($query, $user_id){
return $query->where('user_id', $user_id);
}
public function scopeUpdatedAfter($query, $updated_at){
return $query->where('updated_at', '>', $updated_at);
}
public function currency(){
return $this->hasOne(ModelCurrency::class, 'id', 'currency_id');
}
public function order_lists(){
return $this->hasMany(ModelOrderList::class, 'order_id', 'id');
}
}
Function in controller:
//imports
use App\ModelOrderDetail;
use Illuminate\Support\Carbon;
public function prices() {
$user_id = 1;
$updated_at = Carbon::yesterday();
$data = ModelOrderDetail::with('currency', 'order_lists')->ofUser($user_id)->updatedAfter($updated_at)->get();
foreach ($data as $d){
$base_rate = $d->currency->base_rate;
foreach($d->order_lists as $o) $o->new_unit_price = $base_rate * $o->unit_price;
}
return response()->json($data);
};
Edit - Output : https://pastebin.com/i53PytSk

Laravel Eloquent create null field

class Product extends Model
{
use SoftDeletes;
protected $dates = ['deleted_at'];
public $timestamps = true;
protected $fillable = ['name'];
protected $connection = 'pos';
public function __construct()
{
config(['database.connections.pos.database' => 'pos_1']);
parent::__construct();
}
}
Product::create(['name' => 'Snack']);
on my db id=1, name=null, created_at='2016-06-26 18:30:24', updated_at='2016-06-26 18:30:24', deleted_at=null
Why name=null?
Update post
works when I use
$p = new Product();
$p->name = 'Snack';
$p->save();
but why Product::create(['name' => 'Snack']); fill as null ?
Update post(solved)
ah I missing pass array as parameter on that constructor.
public function __construct(array $attributes)
{
config(['database.connections.pos.database' => 'pos_1']);
parent::__construct($attributes);
}
Probably the reason is that you again don't run parent constructor.
Instead of:
public function __construct()
{
config(['database.connections.pos.database' => 'pos_1']);
}
you should use:
public function __construct()
{
config(['database.connections.pos.database' => 'pos_1']);
parent::__construct();
}
Be aware that for your Eloquent Model you have also connection property, so you could probably set also name of database connection.

How to use "select" method to reduce data transfer when using Eager Loading

I have a API and its taking long time to get all the info and its because I'm only hidding some data but I want to omit not to hidde. I found select() method to chose wich data send and reduce the time to query all information I really need.
Im trying to use select just after the relation just like this, just to retrieve only name from OPR_User table:
public function creatorUser() {
return $this->belongsTo('Knotion\OPR_User', 'idCreatorUser', 'idUser')->select('name');
}
but is not working
This is my Model code
<?php
namespace Knotion;
use Illuminate\Database\Eloquent\Model;
class CTL_Resource extends Model {
protected $table = "CTL_Resource";
protected $primaryKey = "idResource";
public $incrementing = false;
public $timestamps = false;
public static $snakeAttributes = false;
protected $hidden = [
'coachVisibility', 'thumbnail',
'studentVisibility', 'isHTML','studentIndex', 'coachIndex',
'isURL', 'source', 'path', 'status', 'updateTime', 'isfolder',
'parentResource', 'idModifierUser', 'idResourceType', 'idCreatorUser', 'idCreationCountry'
];
protected $fillable = ['idResourceType','productionKey', 'idCreatorUser', 'idModifierUser', 'idCreationCountry', 'title', 'description', 'URL', 'fileName', 'extension', 'minimumAge', 'maximumAge', 'productionKey'];
public function creatorUser() {
return $this->belongsTo('Knotion\OPR_User', 'idCreatorUser', 'idUser');
}
public function creationCountry() {
return $this->belongsTo('Knotion\CTL_Country', 'idCreationCountry', 'idCountry');
}
public function resourceType() {
return $this->belongsTo('Knotion\CTL_ResourceType', 'idResourceType', 'idResourceType');
}
public function quickTags() {
return $this->belongsToMany('Knotion\CTL_QuickTag', 'CTL_Resource_has_QuickTags', 'idResource','idQuickTag');
}
public function tags() {
return $this->belongsToMany('Knotion\CTL_Tag','CTL_Resource_has_Tags', 'idResource', 'idTag');
}
public function relatedTo() {
return $this->belongsToMany('Knotion\CTL_RelatedTo', 'CTL_Resource_has_RelatedTo', 'idResource', 'idRelatedTo');
}
}
this is my relation model code (just in case needed):
<?php
namespace Knotion;
use Illuminate\Database\Eloquent\Model;
class OPR_User extends Model {
protected $table = "OPR_User";
protected $primaryKey = "idUser";
public $incrementing = false;
public $timestamps = false;
public static $snakeAttributes = false;
protected $hidden = ['firstName', 'secondName', 'firstSurName', 'secondSurName', 'password', 'picture', 'status', 'createTime', 'updateTime', 'idUserType', 'email'];
public function resources() {
return $this->hasMany('Knotion\CTL_Resource', 'idResource');
}
public function userType() {
return $this->belongsTo('Knotion\CTL_UserType', 'idUserType', 'idUserType');
}
}
and this is my Controller code:
public function index(Request $request) {
$resources = CTL_Resource::all();
$resources->resourceType->select('name');
return $resources->load('creatorUser', 'creationCountry', 'resourceType', 'tags', 'quickTags', 'relatedTo');
}
When you add the ->select after the ->belongsTo it's no longer an actual relationship type, it's a query builder. You need to add the select afterwards before you call the ->load.
To fix the problem I had to include the id also in the relation, something like this:
public function resources() {
return $this->hasMany('Knotion\CTL_Resource', 'idResource')->select('idResource', 'name');
}

Getting url data to show in the url bar

I'm using Laravel 4 and I'm trying to get the url bar to display the text url that is saved in the database instead of using the id.
This is my routes.php
Route::get('/{id}', function($id = 1){
if(is_numeric($id))
{
$page = Menu::find($id);
$action = 'content';
return App::make('HomeController')->$action($id);
} else {
$column = 'url';
$url = Seo::where($column, '=', $id)->get();
$action = 'show';
return App::make('HomeController')->$action($url[0]->id);
}
});
I'm also using a pivot table to link the menu to the seo.
Seo model
<?php
class Seo extends \Eloquent {
protected $fillable = array('url', 'meta_title', 'meta_description', 'keywords');
protected $guarded = array('id');
protected $table = 'seo';
public static $rules = array(
'title' => '',
'content' => '',
'image' => ''
);
public function menu(){
return $this->belongsToMany('Menu', 'menu_seo', 'seo_id', 'menu_id');
}
}
Menu model
<?php
class Menu extends \Eloquent {
protected $fillable = array('title', 'menu_id', 'image');
protected $guarded = array('id');
protected $table = 'menus';
public static $rules = array(
);
public function seo(){
return $this->belongsToMany('Seo', 'menu_seo', 'menu_id', 'seo_id');
}
}
HomeController
public function content($id)
{
$menus_child = Menu::where('menu_id', 0)->with('menusP')->get();
$menu = Menu::where('id', $id)->firstOrFail();
//dd($menu->frames);
return View::make('index', compact('menus_child'))->with('menu', $menu);
}
and then I call my views that references the menu like this
#foreach($menu->banner as $banners)
{{ $banners->title }}
#endforeach
I'm still not sure how you want to retrieve the correct URL associated to an id but that shouldn't really matter. The basic principle is just to fetch the URL and make a redirect:
Route::get('/{id}', function($id = 1){
if(is_numeric($id))
{
$page = Menu::find($id);
$url = 'foo'; // get correct URL somehow
return Redirect::to($url);
} else {
// ...
}
});

Resources