how to use Laravel Rinvex Attributes? - laravel

I'm trying to use https://github.com/rinvex/attributes, and can't understand how.
Docs are not clear for me and i need help.
After installing the package i've done next:
I have \App\Models\Product class that i want to make attributable.
So I put in model
use Rinvex\Attributes\Traits\Attributable;
class Product extends Model
{
use CrudTrait;
use Sluggable;
use Attributable;
/***/
In AppServiceProvider's boot():
app('rinvex.attributes.entities')->push(App\Models\Product::class);
Next - just like in docs - creating the attribute in Tinker console just like that:
app('rinvex.attributes.attribute')->create([
'slug' => 'size',
'type' => 'varchar',
'name' => 'Product Size',
'entities' => ['App\Models\Product'],
]);
In DB i see added entries in attributes_entries and attributes tables.
But when i try to call
$product->size = 50;
$product->save(); - got "not found field in Model".
What do i do wrong?

Did you register varchar type? As it mentioned in documentation,
Rinvex Attributes does NOT register any types by default (see https://github.com/rinvex/laravel-attributes#register-your-types)
So i suggest you to add this code in your service providers register method:
Attribute::typeMap([
'varchar' => \Rinvex\Attributes\Models\Type\Varchar::class,
]);
Don't forget to include this class
use Rinvex\Attributes\Models\Attribute

Related

changing key names when leveraging laravel resources to return API data

So I am currently building out an API and see that laravel has added an API resource which I am assuming is in lieu of something like fractal?
However running into an issue where when I go to return a collection using the XyzCollection resource I do not have the ability to change my DB names? So i end up with the same naming convention I have in my DB..
Plenty of obvious reasons why I don't want to have that be the case (i can go into them if need be) HOWEVER - is there a way to alter those key names?
for example in one of my tables I have a id,uuid,user_uuid
Now in fractal I would just transform these fields like so -
'id' => $xyz->uuid,
'user' => [
'data' => [
[
'user_id' => $xyz->user->uuid,
'username' => $xyz->user->username,
]
]
],
How do i do this when all i can do is pass in the collectionin the XyzCollection?
'data' => $this->collection,
and before you say use XyzResource ... When I am returning all(); records like I need to do plenty of times in an API (or paginate) etc etc. I can only do that from XyzCollection!
Thanks in advance
Steve
You first need to define a structure for a singular JsonResource object:
(php artisan make:resource Xyz)
public function toArray($request)
{
return [
'user_id' => $this->uuid,
'username' => $this->username,
];
}
And then tell your XyzCollection to use the class:
Customizing The Underlying Resource Class
Typically, the
$this->collection property of a resource collection is automatically
populated with the result of mapping each item of the collection to
its singular resource class. The singular resource class is assumed to
be the collection's class name without the trailing Collection
string.
For example, UserCollection will attempt to map the given user
instances into the User resource. To customize this behavior, you may
override the $collects property of your resource collection
(From https://laravel.com/docs/5.7/eloquent-resources#concept-overview)
If your ResourceCollection doesn't do anything extra, you might not always need it. Every JsonResource can transform itself into a resource collection with the collection() method, e.g. UserResource::collection($users)

admin blade layout include dynamic select

I would like to include in my admin.blade.php layout a dynamic select with a model which I have created. Can you let me know how can I do it?
I know how to create the select dynamic but my main problem is how can i reference my model in admin.blade.php?
Thanks,
1- good => you can always use #inject and here is the document.
2- better => you can add it to the boot method in the appServiceProvider and here is the document.
3- best => you can pass that model from the controller to the view as an object like this
public function modelView(Model $model){
return view('admin.blade.php')->with([ 'model' => $model ]);
}

Using Sentry with Codesleeve Stapler?

Update #1
So I think I found out where the problem is but since I lack the knowledge, there's no way for me to solve it.
When using Sentry, I've tried extending both 'Model' which is default with the Sentry package and Laravel's 'Eloquent' under Illuminate\Database\Eloquent\Model. Neither worked. But while using Laravel's Eloquent on its own (no Sentry package addons), Stapler works nicely.
So I guess there is some compatibilty problem between Stapler and Sentry's User model even though it uses Eloquent (its extra functionalities might be conflicting with stapler's traits or the construct function, I don't know). Too bad since Sentry is a great package for managing authentication and throttling and is widely used as far as I know.
Is there any easy way to use stapler's agnostic version with sentry or will I have to rewrite all my code to use laravel's auth?
Main question
I'm building an app which uses Cartalyst's Sentry for managing users. However, I want users and other models to be able to have associated avatars, so I'm using Codesleeve's Stapler too.
I've read both laravel-stapler's readme and most of stapler's standalone version documentation but couldn't figure out how to make them work with Sentry. Whenever I try to create an user through this function:
$user = Sentry::createUser(array(
'username' => Input::get('username'),
'email' => Input::get('email'),
'password' => Input::get('password'),
'activated' => false,
'avatar' => Input::file('avatar')
));
return 'success';
I get:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'avatar' in 'field list'
So it seems Sentry is querying as if the avatar is a string and Stapler is not working.
Here is my Sentry user model (which I'm extending in Laravel's):
use Illuminate\Database\Eloquent\SoftDeletingTrait;
use Illuminate\Database\Eloquent\Model;
use Codesleeve\Stapler\ORM\StaplerableInterface;
use Codesleeve\Stapler\ORM\EloquentTrait;
use Cartalyst\Sentry\Groups\GroupInterface;
use Cartalyst\Sentry\Hashing\HasherInterface;
use Cartalyst\Sentry\Users\LoginRequiredException;
use Cartalyst\Sentry\Users\PasswordRequiredException;
use Cartalyst\Sentry\Users\UserAlreadyActivatedException;
use Cartalyst\Sentry\Users\UserExistsException;
use Cartalyst\Sentry\Users\UserInterface;
class User extends Model implements UserInterface, StaplerableInterface {
use SoftDeletingTrait, EloquentTrait;
protected $fillabe = array('username','email','password','password_temp','code','active','avatar');
public function __construct(array $attributes = array()) {
$this->hasAttachedFile('avatar', [
'styles' => [
'medium' => '300x300',
'thumb' => '100x100'
]
]);
parent::__construct($attributes);
}
protected $dates = ['deleted_at'];
And inside Sentry's config:
'model' => 'Cartalyst\Sentry\Users\Eloquent\User',
This might be simple to solve since I'm pretty new into Laravel, Sentry and Stapler but I couldn't find any info which would make me solve the problem.
Thanks in advance!
Yes, it can be done. Based on what's in your OP, the root cause appears to be that your user model doesn't know that avatar is a Stapler-provided column.
Theory: the Sentry User Provider manufactures a user model, right here. That user model must be Stapler-aware, per the Stapler docs. Fortunately, Sentry is configurable and you can tell it to use your custom model with setModel().
Rough outline of solution: First, you need a model that is Stapler-aware. You might already have this. Note that it extends the Sentry-provided model class and also imports the Stapler trait. Both are important.
<?php // app/models/UserModel.php
namespace App\Model;
use Codesleeve\Stapler\ORM\StaplerableInterface;
use Codesleeve\Stapler\ORM\EloquentTrait;
use Cartalyst\Sentry\Users\Eloquent\User as SentryUserModel;
class UserModel extends SentryUserModel implements StaplerableInterface {
use EloquentTrait;
}
Second, you need to instruct Sentry to use this. Below I use run-time configuration changes, as is my preference. But you can also change the Sentry configuration file:
<?php // app/bootstrap.php
\Sentry::getUserProvider()->setModel('App\Model\UserModel');
I'm doing this from memory on Laravel 4, so there may need to be some tweaking involved.

Laravel Seeding Does not Fill in Fields

I have a database seed file:
class ContactTableSeeder extends Seeder {
public function run()
{
$contacts = array(
array(
'first_name' => 'Test',
'last_name' => 'Contact',
'email' => 'test.contact#emai.com',
'telephone_number' => '0111345685',
'address' => 'Address',
'city' => 'City',
'postcode' => 'postcode',
'position' => 'Director',
'account_id' => 1
)
);
foreach ($contacts as $contact) {
Contact::create($contact);
}
}
}
When I run php artisan migrate:refresh --seed it seeds the database and creates the relevant record in the contacts table, except that it does not fill the fields with any of the information in the seed array. I am using the exact same syntax for other tables and they work fine, and I've also checked each field thoroughly to make sure they match the database fields but no matter what I do it will not seed correctly.
Does anyone have any ideas?
I had this same problem but none of the above solutions worked for me. It turned out to be due to having a construct function in my model! After I removed this it worked fine!
public function __construct()
{
parent::__construct();
}
EDIT:
After further reading on this I discovered the issue is due to the fact that if you are going to include a constructor in your model must accept the attributes parameter and pass it to the parent. If you do this then the constructor does not break the DB seeding (and probably other things). I hope this saves someone else a headache.
public function __construct($attributes = array())
{
parent::__construct($attributes);
}
Turns out the issue was to do with relationships in my models.
For future visitors to this question: make sure to check all the functions in your models that define hasOne/hasMany/etc relationships. Read though the Eloquent docs for more.
Do you have $this->call("ContactTableSeeder") in your DatabaseSeeder class' run() function?
If you have ContactTableSeeder in it's own file, is the file named ContactTableSeeder.php exactly? If not it would fail to load according to the PSR-0 Standard.
These are my first thoughts.
Have you tried to replace the following lines:
foreach ($contacts as $contact) {
Contact::create($contact);
}
with
DB::table('contact')->insert($contacts);
assuming your table name is contact.
And also, make sure you have line like this
$this->call('ContactTableSeeder');
in your DatabaseSeeder class.

cakePHP: Why are my model associations not working as a plugin?

I have a relationship as follows.
Game -> hasMany Highscores
Highscore -> belongsTo Games, Users
When I run the MVC files standalone (within their respective places in the app dir), I get all belongsTo data associated with Highscores. However, when I run the same MVC files as a plugin, within the plugin dir, these associations are lost.
It seems to me that everythig is in order, but to no avail. I am fairly new to cakePHP so I'm sure it's something stupid. I can't for the life figure it out however.
Any help would be greatly appreciated.
I have referenced:
book.cakephp.org/view/117/Plugin-Models
trac.cakephp.org/ticket/3876
aranworld.com/article/143/cakephp-model-associations-from-within-plugin-directories
Are you setting up your relationships using the PluginName as the prefix in the joined Model's name?
That sounds awkward - example
<?php
class MyModel extends AppModel
{
public $name = "MyModel";
public $belongsTo = array(
'User' => array(
'className' => 'SparkPlug.User',
),
);
?>
I ended up using the bindModel method.
$this->Highscore->bindModel(
array('belongsTo' => array(
'User' => array(
'className' => 'SparkPlug.User'
)
)
)
);
Not ideal and still unsure why my relationships/associations are getting lost. But this will have to do.

Resources