public function store(Request $request) {
$user = Book::create([
'user_id' => auth()->id(),
'name => $request->name,
'year => $request->year
)];
}
The above code is able to store into Database.
I want to know how to add below extra data TOGETHER.
I found out that merge was not working as it is not collection.
Tried to chain but was not working.
public function data() {
$array = [
'amount' => 30,
'source' => 'abcdef',
];
return $array;
}
You can catch create Event in Model.
This code may can help you.
/**
* to set default value in database when new record insert
*
*/
public static function bootSystemTrait()
{
static::creating(function ($model) {
$model->amount = 30;
});
}
You can write this code into your model. It will execute every time when you create record using Laravel model.
If you want to modify it you can use property into Model class. Something like this:
class TestClass extends Model
{
public static $amount = 0;
static::creating(function ($model) {
$model->amount = self::$amount;
});
}
Good Luck.
Related
I have a simple Livewire component that lists users:
class UserListComponent extends Component
{
use WithPagination;
protected $listeners = ['refreshComponent' => '$refresh'];
public $search = '';
public $orderBy = 'id';
public $orderAsc = true;
public $perPage = 10;
public function render()
{
return view('livewire.admin.user-list-component',[
'users' => User::search($this->search)
->orderBy($this->orderBy, $this->orderAsc ? 'ASC' : 'DESC')
->simplePaginate($this->perPage)
]);
}
}
and a component that adds users:
public function addUser()
{
// validate data
$validatedData = $this->validate();
// generate random password
$bytes = openssl_random_pseudo_bytes(4);
$password = bin2hex($bytes);
// create user
$user = User::create([
'name' => $validatedData['name'],
'email' => $validatedData['email'],
'password' => Hash::make($password),
]);
event(new Registered($user));
// assign user role
$user->attachRole('user');
$this->emitTo('UserListComponent', 'refreshComponent');
}
As you can see, at the end of the addUser() function I emit an event to the UserListComponent and have a listener set up in that component to refresh it, so that when a user is added the list of users automatically updates. However, it doesn't work. If I refresh manually I can see that the user is added to the database and display just fine, but the component refreshing does not happen, and no error is thrown.
Any ideas?
From what I see the best way is to use full class name so instead of:
$this->emitTo('UserListComponent', 'refreshComponent');
you should use:
$this->emitTo(\App\Http\Livewire\UserListComponent:class, 'refreshComponent');
(of course update namespace if you have UserListComponent in other namespace)
I have a Post/Category manyToMany relations and would like to be able to attach a default category named "Uncategorised" to each new post that is created. How can I do that? A BelongsToMany method only works on the Details page, not on Create page.
BelongsToMany::make(__('Categories'), 'categories', Category::class),
You can also set default value to your database field so that you can omit passing category and will be taken default to Uncategorised like if you are using MySQL you can do it this way by creating migration
$table->text('category')->default(0);
Because the BelongsToMany not show on mode create in Post Nova model. So we have to make our custom Select, by add this code to your fields:
public function fields(Request $request)
{
if($request->editMode=="create"){
$categories = \App\Category::get(['id','name']);
$options = [];
foreach($categories as $value){
$options[$value->id] = $value->name;
}
return [
ID::make()->sortable(),
Text::make('Title'),
Text::make('Summary'),
Textarea::make('Content'),
Select::make('Categories', 'category_id')
->options($options)
->displayUsingLabels()
->withMeta(['value' => 1]) // 1 = id of Uncategorised in categories table
];
}
return [
ID::make()->sortable(),
Text::make('Title'),
Text::make('Summary'),
Textarea::make('Content'),
BelongsToMany::make('Categories','categories')->display('name'),
];
}
Don’t forget relationship function in both, Post and Category model:
class Post extends Model
{
public function categories(){
return $this->belongsToMany(Category::class, 'category_post', 'post_id', 'category_id');
}
}
And:
class Category extends Model
{
public function posts(){
return $this->belongsToMany(Post::class,'category_post', 'category_id', 'post_id');
}
}
Then, custom the function process the data on mode Create of Post resource page, it’s at nova\src\Http\Controllers\ResourceStoreController.php, change function handle to this:
public function handle(CreateResourceRequest $request)
{
$resource = $request->resource();
$resource::authorizeToCreate($request);
$resource::validateForCreation($request);
$model = DB::transaction(function () use ($request, $resource) {
[$model, $callbacks] = $resource::fill(
$request, $resource::newModel()
);
if ($request->viaRelationship()) {
$request->findParentModelOrFail()
->{$request->viaRelationship}()
->save($model);
} else {
$model->save();
// your code to save to pivot category_post here
if(isset($request->category_id)&&($resource=='App\Nova\Post')){
$category_id = $request->category_id;
$post_id = $model->id;
\App\Post::find($post_id)->categories()->attach($category_id);
}
}
ActionEvent::forResourceCreate($request->user(), $model)->save();
collect($callbacks)->each->__invoke();
return $model;
});
return response()->json([
'id' => $model->getKey(),
'resource' => $model->attributesToArray(),
'redirect' => $resource::redirectAfterCreate($request, $request->newResourceWith($model)),
], 201);
}
}
All runs well on my computer. A fun question with me! Hope best to you, and ask me if you need!
What I ended up doing was saving the data on Post Model in boot().
public static function boot()
{
parent::boot();
static::created(function (Post $post) {
$post->categories()->attach([1]);
});
}
I have upgraded the laravel excel library (Maatswebsite) from 2x to 3.1 (running Laravel 5.6/php 7.1) and trying to make my old data work (download exported file) and cannot work out how to pass my $data (which is an array from a foreach DB query (not eloquent) in controller) to the UsersExport.php class...
If I manually create a test collection (mirroring my $data array) in the class:
return collect([
[
'name' => 'F Name 1',
'surname' => 'Last Name 1',
'email' => 'Email 1'
'date_completed' => 'xx/xx/xx'
],
[
'name' => 'F Name 2',
'surname' => 'Last Name 2',
'email' => 'Email 2',
'date_completed' => 'xx/xx/xx'
]
]);
the above works perfect and the file is created and downloads when I run:
return Excel::download(new UsersExport, 'Test.xlsx');
But I want to pass my array ($data) from the controller to the class and not sure HOW I do this... I am trying to get something like this to work:
return Excel::download(new UsersExport($data), 'Test.xlsx');
From reading the specific posts I could find, I believe I need to create a constructor in the Class to accept my $data - but not sure how, and how to return that data if I succeed in my class accepting the data etc... Is the FromCollection the right option?
private $data;
public function __construct($data)
{
$this->data = $data;
}
Appreciate any assistance.... Thanks in advance.
Your approach is right. then use the collection() function to return that data.
private $data;
public function __construct($data)
{
$this->data = $data;
}
public function collection()
{
return $this->data;
}
if you want passing param data to class you use construct.
Example Controller:
<?php
namespace App\Http\Controllers\Reports;
use App\Http\Controllers\Controller;
use Maatwebsite\Excel\Facades\Excel;
use App\Exports\CustomerinvoiceExport;
use App\Model\OrderInvoiceList;
use Illuminate\Http\Request;
class CustomerInvoiceController extends Controller
{
public function index(Request $request)
{
if ($request->has('start_date')) {
$start_date = $request->start_date;
} else {
$date_now = Carbon::now();
$start_date = $date_now->toDateString();
}
if ($request->has('end_date')) {
$end_date = $request->end_date;
} else {
$date_now = Carbon::now();
$end_date = $date_now->toDateString();
}
$customer_invs = OrderInvoiceList::customer_invoice($start_date, $end_date);
return Excel::download(new CustomerinvoiceExport($customer_invs), 'Customer_Invoice_Report.xlsx');
}
}
}
Class Export
<?php
namespace App\Exports;
use Maatwebsite\Excel\Concerns\FromCollection;
class CustomerinvoiceExport implements FromCollection
{
protected $customer_invs;
/**
* Customer Invoice Report
*/
public function __construct($customer_invs)
{
$this->customer_invs = $customer_invs;
}
/**
* #return invoice_list
*/
public function collection(): array
{
$invoice_list = $this->invoice_list;
...........your logic here....
}
}
My plugin code:
public function boot()
{
**I can:**
$user = new User();
$table = $user->getTable();
**I would like to:**
echo User::getTable();
exit;
$user = $this->user;
\Serviom\Guestpage\Models\Post::extend(function($model) use ($user) {
$model->rules = [
'name' => 'required|between:3,100',
'subject' => 'required|between:3,100',
'desc' => 'required|between:10,1000',
'parent_id' => 'nullable|exists:serviom_guestpage_posts,id',
'user_id' => 'nullable|exists:' . $table . ',id',
Variable in modal $table is protected member so its really nothing we can do about that but we can simply access it by adding public method to class [ extend it ]
In any of your plugin you can add this snippet
use RainLab\User\Models\User as UserModel;
class Plugin extends PluginBase
{
public function boot() {
UserModel::extend(function($model) {
$model->addDynamicMethod('getTableName', function() use ($model) {
return $model->getTable();
});
});
//....
Now you can able to call
echo User::getTableName();
Its like kind of hack but its only if you really badly needed it then you do something like this
if any doubt please comment.
You can add a static method to your Model as a helper :
class MyModel extends Model
{
public static function getTableName()
{
return with(new static)->getTable();
}
}
Usage : MyModel::getTableName()
Source
In Laravel, When I run the following query, it returns a row with null values.
//Cards.php
public function __construct(array $attributes = []) {
$this->gateway = StripeGateway;
}
protected $fillable = ['user_id', 'card_id', 'customer_id', 'exp_year', 'exp_month', 'funding', 'brand', 'last4'];
public function createNewCardFromCustomer($user_id, $customer)
{
$result = $this->create([
'user_id' => $user_id,
'customer_id' => $customer->id,
'card_id' => $customer['sources']['data'][0]->id,
'exp_year' => $customer['sources']['data'][0]->exp_year,
'exp_month' => $customer['sources']['data'][0]->exp_month,
'funding' => $customer['sources']['data'][0]->funding,
'brand' => $customer['sources']['data'][0]->brand,
'last4' => $customer['sources']['data'][0]->last4
]);
return $result;
}
Even the Model static create method receives the right parameters. And I've taken care of the mass assignment also.
I posted this on Laracasts too :)
Anyway, you have to change your constructor to this:
public function __construct(array $attributes = []) {
$this->gateway = StripeGateway;
parent::__construct($attributes);
}
You are overriding the Model's base constructor, which changes its default behavior. Laravel uses the constructor for a lot of things (create method, relationships, etc.).
The base model's constructor function does several things, but one very important part of it is that it accepts an array to fill out its attributes as can be seen here:
public function __construct(array $attributes = [])
{
$this->bootIfNotBooted();
$this->syncOriginal();
$this->fill($attributes);
}
So, after you set your gateway property, you should call the parent's constructor function and pass the attributes.