Laravel Property [nameOfProperty] does not exist on this collection instance - relationship

I am fetching a user in Laravel along with it's relation; competitionResults.
$user = User::where('id', Auth::user()->id)->with('competitionResults')->get();
I now want to check if competitionResults is empty, because it is returning this error: Property [competitionsResults] does not exist on this collection instance.
I've tried
if ($user->competitionResults()->exists()) {...}
if ($user->competitionResults()->isNotEmpty()) {...}
if (count($user->competitionResults)) {...}
But they all return the same error.
How does one check wether the relation data is empty?

You're checking if the property exists on the collection, rather than the Model. Use first() instead of get() to return an instance of the User class.

Related

laravel Model returns null on calling another function from same model

I have a Product Model in which I have a attribute function which return certain data.
Normally if I call it with Product::with(['attributes'])->active()->paginate(config('app.rec_limit')); I get the output.
but I am not able to access that or any other function data in model if I do this,
protected $appends = ['product_attributes'];
public function getProductAttributesAttribute() {
return $this->attributes();
}
public function attributes() {
return $this->hasMany(ProductAttribute::class);
}
also if I pass a string in the getProductAttributesAttribute function I get that string as output.
What can be the reason here for an empty array as output?
Modify your code: return $this->attributes(); returns an eloquent object, not a collection, as if you still want to perform other queries. Change to return $this->attributes; which returns a collection
Note that using this means attributes are fetched for each Product Model, which can lead to performance issues later on.
The ideal way is to leave it as a model relationship, then call it only when you need it

Getting Collection of particular Type with Hybris ModelService

Hiy!
I want all objects(rows in Test Type) with ModelService
So I could iterate through collection and update a Single row (object)'s attribute with new value
I see getModelService.create(TestModel.class) and getModelService.save()
but will they not create a new object/row rather than update a existing object?right
I don't want to create a new one rather selecting one of the existing matching my criteria and update one attribute of that
can somebody help with List<TestModel> testModels = getModelService.get(TestModel.class) will that return me all rows (collection) of Test Type/Table?
unfortunately I can't test it so need help
Actually I am in validateInterceptor ... and on the basis of this intercepted model changed attribute value I have to update another model attribute value...
thanks
ModelService.create(new TestModel.class) will create a single instance of the specified type and attach it to the modelservice's context.
But it will only be saved to the persistence store when you call modelService.save(newInstance)
ModelService.get() returns a model object but expects a Jalo object as input, (Jalo being the legacy persistence layer of hybris) so that won't work for you.
To retrieve objects you can either write your own queries using the FlexibleSearchService or you can have a look at the DefaultGenericDao which has a bunch of simple find() type of methods.
Typically you would inject the dao like e.g.:
private GenericDao<TestModel> dao;
[...]
public void myMethod()
{
List<TestModel> allTestModels = dao.find();
[...]
}
There are a lot more methods with which you can create WHERE type of statements to restrict your result.
Regarding ValidateInterceptor:
Have a look at the wiki page for the lifecycle of interceptors:
https://wiki.hybris.com/display/release5/Interceptors
It's not a good idea to modify 'all' objects of a type while being an interceptor of that type.
So if you're in an interceptor declared for the Test item type, then don't try to modify the items there.
If you happen to be in a different interceptor and want to modify items of a different type:
E.g. you have Type1 which has a list of Type2 objects in it and in the interceptor for Type1 you want to modify all Type2 objects.
For those scenarios you would have to add the instances of Type2 that you modify to the interceptor context so that those changes will be persisted.
That would be something like:
void onValidate(Test1 model, InterceptorContext ctx) throws InterceptorException
{
...
List<Type2> type2s = dao.find();
for (Type2 type2 : type2s)
{
// do something with it
// then make sure to persist that change
ctx.registerElementFor(type2, PersistenceOperation.SAVE);
[...]
}
}
First of all - i think it's not a good idea, to create/update models in any interceptor, especially in 'validation' one.
Regarding your question:
ModelService in most of the cases works with single model, and
designed for create/update/delete operations.
To retreive all models of certain type, you have to use FlexibleSearchService
Then to update each retrieved TestType model, you can use ModelService's save method.
A query to retreive all TestType models will look like:
SELECT PK FROM {TestType}
You could simply use the Flexible Search Service search by example method, and the model service to save them all. Here is an example using Groovy script, with all products :
import java.util.List
import de.hybris.platform.core.model.product.ProductModel
import de.hybris.platform.servicelayer.search.FlexibleSearchService
import de.hybris.platform.servicelayer.model.ModelService
FlexibleSearchService fsq = spring.getBean("flexibleSearchService")
ModelService ms = spring.getBean("modelService")
ProductModel prd = ms.create(ProductModel.class)
List<ProductModel> products = fsq.getModelsByExample(prd)
//Do Whatever you want with the objects in the List
ms.saveAll(products)

adding required property option not working

I'm trying to add property options to my model. I have a StringProperty and I added required=True but I'm still able to create an object with the required field being empty.
I tried it in the admin and also in my update form for the specific model so not sure what I'm doing wrong?
You can create it, but can you put it?
class x(ndb.Model):
author = ndb.StringProperty(required=True)
a = x()
a.put()
Fails with: BadValueError: Entity has uninitialized properties: **author**
Setting a value on the required property author allows you to save it:
a.author = "some_value"
The put can now succeed.
key = a.put()
and key is now:
Key('x', 5707702298738688)
or even key.urlsafe()
ahNzfnNoYXJlZC1wbGF5Z3JvdW5kcg4LEgF4GICAgICArpkKDKIBEDYwNTM4Njc2MzY2NTQwODA
Read more about storing data here.

Calling a model method from the controller in CakePHP

Is there no way to access a Model instance as an object (as opposed to as an array) within a Model method in CakePHP? As a super-simplified example, my instinct tells me it ought to be possible to do something like this:
Bird.php
...
public function specialName()
{
$name = $this->name;
return "Oh wow! It's ".$name;
}
If I call this method from my BirdController.php like so:
public function view($id) {
if (!$id) {
throw new NotFoundException(__('Invalid bird'));
}
$this->Bird->id = $id;
$this->set('results', $this->Bird->specialName());
}
... then it displays in the view file as "Oh wow! It's Bird" rather than "Oh wow! It's Freddy" (i.e. the name of the model, not the name of the model instance).
I've tried variations on this general approach, to no avail. It seems I must access the information via an array, like so:
Bird.php
...
public function specialName($id)
{
$data = $this->findById($id);
$name = $data['Bird']['name'];
return "Oh wow! It's ".$name;
}
This seems WAY over-complicated to me. What am I missing? Ultimately I want to be able to access dependent models in my model function, e.g. get all of the associated Bird->Subspecies. It seems like this would be much easier to do working with objects.
If you would have read the documentation about models you would know that Model::$name is the name of the model. There is also Model::alias which is the name of the model when it is accessed trough associations and the association is named different than the model name.
Cakes ORM does not return results as data objects, 3.0 will do that. Most easy way to return a specifc field right now is to do this in a model:
public function specialName($id) {
$this->id = $id;
return $this->field('name');
}
Also the "Oh wow..." should go to the view where you would echo the name that you set as $result.
If you want data objects, I know there is a plugin, a behaviour that will turn the result sets into data objects. Just google it.
Ultimately I want to be able to access dependent models in my model
function, e.g. get all of the associated Bird->Subspecies.
Did you read the book? See this section. With containable you can control what exactly you want to fetch from the associated models.
I recommend you to do the blog tutorial first to get an idea of the basics of how CakePHP works.

CakePHP Model Callback, specifically beforeDelete

I'm trying to execute some logic before deleting a field. I have some models that are dependent on the model being deleted, and I want to make sure that image files related to those dependent models are also deleted, but I'm a bit confused on how the model callbacks work.
I know that I define the before Delete function in the model class, but How do I access the data in the current model or dependent models being deleted?
function beforeDelete() {
}
I'm just a little confused as how to use these callbacks, and I haven't seen any great documentation out there.
Edit:
After adding this to the parent model, it seems to always return false.
function beforeDelete() {
if ($this->DependentModel->find('count', array('conditions' => array('DependentModel.parent_id' => $this->id))) == 1){
return true;
} else{
return false;
}
}
Should be obvious what I'm trying to do here. If there is one entry of the dependent model present in the table, return true and continue the deletion. I made sure that there is in fact one table entry that is dependent on the object being deleted. When I execute the delete action it always returns false. What's going on here?
When using callbacks, you can refer to the API for the class you are extending to check the parameters it accepts. Your implementation should accept, at minimum, the same parameters as the methods you are overriding.
For example, Model::beforeDelete is implemented like so:
/**
* Called before every deletion operation.
*
* #param boolean $cascade If true records that depend on this record will also be deleted
* #return boolean True if the operation should continue, false if it should abort
* #link http://book.cakephp.org/2.0/en/models/callback-methods.html#beforedelete
*/
public function beforeDelete($cascade = true) {
return true;
}
And also, ModelBehavior::beforeDelete is implemented like this (ie. when making a behavior):
/**
* Before delete is called before any delete occurs on the attached model, but after the model's
* beforeDelete is called. Returning false from a beforeDelete will abort the delete.
*
* #param Model $model Model using this behavior
* #param boolean $cascade If true records that depend on this record will also be deleted
* #return mixed False if the operation should abort. Any other result will continue.
*/
public function beforeDelete(Model $model, $cascade = true) {
return true;
}
Next, it is useful to know that when saving to a model and passing in the controller's data (ie. $this->data in the controller) that data is set to the model (ie. $this->data in the model). [This happens during Model::save(), currently on line 1225.]
In the case of the first example you can access the model using $this and in the second example you can access the model using $model (as $this would be the behavior in that context). So to get at the data, you want to use $this->data or $model->data. You can also access that model's related models using chaining (ie. $this->RelatedModel or $model->RelatedModel).
As the docblock comments state, $cascade should let you know if this is a cascading delete that is happening (true by default) in case your code needs to take different actions when this is or isn't the case; and your implementation of the method should return false if you want to abort the save operation (otherwise, return true when you are done).
There is a Media plugin for CakePHP which implements this exact functionality that can be used as a reference.

Resources