I have a model "SalesContract" which has a "belongsTo" relationship with a class called "Asset". However, it does not work (I cannot set or get).
Could it be an issue with the "asset()" helper method?
If I change the name of my method to something like "related_asset()", then it works.
This does NOT work:
public function asset()
{
return $this->belongsTo(Asset::class);
}
This DOES work:
public function related_asset()
{
return $this->belongsTo(Asset::class);
}
Full model:
class SalesContract extends Model
{
use SoftDeletes;
use Commentable;
const icon_class = 'far fa-file-signature';
const default_buyer_fee = 100;
const default_carproof_fee = 36.45;
protected $fillable = [
'number', 'asset_id', 'seller_id', 'buyer_id', 'buyer_representative', 'sale_date', 'sale_price',
'apply_sales_taxes_to_sale_price', 'buyer_fee', 'carproof_fee', 'deposit'
];
protected $casts = [
'sale_date' => 'datetime',
'sale_price' => 'float',
'carproof_fee' => 'float',
'buyer_fee' => 'float',
'deposit' => 'float',
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime'
];
protected $appends = [
'subtotal', 'taxable_amount', 'sales_taxes', 'total', 'balance'
];
protected static function boot()
{
parent::boot();
static::addGlobalScope('order', function (Builder $builder) {
$builder->orderBy('created_at', 'desc');
});
static::saving(function($table) {
if (empty($table->id)) {
if ($current_user = Auth::user()) {
$table->created_by_user_id = $current_user->id;
}
}
});
}
public function __construct(array $attributes = [])
{
if (empty($this->sale_date)) {
$this->sale_date = Carbon::today()->format('Y-m-d');
}
if (empty($this->id)) {
if (empty($this->number)) {
if ($asset = $this->asset) {
$this->number = $asset->external_file_number ?? $asset->internal_file_number;
}
}
$this->buyer_fee = $this->buyer_fee ?? self::default_buyer_fee;
$this->carproof_fee = $this->carproof_fee ?? self::default_carproof_fee;
$this->apply_sales_taxes_to_sale_price = $this->apply_sales_taxes_to_sale_price ?? 1;
}
parent::__construct($attributes);
}
public function __toString()
{
return __('sales_contracts.item_label', ['number' => $this->number ?? $this->id]);
}
public function scopeFilter($query, $filters)
{
$filters = is_array($filters) ? array_filter($filters) : [];
return $query->where($filters);
}
public function asset()
{
return $this->belongsTo(Asset::class);
}
public function seller()
{
return $this->belongsTo(Contact::class);
}
public function buyer()
{
return $this->belongsTo(Contact::class);
}
public function created_by_user()
{
return $this->belongsTo(User::class);
}
public function getSubtotalAttribute()
{
return $this->sale_price + $this->carproof_fee + $this->buyer_fee;
}
public function getTaxableAmountAttribute()
{
if ($this->apply_sales_taxes_to_sale_price) {
return $this->subtotal;
} else {
return $this->subtotal - $this->sale_price;
}
}
public function getSalesTaxesAttribute()
{
$sales_taxes = [];
if ($seller = $this->seller) {
foreach ($seller->sales_tax_numbers as $tax_number) {
if ($tax_number->use) {
if ($sales_tax = $tax_number->sales_tax) {
$sales_taxes[] = [
'sales_tax' => $sales_tax,
'name' => $sales_tax->name,
'rate' => $sales_tax->rate,
'label' => $sales_tax->label,
'number' => $tax_number->number,
'amount' => round($this->taxable_amount * $sales_tax->rate, 2)
];
}
}
}
}
return $sales_taxes;
}
public function getSalesTaxesTotalAttribute()
{
$total = 0;
foreach ($this->sales_taxes as $sales_tax) {
$total += $sales_tax['amount'];
}
return $total;
}
public function getTotalAttribute()
{
return $this->subtotal + $this->sales_taxes_total;
}
public function getBalanceAttribute()
{
return $this->total - $this->deposit;
}
}
From controller:
$sales_contract = new SalesContract;
if ($request->has('sales_contract')) {
$sales_contract->fill($request->input('sales_contract'));
}
Result of dd($request->input()):
array:1 [▼
"sales_contract" => array:1 [▼
"asset_id" => "11754"
]
]
(Yes, Asset with ID 11754 does exist.)
by default Name of relation is depended on 'foreign_key'
if you want to set different name of relation than foreign key just provide foreign key and other_key along with relation declaration
public function asset()
{
return $this->belongsTo(Asset::class,related_asset,id);
}
Problem solved.
I had to remove the following code from my __construct() method as it was breaking the relationship somehow:
if (empty($this->number)) {
if ($asset = $this->asset) {
$this->number = $asset->external_file_number ?? $asset->internal_file_number;
}
}
Related
i have laravel excel maatwebsite import update function, it works really well but i want to mark record that change by add "correction_flag" variable. the question is, how can i set this "correction_flag" when import.
this is my import function:
public function collection(Collection $rows)
{
foreach ($rows as $row)
{
$tgl_lahir_cell = $this->transformDate($row['tanggal_lahir']);
$tgl_awal_masa_kerja_cell = $this->transformDate($row['tanggal_awal_masa_kerja']);
$tgl_menjadi_permanen_cell = $this->transformDate($row['tanggal_menjadi_permanen']);
$tgl_keluar_cell = $this->transformDate($row['tanggal_keluar']);
if($tgl_lahir_cell == '1970-01-01') {
$formatedDate1 = NULL;
}else{
$formatedDate1 = $tgl_lahir_cell;
}
if($tgl_awal_masa_kerja_cell == '1970-01-01') {
$formatedDate2 = NULL;
}else{
$formatedDate2 = $tgl_awal_masa_kerja_cell;
}
if($tgl_menjadi_permanen_cell == '1970-01-01') {
$formatedDate3 = NULL;
}else{
$formatedDate3 = $tgl_menjadi_permanen_cell;
}
if($tgl_keluar_cell == '1970-01-01') {
$formatedDate4 = NULL;
}else{
$formatedDate4 = $tgl_keluar_cell;
}
Tempdat::where('cc', Auth::user()->ccode)
->where('id_tempdat', $row['id_tempdat'])
->update([
'golongan' => $row['golongan'],
'nama' => $row['nama'],
'jenis_kelamin' => $row['jenis_kelamin'],
'tgl_lahir' => $formatedDate1,
'tgl_awal_masa_kerja' => $formatedDate2,
'tgl_menjadi_permanen' => $formatedDate3,
'status_awal' => $row['status_di_awal_periode'],
'gaji_pokok_awal' => $row['gaji_pokok_di_awal_periode'],
'tunjangan_tetap_awal' => $row['tunjangan_tetap_di_awal_periode'],
'total_upah_awal' => $row['total_upah_di_awal_periode'],
'status_akhir' => $row['status_di_akhir_periode'],
'tgl_keluar' => $formatedDate4,
'status2_akhir' => $row['keterangan_keluar'],
'gaji_pokok_akhir' => $row['gaji_pokok_di_akhir_periode'],
'tunjangan_tetap_akhir' => $row['tunjangan_tetap_di_akhir_periode'],
'total_upah_akhir' => $row['total_upah_di_akhir_periode'],
'jumlah_pesangon_paid_awal' => $row['pesangon_dibayarkan_pada_periode'],
'correction_flag' => 'CORRECTED'
]);
}
}
public function headingRow(): int
{
return 4;
}
public function startRow(): int
{
return 5;
}
i already tried to put correction_flag like the example above but its just make all record uploaded marked CORRECTED eventhou there is no changes happend.
You need to first() the query, because laravel model event listeners won't work if there's mass update/create. So what you need to do is:
$tempdat = Tempdat::where('cc', Auth::user()->ccode)->where('id_tempdat', $row['id_tempdat'])->first();
if($tempdat){
$tempdat->update([
...
]);
}
And add this function to your Temptdat model:
protected static function booted()
{
parent::boot();
self::saving(function ($model) {
if ($model->isDirty()) {
$model->correction_flag = 'CORRECTED';
}
});
}
In controller
Login information is added inside an array and passed to model. Why it is not inserted in table.
$loginInfo = [
'agent' => $this->getUserAgentInfo(),
'ip' => $this->request->getIPAddress(),
'logintime' => date('Y-m-d h:i:s'),
];
$data=$model->saveLoginInfo($loginInfo);
...
...
public function getUserAgentInfo()
{
$agent = $this->request->getUserAgent();
if ($agent->isBrowser())
{
$currentAgent = $agent->getBrowser();
}
elseif ($agent->isRobot())
{
$currentAgent = $this->agent->robot();
}
elseif ($agent->isMobile())
{
$currentAgent = $agent->getMobile();
}
else{
$currentAgent = 'Undefined User Agent';
}
return $currentAgent;
}
In Model
public function saveLoginInfo($data){
$this->db->table('login_activity')->set($data)->insert();
}
I'm using ValueObject casting as an ID of my model. Everything works fine when I get a record from database, however when it coming to saving, the ID is null. If I comment "casts" out, ID is correct.
Example:
$game = new Game($data);
$game->created_by = $userId; // Id ValueObject
$game->save();
dd($game);
// attributes:
// "id" => null,
// "created_by" => Id{#value: 10},
Id ValueObject:
class Id
{
public function get($model, $key, $value, $attributes)
{
$this->value = $value;
return $this;
}
public function set($model, $key, $value, $attributes)
{
$this->value = $value;
}
public function value(): int
{
return $this->value;
}
public function __toString()
{
return (string) $this->value;
}
}
Model:
class Game extends Model
{
protected $casts = [
'id' => Id::class
];
}
What can I do with it?
Thanks in advance
Okey, I think that there should be a ValueObject and a CastingObject, I ended up with something similar to this:
class Game extends Model
{
protected $casts = [
'id' => IdCast::class
];
}
class IdCast implements CastsAttributes
{
public function get($model, $key, $value, $attributes)
{
return new Id(
$attributes['id']
);
}
public function set($model, $key, $value, $attributes)
{
return [
'id' => $value
];
}
}
class Id
{
private $value;
public function __construct($id)
{
$this->value = $id;
}
public function value(): int
{
return $this->value;
}
public function __toString()
{
return (string) $this->value;
}
}
I have a model with the relation called "reviews":
class ReportStructure extends \yii\db\ActiveRecord
{
const REVIEW_LIST_NAME = 'reviews';
public function getReviewList()
{
return $this->hasOne(FileIndexList::className(), ['id_owner' => 'id_report'])
->where('list_name = :list_name', [':list_name' => self::REVIEW_LIST_NAME]);
}
public function getReviews()
{
return $this->hasMany(FileIndex::className(), ['id_file_index' => 'id_file_index'])->via('reviewList');
}
}
In View, the reviews are displayed by GridView widget. The user can add or delete reviews by the other View. The user should specify at least one review. I added the validation rule to the model:
public function rules()
{
return [
['reviews', 'checkReviews'],
];
}
public function checkReviews($attribute)
{
if (count($this->reviews) === 0) {
$this->addError($attribute, 'You should add at least one review');
}
}
But it seems that rule even not fired.
public function actionIndex($idSupply, $restoreTab = false) {
$this->initData($idSupply, $report, $reestrData, $structure, $elements);
$ok = $report->load(Yii::$app->request->post()) &&
$reestrData->load(Yii::$app->request->post()) &&
Model::loadMultiple($elements, Yii::$app->request->post());
if($ok) {
$ok = $report->validate() &&
$reestrData->validate() &&
Model::validateMultiple($elements) &&
$structure->validate();
if($ok) {
$report->id_status = Status::STATUS_VERIFIED;
$this->saveData($report, $reestrData, $structure, $elements);
return $this->redirect(['supplies/update', 'id' => $idSupply]);
}
}
return $this->render('index', [
'structure' => $structure,
'report' => $report,
'reestrData' => $reestrData,
'elements' => $elements,
'restoreTab' => $restoreTab
]);
}
That's how the data is initialized. $elements are the objects of one class, I use tabular input for them.
private function initData($idSupply, &$report, &$reestrData, &$structure, &$elements) {
$report = \app\models\Reports::findOne($idSupply);
$reestrData = \app\models\ReestrData::findOne($report->id_reestr_data);
$structure = \app\models\report\ReportStructure::findOne($report->id_supply);
$elements = [
'titleIndex' => FileIndex::getInstance($structure->id_title_index, $structure->getAttributeLabel('id_title_index')),
'abstractIndex' => FileIndex::getInstance($structure->id_abstract_index, $structure->getAttributeLabel('id_abstract_index')),
'technicalSpecificationIndex' => FileIndex::getInstance($structure->id_technical_specification_index, $structure->getAttributeLabel('id_technical_specification_index')),
'contentsIndex' => FileIndex::getInstance($structure->id_contents_index, $structure->getAttributeLabel('id_contents_index')),
'imageListIndex' => FileIndex::getInstance($structure->id_image_list_index, $structure->getAttributeLabel('id_image_list_index'), false),
'tableListIndex' => FileIndex::getInstance($structure->id_table_list_index, $structure->getAttributeLabel('id_table_list_index'), false),
'textAnnexListIndex' => FileIndex::getInstance($structure->id_text_annex_list_index, $structure->getAttributeLabel('id_text_annex_list_index'), false),
'graphAnnexListIndex' => FileIndex::getInstance($structure->id_graph_annex_list_index, $structure->getAttributeLabel('id_graph_annex_list_index'), false),
'glossaryIndex' => FileIndex::getInstance($structure->id_glossary_index, $structure->getAttributeLabel('id_glossary_index'), false),
'reportIntroductionIndex' => FileIndex::getInstance($structure->id_report_introduction_index, $structure->getAttributeLabel('id_report_introduction_index')),
'reportMainPartIndex' => FileIndex::getInstance($structure->id_report_main_part_index, $structure->getAttributeLabel('id_report_main_part_index')),
'reportConclusionIndex' => FileIndex::getInstance($structure->id_report_conclusion_index, $structure->getAttributeLabel('id_report_conclusion_index')),
'bibliographyIndex' => FileIndex::getInstance($structure->id_bibliography_index, $structure->getAttributeLabel('id_bibliography_index')),
'metrologicalExpertiseIndex' => FileIndex::getInstance($structure->id_metrologicalexpertise_index, $structure->getAttributeLabel('id_metrologicalexpertise_index')),
'patentResearchIndex' => FileIndex::getInstance($structure->id_patent_research_index, $structure->getAttributeLabel('id_patent_research_index')),
'costStatementIndex' => FileIndex::getInstance($structure->id_cost_statement_index, $structure->getAttributeLabel('id_cost_statement_index')),
];
}
And tht's how the data is saved:
private function saveData($report, $reestrData, $structure, $elements) {
$reestrData->save(false);
$report->save(false);
foreach ($elements as $element) {
$element->save(false);
}
$structure->id_title_index = $elements['titleIndex']->id_file_index;
$structure->id_abstract_index = $elements['abstractIndex']->id_file_index;
$structure->id_technical_specification_index = $elements['technicalSpecificationIndex']->id_file_index;
$structure->id_contents_index = $elements['contentsIndex']->id_file_index;
$structure->id_image_list_index = $elements['imageListIndex']->id_file_index;
$structure->id_table_list_index = $elements['tableListIndex']->id_file_index;
$structure->id_text_annex_list_index = $elements['textAnnexListIndex']->id_file_index;
$structure->id_graph_annex_list_index = $elements['graphAnnexListIndex']->id_file_index;
$structure->id_glossary_index = $elements['glossaryIndex']->id_file_index;
$structure->id_report_introduction_index = $elements['reportIntroductionIndex']->id_file_index;
$structure->id_report_main_part_index = $elements['reportMainPartIndex']->id_file_index;
$structure->id_report_conclusion_index = $elements['reportConclusionIndex']->id_file_index;
$structure->id_bibliography_index = $elements['bibliographyIndex']->id_file_index;
$structure->id_metrologicalexpertise_index = $elements['metrologicalExpertiseIndex']->id_file_index;
$structure->id_patent_research_index = $elements['patentResearchIndex']->id_file_index;
$structure->id_cost_statement_index = $elements['costStatementIndex']->id_file_index;
$structure->save(false);
}
I eventually decided not to use validation for the relation at all and simply check reviews count in the controller:
if (count($structure->reviews) === 0) {
$ok = false;
Yii::$app->session->setFlash('danger', 'You should add at least one review!');
}
I think it's better to check it in beforeDelete method.
you can add this method to your model, and check, if it's the only review, then returns false.
public function beforeDelete()
{
if (!parent::beforeDelete()) {
return false;
}
if(self::find()->count() >1)
return true;
else
return false;
}
I'm busy with a tutorial and I ended up getting an error that says
This webpage has a redirect loop
I know that the problem is here in my routes.php
Route::group(["before" => "guest"], function(){
$resources = Resource::where("secure", false)->get();
foreach($resources as $resource){
Route::any($resource->pattern, [
"as" => $resource->name,
"uses" => $resource->target
]);
}
});
Route::group(["before" => "auth"], function(){
$resources = Resource::where("secure", true)->get();
foreach($resources as $resource){
Route::any($resource->pattern, [
"as" => $resource->name,
"uses" => $resource->target
]);
}
});
UserController
class UserController extends \BaseController {
public function login()
{
if($this->isPostRequest())
{
$validator = $this->getLoginValidator();
if($validator->passes())
{
$credentials = $this->getLoginCredentials();
if(Auth::attempt($credentials)){
return Redirect::route("user/profile");
}
return Redirect::back()->withErrors([
"password" => ["Credentials invalid."]
]);
}else{
return Redirect::back()
->withInput()
->withErrors($validator);
}
}
return View::make("user/login");
}
protected function isPostRequest()
{
return Input::server("REQUEST_METHOD") == "POST";
}
protected function getLoginValidator()
{
return Validator::make(Input::all(), [
"username" => "required",
"password" => "required"
]);
}
protected function getLoginCredentials()
{
return [
"username" => Input::get("username"),
"password" => Input::get("password")
];
}
public function profile()
{
return View::make("user/profile");
}
public function request()
{
if($this->isPostRequest()){
$response = $this->getPasswordRemindResponse();
if($this->isInvalidUser($response)){
return Redirect::back()
->withInput()
->with("error", Lang::get($response));
}
return Redirect::back()
->with("status", Lang::get($response));
}
return View::make("user/request");
}
protected function getPasswordRemindResponse()
{
return Password::remind(Input::only("email"));
}
protected function isInvalidUser($response)
{
return $response === Password::INVALID_USER;
}
public function reset($token)
{
if($this->isPostRequest()){
$credentials = Input::only(
"email",
"password",
"password_confirmation"
) + compact("token");
$response = $this->resetPassword($credentials);
if($response === Password::PASSWORD_RESET){
return Redirect::route("user/profile");
}
return Redirect::back()
->withInput()
->with("error", Lang::get($response));
}
return View::make("user/reset", compact("token"));
}
protected function resetPassword($credentials)
{
return Password::reset($credentials, function($user, $pass){
$user->password = Hash::make($pass);
$user->save();
});
}
public function logout()
{
Auth::logout();
return Redirect::route("user/login");
}
}
GroupController
class GroupController extends \BaseController {
public function indexAction()
{
return View::make("group/index", [
"groups" => Group::all()
]);
}
public function addAction()
{
$form = new GroupForm();
if($form->isPosted()){
if($form->isValidForAdd()){
Group::create([
"name" => Input::get("name")
]);
return Redirect::route("group/index");
}
return Redirect::route("group/add")->withInput([
"name" => Input::get("name"),
"errors" => $form->getErrors()
]);
}
return View::make("group/add", [
"form" => $form
]);
}
public function editAction()
{
$form = new GroupForm();
$group = Group::findOrFail(Input::get("id"));
$url = URL::full();
if($form->isPosted()){
if($form->isValidForEdit()){
$group->name = Input::get("name");
$group->save();
$group->users()->sync(Input::get("user_id", []));
$group->resources()->sync(Input::get("resource_id", []));
return Redirect::route("group/index");
}
return Redirect::to($url)->withInput([
"name" => Input::get("name"),
"errors" => $form->getErrors(),
"url" => $url
]);
}
return View::make("group/edit", [
"form" => $form,
"group" => $group,
"users" => User::all(),
"resources" => Resource::where("secure", true)->get()
]);
}
public function deleteAction()
{
$form = new GroupForm();
if($form->isValidForDelete()){
$group = Group::findOrFail(Input::get("id"));
$group->delete();
}
return Redirect::route("group/index");
}
}
but I'm not sure how to go about fixing it especially since I was following a tutorial.