I use laravel framework . I have two table. users and points . that has one to many relationship between them.in points table saved many records related to a one user that keep all of the ponits we assign to this user.I want to keep sum this points to one field as sumpoints filed in user table.how can i do it in laravel
Do something like this in your Points model:
public static function boot()
{
parent::boot();
self::created(function($model){
$user = Auth::user();
$user->sumfields = Points::where('user_id',$user->id)->sum('points');
$user->save();
});
}
The self::created function gets called after a new instance of that model has been created.
However if this was my project, I would probably do what Ivan Jelev suggested to you (doing the sum only when you need it).
Related
I'm very much a beginner when it comes to database relationships hence what I suspect is a basic question! I have two database tables as follows:
Projects
id
company_id
name
etc...
rfis
id
project_id (foreign key is id on the Projects table above)
Number (this is the column I need help with - more below)
question
The relationships at the Model level for these tables are as follows:
Project
public function rfi()
{
return $this->hasMany('App\Rfi');
}
RFI
public function project()
{
return $this->belongsTo('App\Project');
}
What I'm trying to achieve
In the RFI table I need a system generated number or essentially a count of RFI's. Where I'm finding the difficulty is that I need the RFI number/count to start again for each project. To clarify, please see the RFI table below which I have manually created with the the 'number' how I would like it displayed (notice it resets for each new project and the count starts from there).
Any assistance would be much appreciated!
Todd
So the number field depends on the number of project_id in the RFI table. It is exactly the number of rows with project_id plus one.
So when you want to insert a new row, you calculate number based on project_id and assign it.
RFI::create([
'project_id' => $project_id,
'number' => RFI::where('project_id', $project_id)->count() + 1,
...
]);
What I understood is that you want to set the value of the "number" field to "1" if it's a new project and "increment" if it's an existing project. And you want to automate this without checking for it every time you save a new row for "RFI" table.
What you need is a mutator. It's basically a method that you will write inside the desired Model class and there you will write your own logic for saving data. Laravel will run that function automatically every time you save something. Here you will learn more about mutators.
Use this method inside the "RFI" model class.
public function setNumberAttribute($value)
{
if(this is new project)
$this->attributes['number'] = 1;
else
$this->attributes['number']++;
}
Bonus topic: while talking about mutators, there's also another type of method called accessor. It does the same thing as mutators do, but just the opposite. Mutators get called while saving data, accessors get called while fetching data.
How to select a single row on october cms?
How can a simple thing be so complicated here?
I thought it would be something to help us and not to disturb something that is as simple as
SELECT * FROM `engegraph_forms_membros`
Here it's like fighting against demons without a bible, oh god why?
Why make the query difficult for newbie?
I understand you don't speak English natively but you should watch every single one of these videos.
Does the record belong to a model in a plugin? Here are the docs on how to work with models.
You make a plugin, set the database which creates models, and then make components to be ran in your CMS Pages.
In a component.php file you can have something like this: Here I am calling the model class Agreements with use Author\Plugin\Models\Agreements;. This allows me to run a function/method to retrieve all agreements or one agreements using laravel's eloquent collection services.
Lets say we have the ID of a record. Well we can either call on the Agreements model with ::find or with ::where. You will noticed I have two functions that essentially do the same thing. ::find uses the primary key of the models (in my case the id) and will return a singular record. *Note that find can take an array and return a collection of records; like ::where. Using ::where we are going to look for the ID. *Note ::where always returns a collection which is why I have included ->first().
<?php namespace Author\Plugin\Components;
use Session;
use Input;
use Crypt;
use Db;
use Redirect;
use Illuminate\Contracts\Encryption\DecryptException;
use October\Rain\Support\Collection;
use Author\Plugin\Models\Agreements;
class GetAgreement extends \Cms\Classes\ComponentBase
{
public function componentDetails()
{
return [
'name' => 'Get one agreement',
'description' => 'Get an agreement to change or delete it'
];
}
public function onRun() {
$this->page['agreement'] = $this->getWithFindAgreement;
}
public function getWithFindAgreement() {
$id = 1;
$agreement = Agreements::find($id);
return $agreement;
}
public function getWithWhereAgreement() {
$id = 1;
$agreement = Agreements::where($id)->first();
return $agreement;
}
}
If for some reason you aren't working with models, here are the docs to work with Databases. You will have to register the use Db; facade.
Here call the table you want and use ::where to query it. *Note the use of ->first() again.
$users = Db::table('users')->get();
$user = $users->where('id', 1)->first();
There are two simple ways to select a single row:
This will give you the'first' record in the selected recordset.
SELECT top 1 * FROM `engegraph_forms_membros`
This will select all the records that meet the predicate requirement that the value of <columnname> is equal to <value>
SELECT * FROM `engegraph_forms_membros` where <columnname>=<value>
If you select a record where multiple values meet that requirement, then you can (randomly) pick one by combining the solutions...
SELECT top 1 * FROM `engegraph_forms_membros` where <columnname>=<value>
But be aware that without an ORDER BY clause, the underlying data is unordered and prone to change uncontrollably, which is why most people (including your boss) will find the use of 'Top' to be improper for real use.
I have two models with a simple 1-n relation (category and item with category_id). I would like to show how much items there is in the category. I would like to have the number cached rather then always doing the count, so I have an extra field in category table called "total_items_count".
How to best do this total count triggering, when to call the "countUpdate" function since the relation could change from several places (backend, api, frontend...).
My initial plan was to use AFTER_UPDATE event, but "link()" must be called after the item is stored in database (on adding new item at least) so then I do not know which category is the item related to. I also need to know the old category, in case item goes from one category to another. In the backend controller I am using $item->link('category', $categoryObj); as I might change this relation to n-n someday.
Any advice on how to have complete control if the link between item and category changes and then update the count for the old and new linked category?
Thanks
The first and most important thing you need to now, is that you need to update the category count field via the ActiveRecord::updateCounters() method, in order to prevent incorrect update from multiple places. So you can do one of those things:
In the category item model you can do the following:
public function save($runValidation = true, $attributeNames = null)
{
if (parent::save(runValidation, attributeNames)) {
$this->category->updateCounters(['total_items_count' => 1]);
return true;
}
return false;
}
Or you can write a centralized component (let's say app\components\Category) which you will call from the whole application. This component will have a method that saves an item. For example:
public function saveItem($category, $item)
{
if ($item->save()) {
$item->link('category', $category);
$category->updateCounters(['total_items_count' => 1]);
return true;
}
return false;
}
Of course, when you delete an item, you will call:
$category->updateCounters(['total_items_count' => -1]);
See the ActiveRecord::updateCounters() API
From the Yii2 documentation:
Note: If you use yii\db\ActiveRecord::save() to update a counter column, you may end up with inaccurate result, because it is likely the same counter is being saved by multiple requests which read and write the same counter value.
If you need to keep track of which is the old category, just create another column let's say "old_category" to the category item table and when you change the category of the item put the old category id there, and the new category id to the category_id column.
Does that helps? If you have any questions, please ask!
I have this setup as my database structure which already works pretty well, but I feel like it could be better, but cannot figure out how.
Database Structure:-
Events can have multiple sub-events. Users can join these events and optionally their sub-events. With this structure I have all constraints, but the one that links the event attending with the sub event attendings => there can be sub event attendings left without having the main event attending (this shouldn't be possible as users who don't attend the main event cannot attend it's sub events).
I am currently working with Laravel so it looks like this:
User:
hasMany Event (as organizer of these events)
belongsToMany EventAttending (which events is a user joining)
belongsToMany SubEventAttending (which sub-events is a user joining)
Event:
belongsTo User
hasMany SubEvent
belongsToMany EventAttending (which users are attending this event)
SubEvent:
belongsTo Event
belongsToMany SubEventAttending (which users are attending this sub-event)
The problem arises when trying to manage the sub-event attendings of a user. How would I make this constraint between the event and sub-event attendings exist, while keeping it clean with the capabilities of Laravel / What can you give as advice for a better structuring / How would you guys do it?
Edit
To clarify, the events and sub-events store different things, have different properties. Also I need to store information for the event attendings (like did he attend in real life) and sub-event attendings, most likely differing ones.
Edit
Edward Haber has the better structure, but as my two pivot tables (the connection between User-Event and User-SubEvent) store additional diferent type of information, currently chose to remain with the initial design.
One of the biggest problems I am facing (which does exist with both structure) is querying for a User while getting the attended Events with the attended SubEvents. Trying to achive this result:
User[]:{
...,
attending_events[]:{
...,
attending_sub_events[]:{
...
}
}
}
Been thinking for hours for a clean solution, couldn't get anything else to work. Wouldn't like to write the whole SQL query manually. My current implementation with the two pivot table looks like this (result not nested, code messy):
$users = User::withCount(['attendingEvents' => function($query) use($eventId){
$query->where('event_id', $eventId);
}])
->with(['attendingSubEvents' => function($query) use($eventId){
$query->select('id')->whereHas('event', function($query) use($eventId){
$query->where('id', $eventId);
});
}]);
With this approach I get the sub-events separated from the main event. (querying only for the main attending-event count, because I only need to determine whether he is joining or not).
The pattern for this type of solution is to use a Polymorphic Relationship. This solution focuses just on connecting the User to the Event and SubEvent - the rest of the relations look correct.
<?php
class User extends Model {
public function attending() {
return $this->morphTo();
}
}
<?php
class Event extends Model {
public function attendees() {
return $this->morphMany('App\User', 'attending')
}
}
<?php
class Subevent extends Model {
public function attendees() {
return $this->morphMany('App\User', 'attending')
}
}
The users table needs these fields:
*users*
-----
id
attending_id
attending_type
This is all untested - but the basic idea. (Edited: changed name of polymorphic method to attending from attendee)
So I have a weird question.
I'm making an application in Laravel and Angular. I'm using Eloquent models.
Right now I have 2 tables, 1 users table (with the users info), and 1 events table (with the name, date, ... of an event).
These 2 are binded by a oneToMany relation (Every event belongs to an user). But now I would like people to sign up for that event. ( a switch in the front end, so they can apply for the event).
So, many users will have many events.
The catch is also, the owner of the event can manually set an maximum # users. (This is an tinyINt in my event table).
So now my question. How can I pull this off?
Options I have thought off:
1. I make a pivot table
-> Is this possible? Because the User and the event are already binded by a one to many realtion? So how can I bind them with a many to many relation again?
2. Every time a user signs op, I add his ID to an array in the events table.
-> Is this possible? I could then be able to set the maximum # users by checking the length of the array?
Thank you friends!
Using a pivot table is the correct approach here. The fact that the two tables are already bound by a different relation should not deter you.
class Events extends Eloquent
{
public function owner()
{
return $this->belongsTo(App\User::class);
}
public function subscribers()
{
return $this->belongsToMany(App\User::class, 'event_user');
}
public function canAddSubscriber()
{
if ( ! $this->max_users) return true;
return $this->max_users < $this->subscribers()->count();
}
}
As you can see, you can use the relationship to determine if a subscriber can still be added.