Using Scopes on the Load method not working - eloquent

Is there a way to abstract this Closure to my MerchantUser model in a way similar to using scopes on with()?
So far I have this which works:
$merchant_user->load(['permissions' => function ($query) use ($merchantId) {
if ($merchantId) {
$query->where('merchant_user_permission.merchant_id','=', $merchantId);
}
}]);
But I'd like to do something like this:
$merchant_user->loadPermissions($merchantId);
In my Model:
public function scopeLoadPermissions($query, $merchantId = null)
{
return $query->load(['permissions' => function ($q) use ($merchantId) {
if ($merchantId) {
$q->where('merchant_user_permission.merchant_id','=', $merchantId);
}
}]);
}
Which at the moment just returns an error:
"Method Illuminate\Database\Query\Builder::load does not exist."

For this case you dont need add scope. Instead if you can add this function in your model
public function loadPermissions($merchantId = null)
{
return $this->load(['permissions' => function ($q) use ($merchantId) {
if ($merchantId) {
$q->where('merchant_user_permission.merchant_id','=', $merchantId);
}
}]);
}
and usage
$merchant_user->loadPermissions($merchantId);

Related

Yii2: How to merge to relations as one

I have two relations
public function getAnnounceComments()
{
return $this->hasMany(AnnounceComment::className(), ['user_id' => 'id']);
}
public function getAnnounceRates()
{
return $this->hasMany(AnnounceRate::className(), ['user_id' => 'id']);
}
How can I merge User's two relations as one on same announce_id then I can call this like
$user->commentAndRate->comment or $user->commentAndRate->rate
I did like that:
Added this relation to AnnounceComment model:
public function getRate()
{
return $this->hasOne(AnnounceRate::className(), ['announce_id' => 'announce_id']);
}
And when I call User did like this:
$user = User::find()->with('announceComments.rate')->where('id=1')->one()
Then I can easily call :
foreach ($model->announceComments as $key => $comment) {
echo $comment->text . $comment->rate->count`
}
I wait for better answers :)

How to access other function in UI5 custom control/type?

I defined many custom type in Utils.js: http://plnkr.co/edit/BGqDoWEC7DTmomEFHygd?p=catalogue
I want to add trim() in parseValue
parseValue: function (oValue) {
if(oValue !== null) {
return oValue.trim();
}
return oValue;
},
Copy and paste this function is kind of dumb, so I want to do sth. like :
trimString : function(oValue) {
if(oValue !== null) {
return oValue.trim();
}
return oValue;
},
mandatoryValueType : SimpleType.extend("text", {
formatValue: function (oValue) {
return oValue;
},
parseValue: this.trimString,
validateValue: function (oValue) {
if (!oValue) {
throw new ValidateException(Utils.i18n("MANDATORY_VALIDATE_ERROR"));
}
}
}),
But scope in mandatoryValueType seems can not access to this.trimString, what can I do?
this scope in parseValue function, no trimString function:
Another working sample : http://plnkr.co/edit/ahS6NlUHHL0kdvdddvgd?p=preview
Reference: https://sapui5.hana.ondemand.com/#/sample/sap.m.sample.InputChecked/preview
Maybe you can put the trimString function outside the var Utils object, and set it as a global function.
here is the example: http://plnkr.co/edit/u64DEP0RnT5CJADZyXJg?p=catalogue
edit:
corrected by #boghyon, the trimString function should be a function in a closure, instead of a global function :)
in this case the this keyword contains the object which invokes the function: the controller which invokes mandatoryValueType of utils.js.
initialise in utils.js in the upper scope of mandatoryValueType a var that = this. then use inside of mandatoryValueType instead of this.trimString the that.trimString.
edit
self reference to a property of an object in a literal declaration of an object:
var Utils = {
...
trimString: function() {
...
},
...
parseValue: function() {
this.trimString();
}
..
}

How to use node-simple-schema reactively?

Given that there is not much examples about this, I am following the docs as best as I can, but the validation is not reactive.
I declare a schema :
import { Tracker } from 'meteor/tracker';
import SimpleSchema from 'simpl-schema';
export const modelSchema = new SimpleSchema({
foo: {
type: String,
custom() {
setTimeout(() => {
this.addValidationErrors([{ name: 'foo', type: 'notUnique' }]);
}, 100); // simulate async
return false;
}
}
}, {
tracker: Tracker
});
then I use this schema in my component :
export default class InventoryItemForm extends TrackerReact(Component) {
constructor(props) {
super(props);
this.validation = modelSchema.newContext();
this.state = {
isValid: this.validation.isValid()
};
}
...
render() {
...
const errors = this.validation._validationErrors;
return (
...
)
}
}
So, whenever I try to validate foo, the asynchronous' custom function is called, and the proper addValidationErrors function is called, but the component is never re-rendered when this.validation.isValid() is supposed to be false.
What am I missing?
There are actually two errors in your code. Firstly this.addValidationErrors cannot be used asynchronously inside custom validation, as it does not refer to the correct validation context. Secondly, TrackerReact only registers reactive data sources (such as .isValid) inside the render function, so it's not sufficient to only access _validationErrors in it. Thus to get it working you need to use a named validation context, and call isValid in the render function (or some other function called by it) like this:
in the validation
custom() {
setTimeout(() => {
modelSchema.namedContext().addValidationErrors([
{ name: 'foo', type: 'notUnique' }
]);
}, 100);
}
the component
export default class InventoryItemForm extends TrackerReact(Component) {
constructor(props) {
super(props);
this.validation = modelSchema.namedContext();
}
render() {
let errors = [];
if (!this.validation.isValid()) {
errors = this.validation._validationErrors;
}
return (
...
)
}
}
See more about asynchronous validation here.

Cannot read property 'subscribe' of undefined in nested calls in Angular 2

I want to subscribe in company-list.component on getCompanies() from the company.service. However I get the following error:
Cannot read property 'subscribe' of undefined
This is the code:
company.service.ts
getCompaniesOfUser() {
let r;
this.userService.getUser().subscribe(
res=> r = res,
err => console.log(err),
()=>(this.getCompaniesWithSpecificLink())
)
}
getCompaniesWithSpecificLink() {
if (isAdmin == false) {
url = '/user/companies';
} else {
url = '/companies';
}
return this.getCompanies(url);
}
getCompanies(url):Observable<Company[]> {
return this.http.get(this.host + url)
.map((res:Response) => res.json());
}
company-list.component.ts
companies:Company[];
public getTheCompanies() {
this._companyService.getCompaniesOfUser()
.subscribe(companies => this.companies = companies); <-- the error occurred here
}
Subscribe method must be used on an observable but your getCompaniesOfUser() method is not returning anything thus is a void method.
If you want to call back-to-back rest services. Like one's input depending on the others' output. You should use the flatMap operator.
Check this answer for example: https://stackoverflow.com/a/36712707/5706293
Something like this should work:
getCompaniesOfUser() {
return this.userService.getUser().flatMap( (resp) => {
return this.getCompaniesWithSpecificLink();
});
}

Is it possible to apply destructuring to storing a class method in a variable?

I have the following render method that calls another method in its class:
render() {
const isValidField = this.isValidField();
}
Is it possible - and if so is it a good idea - to use destructuring in this case to avoid repeating the method name in the variable?
I'm looking for something like this:
render() {
const { isValidField }() = this;
}
You could use a getter function:
get isValidField() {
return true;
}
render() {
const {isValidField} = this;
}