Laravel 5.8 Call to undefined relationship [sourceClient] on model - laravel

I have a model WorkflowStep with a Polyphormic relation to TransportWorkflowStep and TransformworkflowStep
My transportWorkflowStep has an other relation to client.
When I do this in my code:
/** #var TransportWorkflowStep $workflowStepEntity */
$workflowStepEntity = $workflowStep->entity;
try {
var_dump($workflowStepEntity->sourceClient);
} catch (\Exception $exception) {
dd($exception);
}
I get this error:
Call to undefined relationship [sourceClient] on model [App\TransformWorkflowStep].
First weird thing is that I am working with TransportWorkflowStep when I dd($workflowstep) so I don’t know why he’s complaining about TransformWorkflowStep
My WorkflowStep model:
public function entity(): MorphTo
{
return $this->morphTo();
}
My TransportWorkflowStep model:
public function workflowStep(): MorphOne
{
return $this->morphOne(WorkflowStep::class, 'entity');
}
public function sourceClient(): BelongsTo
{
return $this->belongsTo(Client::class, 'source_id', 'id');
}
public function destinationClient(): BelongsTo
{
return $this->belongsTo(Client::class, 'destination_id', 'id');
}
My TransformWorkflowStep model:
public function workflowStep(): MorphOne
{
return $this->morphOne(WorkflowStep::class, 'entity');
}
EDIT
dump of $workflowStepEntity:
object(App\TransportWorkflowStep)[439]
protected 'table' => string 'transport_workflow_steps' (length=24)
protected 'fillable' =>
array (size=4)
0 => string 'source_id' (length=9)
1 => string 'destination_id' (length=14)
2 => string 'source_options' (length=14)
3 => string 'destination_options' (length=19)
protected 'connection' => string 'mysql' (length=5)
protected 'primaryKey' => string 'id' (length=2)
protected 'keyType' => string 'int' (length=3)
public 'incrementing' => boolean true
protected 'with' =>
array (size=0)
empty
protected 'withCount' =>
array (size=0)
empty
protected 'perPage' => int 15
public 'exists' => boolean true
public 'wasRecentlyCreated' => boolean false
protected 'attributes' =>
array (size=8)
'id' => string '4d32e11c-6453-4f48-9419-7c5cbd647128' (length=36)
'source_id' => string '8c826f52-a78c-4ef5-acf5-8e6fd59004a0' (length=36)
'destination_id' => string '921f0d90-2fae-496e-9991-68128e87d6d5' (length=36)
'source_options' => string 'source options' (length=14)
'destination_options' => string 'destination options' (length=19)
'created_at' => string '2019-07-04 11:17:35' (length=19)
'updated_at' => string '2019-07-12 08:39:58' (length=19)
'deleted_at' => null
protected 'original' =>
array (size=8)
'id' => string '4d32e11c-6453-4f48-9419-7c5cbd647128' (length=36)
'source_id' => string '8c826f52-a78c-4ef5-acf5-8e6fd59004a0' (length=36)
'destination_id' => string '921f0d90-2fae-496e-9991-68128e87d6d5' (length=36)
'source_options' => string 'source options' (length=14)
'destination_options' => string 'destination options' (length=19)
'created_at' => string '2019-07-04 11:17:35' (length=19)
'updated_at' => string '2019-07-12 08:39:58' (length=19)
'deleted_at' => null
protected 'changes' =>
array (size=0)
empty
protected 'casts' =>
array (size=0)
empty
protected 'dates' =>
array (size=1)
0 => string 'deleted_at' (length=10)
protected 'dateFormat' => null
protected 'appends' =>
array (size=0)
empty
protected 'dispatchesEvents' =>
array (size=0)
empty
protected 'observables' =>
array (size=0)
empty
protected 'relations' =>
array (size=0)
empty
protected 'touches' =>
array (size=0)
empty
public 'timestamps' => boolean true
protected 'hidden' =>
array (size=0)
empty
protected 'visible' =>
array (size=0)
empty
protected 'guarded' =>
array (size=1)
0 => string '*' (length=1)
protected 'forceDeleting' => boolean false
EDIT full code
WorkflowJob
<?php
namespace App\Jobs;
use App\Workflow;
use Carbon\Carbon;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class WorkflowJob implements ShouldQueue
{
use Dispatchable;
use InteractsWithQueue;
use Queueable;
use SerializesModels;
/**
* #var Workflow
*/
protected $workflowId;
/**
* Create a new job instance.
*
* #return void
* #param string $workflowId
*/
public function __construct(string $workflowId)
{
$this->workflowId = $workflowId;
}
/**
* Execute the job.
*
* #return \Illuminate\Foundation\Bus\PendingDispatch
* #throws \Exception
*/
public function handle()
{
try {
$this->execute(Workflow::find($this->workflowId));
} catch (\Exception $exception) {
throw $exception;
}
}
/**
* Execute the WorkflowJob.
*
* #param Workflow $workflow
*/
private function execute(Workflow $workflow)
{
// start a new workflow instance
$workflowInstance = $this->startWorkflowInstance($workflow);
// start the first step
StepJob::dispatch($workflowInstance, $workflow->workflowSteps->first()->order);
}
/**
* Start a new WorflowInstance for a Workflow.
*
* #param Workflow $workflow
* #return \Illuminate\Database\Eloquent\Model
*/
private function startWorkflowInstance(Workflow $workflow)
{
return $workflow->workflowInstances()->create([
'started_at' => Carbon::now(),
]);
}
}
StepJob:
<?php
namespace App\Jobs;
use App\Client;
use App\File;
use App\TransportWorkflowStep;
use App\WorkflowInstance;
use App\WorkflowStep;
use Carbon\Carbon;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
class StepJob implements ShouldQueue
{
use Dispatchable;
use InteractsWithQueue;
use Queueable;
use SerializesModels;
const LOG_START = 'start';
const LOG_END_SUCCESS = 'end';
const LOG_END_FAIL = 'fail';
/**
* #var WorkflowInstance
*/
private $workflowInstance;
/**
* #var int
*/
private $stepCount;
/**
* Create a new job instance.
*
* #param WorkflowInstance $workflowInstance
* #param int $order
*/
public function __construct(WorkflowInstance $workflowInstance, int $order)
{
$this->workflowInstance = $workflowInstance;
$this->stepCount = $order;
}
/**
* Execute the job.
*/
public function handle()
{
if ($this->stepCount <= $this->workflowInstance->workflow->workflowSteps->count()) {
/** #var WorkflowStep $workflowstep */
$workflowstep = $this->workflowInstance->workflow->workflowSteps->where('order', $this->stepCount)->first();
$workflowStepEntity = $workflowstep->entity;
if ($workflowStepEntity instanceof TransportWorkflowStep) {
/* #var TransportWorkflowStep $workflowStepEntity */
try {
var_dump($workflowStepEntity->sourceClient);
} catch (\Exception $exception) {
dd($exception);
}
var_dump($workflowstep->entity->sourceClient);
} else {
$workflowstep->entity->transformer
}
StepJob::dispatch($this->workflowInstance, $this->stepCount + 1);
} else {
return;
}
}
}
workflow_steps
transport_workflow_steps
transform_workflow_steps

You message sais: Call to undefined relationship [sourceClient] on model [App\TransformWorkflowStep].
Your model definition(TransformWorkflowStep):
public function workflowStep(): MorphOne
{
return $this->morphOne(WorkflowStep::class, 'entity');
}
Error message is correct, there is no sourceClient relationship on TransformWorkflowStep model. You should define it or stop using it like this ;)
EDIT:
Could you try to do this:
foreach($workflowStepCollection as $workflowStep)
{
dump($workflowStep->entity);
try
{
$x = $workflowStep->sourceClient;
}
catch(\Exception $ex)
{
dd($ex->getMessage());
}
}
When it fails(dd), the last result before dd should show you exactly which one is going bad.

Related

Update a record of DB if it exists after importing a Csv file in Laravel?

I'm using Maatwebsite\Excel to import a csv file to store new users in the DB. If i have already a record in DB with the same data it creates and error. How can i update the record if it exists ?
My import class is :
class UsersImport implements ToModel, WithCustomCsvSettings, WithHeadingRow
{
/**
* #param array $row
*
* #return \Illuminate\Database\Eloquent\Model|null
*/
public function model(array $row)
{
return new User([
'firstname' => $row['firstname'],
'lastname' => $row['lastname'],
'email' => $row['email'],
'password' => $row['pass'],
'created_at' => $row['registered'],
]);
}
public function getCsvSettings(): array
{
return [
'delimiter' => ","
];
}
}
You should implement the WithUpserts interface. Also you need to specify which field should be unique so if it exists, it will update the record, else it will create new one.
Assuming your unique column is email, change your code to the following:
class UsersImport implements ToModel, WithCustomCsvSettings, WithHeadingRow, WithUpserts
{
/**
* #param array $row
*
* #return \Illuminate\Database\Eloquent\Model|null
*/
public function model(array $row)
{
return new User([
'firstname' => $row['firstname'],
'lastname' => $row['lastname'],
'email' => $row['email'],
'password' => $row['pass'],
'created_at' => $row['registered'],
]);
}
public function getCsvSettings(): array
{
return [
'delimiter' => ","
];
}
public function uniqueBy()
{
return 'email';
}
}

how to unit test a controller in laravel?

This is the test function
public function testCreateSuccess(){
$user=['first_name'=>"heba",'last_name'=>"chakaron",'email'=>"hebachakaron#gmail.com",'password'=> "123456"];
$userReturned=['first_name'=>"heba",'last_name'=>"chakaron",'email'=>"hebachakaron#gmail.com",'password'=> Hash::make('123456')];
$userRequest = UserRegisterRequest::create("http://127.0.0.1:8000/api/users/", 'POST',[
'first_name'=>"heba",
'last_name'=>"chakaron",
'email'=>"hebachakaron#gmail.com",
'password'=>'123456',
'password_confirmation'=>'123456'
]);
/**
* #var UserService|\Mockery\MockInterface|\Mockery\LegacyMockInterface
*/
$mock=Mockery::mock(UserService::class);
$mock->shouldReceive('create')->with($user)
->once()
->andReturn($userReturned);
$this->userController=new UserController($mock);
$this->app->instance('App\Services\UserService', $mock);
$created=$this->userController->create($userRequest);
$this->assertSame($created['password'],$userReturned['password']);
}
This is the controller
class UserController extends Controller
{
//
public function __construct(UserService $userService)
{
$this->userService = $userService;
}
public function create(UserRegisterRequest $request)
{
$data = $this->userService->create($request->validated());
return HTTPResponse::ok($data);
}
}
This is the UserRegisterRequest
class UserRegisterRequest extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'first_name' => 'required|string|max:255',
'last_name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:6|confirmed',
];
}
}
When I run this testCreateSuccess it return There was 1 error:
Tests\Unit\UserTest::testCreateSuccess
Error: Call to a member function validated() on null
and the error is on the line $created=$this->userController->create($userRequest)

Laravel-excel cannot update records "WithUpserts" - not found

I'm trying to update database but i got this error:
Interface 'App\Imports\WithUpserts' not found
I can't understand where is mistake.
Everything from examples. My import class here:
namespace App\Imports;
use App\bmwprice;
use Maatwebsite\Excel\Concerns\ToModel;
class bmwimport implements ToModel, WithUpserts
{
public function model(array $row)
{
return new bmwprice([
'NUMBER' => $row[0],
'NUMBER2' => $row[1],
'WEIGHT' => $row[2],
'VPE' => $row[3],
'VIN' => $row[4],
'NL' => $row[5],
'TITLE' => $row[6],
'TEILEART'=> $row[7],
]);
}
public function uniqueBy()
{
return 'NUMBER';
}
}
Thank you.
Add
use Maatwebsite\Excel\Concerns\WithUpserts; // below other imports using use
<?php
namespace App\Imports;
use App\Models\CatalogStore;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\WithUpserts;
class CatalogupdateImport implements ToModel, WithUpserts
{
/**
* #param array $row
*
* #return \Illuminate\Database\Eloquent\Model|null
*/
public function model(array $row)
{
return new CatalogStore([
'sku' => $row['sku'],
'price' => $row['price'],
'qty' => $row['qty'],
]);
}
/**
* #return string|array
*/
public function uniqueBy()
{
return 'price';
}
}
I need to update the price field in an existing table but I get an error in my code that I can't find. Even if I remove sku in it goes to the next field "qty" and it generates undefined.
"Undefined index: sku"

how to set cakephp 3 email unique validation

I created a table users with 2 fields id(primary),(email)
I want email unique validation used following code but not working only not empty working.
<?php
namespace App\Controller;
use App\Model\Validation\UserValidator;
class UsersController extends AppController
{
public function register()
{
$this->loadModel("users");
if ($this->request->is('post')) {
$validator = new UserValidator();
$errors = $validator->errors($this->request->getData());
if (empty($errors)) {
} else {
$this->set('errors', $errors);
}
}
}
}
src/Model/Validation/UserValidator.php
<?php
namespace App\Model\Validation;
use Cake\Validation\Validator;
use Cake\ORM\Table;
use Cake\ORM\Rule\IsUnique;
class UserValidator extends Validator {
public function __construct()
{
parent::__construct();
$this
->notEmpty('name', 'The name field cannot be left empty')
->notEmpty('email', 'Fill Valid Email Id')
->add('email',['unique' => ['rule' => 'validateUnique', 'provider' => 'table', 'message' => 'Not unique']])
->notEmpty('mobile', 'Fill Valid 10 Digit Mobile No.');
}
}
create this file under \src\Model\Table\Userstable.php
updated
change the the filename capitalize the to make it \src\Model\Table\UsersTable.php
in my code below I validated my username and email as unique
use App\Model\Entity\User;
use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;
use Cake\ORM\Rule\IsUnique;
/**
* Users Model
*
*/
class UsersTable extends Table
{
/**
* Initialize method
*
* #param array $config The configuration for the Table.
* #return void
*/
public function initialize(array $config)
{
parent::initialize($config);
$this->table('users');
}
/**
* Default validation rules.
*
* #param \Cake\Validation\Validator $validator Validator instance.
* #return \Cake\Validation\Validator
*/
public function validationDefault(Validator $validator)
{
$validator
->requirePresence('username','create')
->notBlank('username', 'A username is required')
->add('username', 'unique', [
'rule' => 'validateUnique',
'provider' => 'table',
'message' => 'Username is already used'
]);
$validator
->requirePresence('email','create')
->notBlank('email', 'An email is required')
->add('email', 'unique', [
'rule' => 'validateUnique',
'provider' => 'table',
'message' => 'Email is already used'
]);
return $validator;
}
public function buildRules(RulesChecker $rules)
{
$rules->add($rules->isUnique(['username']));
$rules->add($rules->isUnique(['email']));
return $rules;
}
}

One to Many in Laravel

I have a model in which a Firm has a status. This means there are two tables:
Firm
FirmStatus
I have this defined in my project like this:
class FirmStatus extends Eloquent {
protected $table = 'firm_statuses';
protected $primaryKey = 'firm_status_id';
protected $fillable = array('firm_status_id', 'name');
}
class Firm extends Eloquent {
protected $table = 'firms';
protected $primaryKey = 'firm_id';
protected $fillable = array('name', 'firm_status_id');
public function users()
{
return $this->hasMany('User', 'firm_id', 'firm_id');
}
public function firm_status()
{
return $this->belongsTo('FirmStatus', 'firm_status_id');
}
}
But I can't seem to get this to work, no matter what way I try to access the FirmStatus on the Firm it just doesn't work?
In my controller I have this code:
$firm = Firm::find($id);
$firmClassifications = DB::table('firm_classifications')->orderBy('name', 'asc')->lists('name','firm_classification_id');
return var_dump($firm);
which returns this:
object(Firm)[243]
protected 'table' => string 'firms' (length=5)
protected 'primaryKey' => string 'firm_id' (length=7)
protected 'fillable' =>
array (size=5)
0 => string 'name' (length=4)
1 => string 'firm_classification_id' (length=22)
2 => string 'fca_number' (length=10)
3 => string 'question_number_passed_on' (length=25)
4 => string 'firm_status_id' (length=14)
protected 'connection' => null
protected 'perPage' => int 15
public 'incrementing' => boolean true
public 'timestamps' => boolean true
protected 'attributes' =>
array (size=7)
'firm_id' => int 8
'name' => string 'siofds4' (length=7)
'fca_number' => string '' (length=0)
'firm_classification_id' => int 1
'created_at' => string '2014-09-08 11:06:17' (length=19)
'updated_at' => string '2014-09-08 12:24:23' (length=19)
'firm_status_id' => int 2
protected 'original' =>
array (size=7)
'firm_id' => int 8
'name' => string 'siofds4' (length=7)
'fca_number' => string '' (length=0)
'firm_classification_id' => int 1
'created_at' => string '2014-09-08 11:06:17' (length=19)
'updated_at' => string '2014-09-08 12:24:23' (length=19)
'firm_status_id' => int 2
protected 'relations' =>
array (size=0)
empty
protected 'hidden' =>
array (size=0)
empty
protected 'visible' =>
array (size=0)
empty
protected 'appends' =>
array (size=0)
empty
protected 'guarded' =>
array (size=1)
0 => string '*' (length=1)
protected 'dates' =>
array (size=0)
empty
protected 'touches' =>
array (size=0)
empty
protected 'observables' =>
array (size=0)
empty
protected 'with' =>
array (size=0)
empty
protected 'morphClass' => null
public 'exists' => boolean true
I am expecting that $firm->firm_status (method call or not, whichever way will work) will allow me to access the specified firm status, but $firm->firm_status results in null.
First off, you won't see anything in var_dump($firm) result unless you load the relation.
Next thing - Eloquent requires you to use camelCased methods for relations, if you want to work with dynamic methods (call $model->relation).
So you need:
public function firmStatus()
{
return $this->belongsTo('FirmStatus', 'firm_status_id');
}
then you can access it:
$firm->firmStatus; // FirmStatus model | null
$firm->firm_status; // this will be translated to firmStatus anyway, but not other way around
and to view it in your call:
$firm = Firm::with('firmStatus')->first();
var_dump($firm);
// but better use toArray(), since it's easier to read
dd($firm->toArray());
If a firm can have a single status, use hasOne() instead of belongsTo():
class Firm extends Eloquent {
public function firm_status()
{
return $this->hasOne('FirmStatus', 'firm_status_id', 'firm_status_id');
}
}
If you need to query all of the firms with a given status, add the inverse relationship to FirmStatus:
class FirmStatus extends Eloquent {
public function firm()
{
return $this->hasMany('Firm', 'firm_status_id', 'firm_status_id');
}
}

Resources