I am currently in the process of updating old projects from cakephp 3.1.3 to 3.7.4.
For one of the projects I got the error
"_joinData" is missing from the belongsToMany results
I was unable to find any explanation to that specific error and since I am relatively new to PHP and CakePHP. and usually don't do much with databases I am currently a littlebit stuck despite lot's of information's about associations and CakePHP tables in general.
The error happens after an first() call on an model, like
$foundInstances = $instances->find()
->where([
'type_id' => $instanceTypeId,
'id' => $this->otherModel->id
])
->contain(['Features'])
->enableHydration(false);
$this->instances->first()
In the model class the relationsa re simply set like this:
$this->belongsToMany('BackendFeatures', [
'setForeignKey' => 'instance_id',
'setTargetForeignKey' => 'backend_feature_id',
'joinTable' => 'backend_features_instances'
]);
$this->belongsToMany('Features', [
'setForeignKey' => 'instance_id',
'setTargetForeignKey' => 'feature_id',
'joinTable' => 'features_instances'
]);
Can someone maybe give me an hint what i have to be looking for?
Related
I have 2 models: Order and Product, each has belongsToMany with pivot set properly.
In OrderCrudController, I also use FetchOperation and make a fethProducts() function as below:
use \Backpack\CRUD\app\Http\Controllers\Operations\FetchOperation;
public function fetchProducts()
{
return $this->fetch([
'model' => \App\Models\Product::class,
'searchable_attributes' => ['name','sku']
]);
// return $this->fetch(\App\Models\Product::class); <-- I also tried this one
}
protected function setupCreateOperation()
{
CRUD::setValidation(OrderRequest::class);
// other fields
$this->crud->addField([
'name' => 'products',
'type' => 'relationship',
'pivotSelect' => [
'attribute' => 'name',
'ajax' => true,
],
'subfields' => [
[
'name' => 'quantity',
'type' => 'number',
],
],
]);
}
But it comes to unexpected behavior when I search the product, the select2 field remains "searching" though the request successfully retrieved the data.
screenshot - select2 field
screenshot - ajax results
PS: this field works perfectly without subfields, no vendor overrides etc., so I think I've set everything correctly.
Anyone can help?
This was asked two months ago but somehow I missed it, just noticed it today after someone opened an issue on the GitHub repository.
I am happy you guys found a solution for it but unfortunatelly I cannot recommend it as using the select2_from_ajax will miss the functionality to don't allow the selection of the same pivots twice, otherwise you will have undesired consequences when saving the entry.
I've just submitted a PR to fix this issue, I will ping you guys here when it's merged, probably by next Monday.
Cheers
I just came accross this exact problem and after quite some research and trials, i finally found a solution !
The problem seems to be related to the relationship field type inside the pivotSelect. Try to use select2_from_ajax instead and don't forget to set method to POST explicitly, that worked for me like a charm.
Here is what you might try in your case :
$this->crud->addField([
'name' => 'products',
'type' => 'relationship',
'pivotSelect' => [
'attribute' => 'name',
'type' => 'select2_from_ajax',
'method' => 'POST',
'data_source' => backpack_url('order/fetch/products') // Assuming this is the URL of the fetch operation
],
'subfields' => [
[
'name' => 'quantity',
'type' => 'number',
],
],
]);
I have this nested relation im abit unsure how i assertJson the response within the phpunit test.
FilmController
public function show(string $id)
{
$film = Film::with([
'account.user:id,account_id,location_id,name',
'account.user.location:id,city'
])->findOrFail($id);
}
FilmControllerTest
public function getFilmTest()
{
$film = factory(Film::class)->create();
$response = $this->json('GET', '/film/' . $film->id)
->assertStatus(200);
$response
->assertExactJson([
'id' => $film->id,
'description' => $film->description,
'account' => $film->account->toArray(),
'account.user' => $film->account->user->toArray(),
'account.user.location' => $film->account->user->location->toArray()
]);
}
Obviously this isnt working because its returning every column for the user im a little unfamiliar with how you test nested relations with the code you need so im unsure with a toArray can anyone help out?
Testing is a place where you throw DRY (don't repeat yourself) out and replace it with hard coded solutions. Why? simply, you want the test to always produce the same results and not be bound up on model logic, clever methods or similar. Read this amazing article.
Simply hard code the structure you expect to see. If you changed anything in your model to array approach, the test would still pass even thou your name was not in the response. Because you use the same approach for transformation as testing. I have tested a lot of Laravel apps by now and this is the approach i prefers.
$account = $film->account;
$user = $account->user;
$location = $user->location;
$response->assertExactJson([
'description' => $film->description,
'account' => [
'name' => $account->name,
'user' => [
'name' => $user->name,
'location' => [
'city' => $location->city,
],
],
],
]);
Don't test id's the database will handle those and is kinda redundant to test. If you want to check these things i would rather go with assertJsonStructure(), which does not assert the data but checks the JSON keys are properly set. I think it is fair to include both, just always check the JSON structure first as it would likely be the easiest to pass.
$response->assertJsonStructure([
'id',
'description',
'account' => [
'id',
'name',
'user' => [
'id',
'name',
'location' => [
'id',
'city',
],
],
],
]);
I am trying to use bindModel in cakephp 3.x using below code:
$this->Member->bindModel([
[
'hasMany'=>[
'NpoMember' =>[
'className' => 'NpoMember',
'foreignKey' => 'member_id',
'conditions' => ['NpoMember.status' => 'Active'],
]
]
]
]);
but it is throwing error. Please suggest the correct syntax to bindmodel in controller in cakephp 3.x
It will work using contains after adding association in model. then you can add any number of binding using contain and . operator example:
$getPlaylistItems= $this->MyPlaylists->find()->where(['user_id'=>$_POST['user_id'],'section'=>$_POST['section']])
->contain(['PlaylistItems','PlaylistItems.DbArtists'])
->hydrate(false)->toArray();
I read a book Pactpub Web Application Development with Yii and PHP Nov 2012. Faced with such a problem, I can not understand the logic behind the use of relations (). Here diagram tables in the database:
You need to insert code in the model:
Issue model:
...
'requester' => array(self::BELONGS_TO, 'User', 'requester_id'),
'owner' => array(self::BELONGS_TO, 'User', 'owner_id'),
'project' => array(self::BELONGS_TO, 'Project', 'project_id'),
);
...
Project model:
...
'issues' => array(self::HAS_MANY, 'Issue', 'project_id'),
'users' => array(self::MANY_MANY, 'User', 'tbl_project_user_assignment(project_id, user_id)'),
...
I can not understand that we add? If the model Issue understand everything, then the model Project - I do not understand that we are adding. Help to understand ...
If the model Issue understand everything, then the model Project - I
do not understand that we are adding
in some case, you have already had a project, and you would like to find all of issues and partner users of that project.
$project = Project::model()->findByPK(1); // get project id=1
$issues = $project->issues; // get all of issues of project id=1, the result would be array
$users = $project->issues; // get all of users of project id=1, the result would be array
$project = Project::model()->with('issues', 'users')->findAll(); // get all of projects which has issue and user
//you have a user name ABC, and you want to find all of projects which contains a issue from owner has that user name.
$projects = Project::model()->with(array(
'issues' => array(
'alias' => 'issue',
//'condition' => '',
//'params' => array(),
'with' => array(
'owner'=>array(
'alias' => 'user',
'condition' => 'username =:username',
'params' => array(':username'=>'ABC'),
)
)
),
))->findAll();
There has many ways let you mix them up with multiple relations and conditions. One of above example would generate some big SQL SELECT query that I never want to deal with on my own :)
AR Relations Details
I've been doing the SYMFONY jobeet tuto(day 10) and once in the FORMS section, I found that some times we use :
'category_id' => new sfWidgetFormDoctrineChoice(array('model' => $this->getRelatedModelName('JobeetCategory'), 'add_empty' => false)),
and sometimes we use simply
'jobeet_affiliates_list' => new sfWidgetFormDoctrineChoice(array('multiple' => true, 'model' => 'JobeetAffiliate')),
Can anyboody explain to me WHY? and HOW is it working ?
why ,sometimes,do we use getRelatedModelName?? and why somtimes 'model' => 'myModel'???
Pretty much same thing, but, you can only use getRelatedModelName when there's a relation between the current form's model and the model you need in your widget. For example, if there's a relation defined between Article and Category, you can use getRelatedModelName('Category') in ArticleForm (usually a relation is defined).
In both cases (when a relation exists/does not exist) you can just write the model as a string 'model' => 'JobeetAffiliate'. I usually do that.