Recursive relationship with scope - sql

A user has a sponsor:
public function sponsor()
{
return $this->belongsTo(User::class, 'sponsor_id');
}
A user has referrals:
public function referrals()
{
return $this->hasMany(User::class, 'sponsor_id');
}
A user is considered capped when they have 2 or more referrals:
public function activeReferrals()
{
return $this->referrals()->whereActive(true);
}
public function isCapped()
{
return $this->activeReferrals()->count() >= 2;
}
A user can give points. By default, the sponsor will receive them, but if the sponsor is capped, I want the points to go to a sponsor's referral that is NOT capped. If all the referrals are capped, then it does the same thing with the level below (the referral's referrals).
If I go user by user making database calls for each one, it's gonna take a long time. How can I write a scope that makes recursive calls until it finds the first active referral in the tree that's not capped?
This is what I'm trying to do:

Please give this a try... I believe this will work for you :)
public function scopeNotCappedActiveReferrals($query, $count) {
return $query->withCount(['referrals' => function($q) {
$q->where('active', true);
}])->where('referrals_count', '<', $count);
}
For the second part...
// Finally you can call it with
public function allReferrals() {
$users = User::notCappedActiveReferrals(2)->get();
$allUsers = $this->findNotCappedActiveReferralsRecurrsively($users);
}
// Do not place this function in the model,
// place it in your Controller or Service or Repo or blahblah...
// Also, not tested... but should work :)
protected function findNotCappedActiveReferralsRecurrsively($users) {
if(!count($user)) {
return $users;
}
foreach($users as $user) {
$moreUsers = $user->notCappedActiveReferrals(2)->get();
return $users->merge($this->findNotCappedActiveReferralsRecurrsively($moreUsers));
}
}
Hope this is what you need :)

Related

How to check permissions in my controller

I'm new to Laravel and I'm writing a user management System on my own.
At this time,
I can CRUD permissions, roles and users,
I can check the permissions by the AuthServiceProvider#boot method like this:
public function boot()
{
Gate::before( function (User $user , $permission) {
// App administrator
if($user->getPermissions()->contains('appAll'))
{
return true;
}
// Permission check
return $user->getPermissions()->contains($permission);
});
}
In my AdminUserController, I can check the permissions like that:
public function index()
{
if( Gate::check('createUser') || Gate::check('readUser') || Gate::check('updateUser') || Gate::check('deleteUser')) {
return view('userMgmt/users/index', [
'users' => User::getUsersWithRolesWithTexts()
]);
}
else
{
return redirect(route('home'))->withErrors('You do not have required permission');
}
}
That is working well.
BUT
Is this the right way to wrap each controller method with:
if( Gate::check(...) ...) {
//Do what the method is supposed to do
}
else
{
return redirect(route('SOME.ROUTE'))->withErrors('SOME ERROR OCCURRED');
}
It would be nice if someone can give me some ideas.
Tank you
There is a controller helper function named authorize that you can call from any method in a controller that extends App\Http\Controllers\Controller. This method accepts the action name and the model, and it will throw an exception if the user is not authorized. So instead of the if...else statement, it will be one line:
public function update(Request $request, Post $post)
{
$this->authorize('update', $post);
// The current user can update the blog post...
}

Flatten laravel nested relationship (parent to descendants) get all childerns

This is my Controller
$categoryIds = Category::select('id')->with('childrenRecursive')->where('id', 1)->get();
Ad::whereIn('category_id', $categoryIds)->get();
This is my model
public function parent() {
return $this->belongsTo(Category::class, 'parent_id');
}
public function childs() {
return $this->hasMany(Category::class, 'parent_id');
}
public function Ads() {
return $this->hasManyThrough(Ad::class, Category::class, 'parent_id', 'category_id', 'id');
}
How get all childern categories ides
I solved this problem with this solution
My Controller
public function index()
{
$parent = Category::with('descendants')->find(1);
$descendants = $this->traverseTree($parent, collect([1]));
$ads = Ad::whereIn('category_id',$descendants)->get();
return response($ads);
}
protected function traverseTree($subtree, $des)
{
$descendants = $des;
if ($subtree->descendants->count() > 0) {
foreach ($subtree->descendants as $descendant) {
$descendants->push($descendant);
$this->traverseTree($descendant, $descendants);
}
}
return $descendants;
}
I'd do it with Laravel's Subqueries approach.
$parentId = 4;
Ad::whereIn('category_id', function($q) use ($parentId) {
$q->select('id')
->from('categories')
->where('parent_id', $parentId);
});
If you want to add the parent model, you can chain with():
Ads::whereIn('category_id', function($q) use ($parentId) {
$q->select('id')
->from('categories')
->where('parent_id', $parentId);
})
->with('category.parent')
->get();
Your code chunks are not clear so you may need to tweak my code example.
If I understand your question properly you need to get ads corresponding to id's of all related records also, for a given category record.
$category = Category::with('childs:id,parent_id')
->where('id', 1)
->firstOrFail();
$categoryIds = collect([$category->parent_id, $category->id]);
$category->childs->map(fn($child) => $categoryIds->push($child->id));
$ads = Ads::whereIn('category_id', $categoryIds->filter()->all())
// Can eager load the product(s) if needed
//->with('products')
->get();

How to do WaitAll with Akka.Net?

I have a hierarchy of actors in Akka.Net and am wondering whether I've chosen the right way to do something, or if there are better/simpler ways to achieve what I want.
My specific example is that I'm constructing a User actor in response to a user logging into the system, and when constructing this actor there are two pieces of data I need in order to complete the construction of the actor.
If this were regular .NET code I might have something like the following...
public Task<User> LoadUserAsync (string username)
{
IProfileService profileService = ...;
IMessageService messageService = ...;
var loadProfileTask = profileService.GetUserProfileAsync(username);
var loadMessagesTask = messageService.GetMessagesAsync(username);
Task.WaitAll(loadProfileTask, loadMessagesTask);
// Now construct the user from the result of both tasks
var user = new User
{
Profile = loadProfileTask.Result,
Messages = loadMessagesTask.Result
}
return Task.FromResult(user);
}
Here I use WaitAll to wait for the subordinate tasks to complete, and let them run concurrently.
My question is - if I wanted to do the same in Akka.Net, would the following be the most regular way to do this? Pictorially I've created the following...
When I create my User actor, I then construct a (temporary) User Loader Actor, whose job it is to get the full user details by calling to the Profile actor and the Messages actor. The leaf actors that get the data are as follows...
public class UserProfileLoader : ReceiveActor
{
public UserProfileLoader()
{
Receive<LoadUserRequest>(msg =>
{
// Load the user profile from somewhere
var profile = new UserProfile();
// And respond to the Sender
Sender.Tell(profile);
Self.Tell(PoisonPill.Instance);
});
}
}
public class UserMessagesLoader : ReceiveActor
{
public UserMessagesLoader()
{
Receive<LoadUserRequest>(msg =>
{
// Load the messages from somewhere
var messages = new List<Message>();
// And respond to the Sender
Sender.Tell(messages);
Self.Tell(PoisonPill.Instance);
});
}
}
It doesn't really matter where they get the data from for this discussion, but both simply respond to a request by returning some data.
Then I have the actor that coordinates the two data gathering actors...
public class UserLoaderActor : ReceiveActor
{
public UserLoaderActor()
{
Receive<LoadUserRequest>(msg => LoadProfileAndMessages(msg));
Receive<UserProfile>(msg =>
{
_profile = msg;
FinishIfPossible();
});
Receive<List<Message>>(msg =>
{
_messages = msg;
FinishIfPossible();
});
}
private void LoadProfileAndMessages(LoadUserRequest msg)
{
_originalSender = Sender;
Context.ActorOf<UserProfileLoader>().Tell(msg);
Context.ActorOf<UserMessagesLoader>().Tell(msg);
}
private void FinishIfPossible()
{
if ((null != _messages) && (null != _profile))
{
_originalSender.Tell(new LoadUserResponse(_profile, _messages));
Self.Tell(PoisonPill.Instance);
}
}
private IActorRef _originalSender;
private UserProfile _profile;
private List<Message> _messages;
}
This just creates the two subordinate actors, sends them a message to get cracking, and then waits for both to respond before sending back all the data that's been gathered to the original requestor.
So, does this seem like a reasonable way to coordinate two disparate responses, in order to combine them? Is there an easier way to do this than craft it up myself?
Thanks in advance for your responses!
Thanks folks, so I've now simplified the actor significantly into the following, based on both Roger and Jeff's suggestions...
public class TaskBasedUserLoader : ReceiveActor
{
public TaskBasedUserLoader()
{
Receive<LoadUserRequest>(msg => LoadProfileAndMessages(msg));
}
private void LoadProfileAndMessages(LoadUserRequest msg)
{
var originalSender = Sender;
var loadPreferences = this.LoadProfile(msg.UserId);
var loadMessages = this.LoadMessages(msg.UserId);
Task.WhenAll(loadPreferences, loadMessages)
.ContinueWith(t => new UserLoadedResponse(loadPreferences.Result, loadMessages.Result),
TaskContinuationOptions.AttachedToParent & TaskContinuationOptions.ExecuteSynchronously)
.PipeTo(originalSender);
}
private Task<UserProfile> LoadProfile(string userId)
{
return Task.FromResult(new UserProfile { UserId = userId });
}
private Task<List<Message>> LoadMessages(string userId)
{
return Task.FromResult(new List<Message>());
}
}
The LoadProfile and LoadMessages methods will ultimately call a repository to get the data, but for now I have a succinct way to do what I wanted.
Thanks again!
IMHO that's a valid process, as you fork action and then join it.
BTW you could use this.Self.GracefulStop(new TimeSpan(1)); instead of sending poison pill.
You could use a combination of Ask, WhenAll and PipeTo:
var task1 = actor1.Ask<Result1>(request1);
var task2 = actor2.Ask<Result2>(request2);
Task.WhenAll(task1, task2)
.ContinueWith(_ => new Result3(task1.Result, task2.Result))
.PipeTo(Self);
...
Receive<Result3>(msg => { ... });

Get All Property's From A User in Flash CS2

I have this:
public function saveProfile() {
this.setProperty("picture",factory.getClass("userProfile").getProperty("picture"),"no");
this.setProperty("gender",factory.getClass("userProfile").getProperty("gender"),"no");
this.setProperty("state",factory.getClass("userProfile").getProperty("state"),"no");
this.setProperty("city",factory.getClass("userProfile").getProperty("city"),"no");
this.setProperty("marital",factory.getClass("userProfile").getProperty("marital"),"no");
this.setProperty("about",factory.getClass("userProfile").getProperty("about"),"no");
}
factory.getClass("userProfile") functions:
public function setProperty(property:String, value:String) {
_profile[property] = value;
}
public function getProperty(property:String) {
if (_profile[property] == undefined) {
return "";
}
return _profile[property];
}
what i wanna do is:
this getProperty - setProperty returns the values from a specific user.
I want to get the properties from another user ex:
public function saveProfile(username:String) {
this.setProperty("picture",factory.getClass("userProfile").getProperty("picture"),"no"); ->
from the user username:String i ask to
etc...
}
If anyone can help me to change the getProperty, setProperty functions in the userprofile class to give me the property's from the username i ask.
Thanks a lot!
Regards

Return View() or PartialView()? How to decide?

I hava an Action:
public ActionResult GetOrders(int id)
{
...
}
When I access it through hyperlink(~/Order/GetOrders/1), I want GetOrder return View(), the whole page.
When through #Html.Action("GetOrders"), I want it return PartialView() to be a part of a page.
Now i settled the problem using Erik Philips's method.
public ActionResult GetOrders(int id)
{
var orders = db.Order.Where(a => a.AdCompanyID == id).ToList();
ViewBag.AdCompanyName = db.AdCompany.Where(a => a.ID == id).Select(a => a.Name).First().ToString();
if (ControllerContext.IsChildAction)
{
ViewBag.isPartial = true;
return PartialView(orders);
}
ViewBag.isPartial = false;
return View(orders);
}
#{Html.RenderAction("GetOrders", new { id = Model.ID });}
#Html.ActionLink("Related orders", "GetOrders", new { id = item.ID })
in GetOrders.cshtml:
#if (ViewBag.isPartial == false)
{
...
}
to generate different view.
Queti M. Porta thanks all the same!
You can use the ControllerContext.IsChildAction.
public ActionResult Foo()
{
if (ControllerContext.IsChildAction)
{
return PartialView("GetOrdersPartial", model);
}
return View("GetOrders", model);
}
Also, I would recommend using Html.RenderAction.
Updated per Comment
I'd also mention that I've never had the need to do this, in my own experience. Either you really have a completely different view, or you are unaware that PartialView will return a view without a Layout.
An easy way would be to pass in a parameter into the action method to let it know how you want the view rendered.
public ActionResult GetOrders(int id, bool? isPartial)
{
return (isPartial.HasValue() && isPartial.Value)
? PartialView()
: View();
}
In the above example, we are passing in the isPartial, however, you can also check to see if the request was done via ajax using Request.IsAjaxRequest
Other than that, there aren't many other ways to determine the method of the request.