yii2 advanced template extend User model and no data saved - activerecord

I just recently downloaded yii2 advanced template and create new model in frontend module that extend User in "common/models" like this
class UsUser extends User
{
}
class SignupForm extends Model
{
/**
* Signs user up.
*
* #return User|null the saved model or null if saving fails
*/
public function signup()
{
if ($this->validate()) {
$user = new UsUser();
$user->username = $this->username;
$user->email = $this->email;
$user->setPassword($this->password);
$user->generateAuthKey();
$user->save();
return $user;
}
return null;
}
When I signup, there is no error and simply get redirected to main page but no data is inserted into db. I do not use public attribute in my model (either User or UsUser) as specified by Tal V. in here (Yii2 active record model not saving data . So only #property annotation in UsUser.
Maybe I am doing it wrong or is there something else to be aware of, could somebody help pointing it out? Many Thanks.

class SignupForm extends Model
{
/**
* Signs user up.
*
* #return User|null the saved model or null if saving fails
*/
public function signup()
{
if ($this->validate())
{
$user = new UsUser();
$user->username = $this->username;
$user->email = $this->email;
$user->setPassword($this->password);
$user->generateAuthKey();
//IF UsUser MODEL IS VALID THEN SAVE DATA
if ($user->validate())
{
$user->save(false);
return $user;
}
//IF UsUser MODEL IS NOT VALID THEN PRINT THE ERRORS.SO YOU CAN CHECK WHAT ARE THE ERRORS IN MODEL
else
{
echo "<pre>";
print_r($user->getErrors());
echo "</pre>";
}
}
}
}

Related

How to show data for only a specific user using Laravel

I am trying to show data related to user but unfortunately it's not working. Currently, when I submit order via my form, every account can see the data. How can I show data for only the specific person who submitted it?
Database
Table digitizing_orders table has
id | order_name | order_placement | user_id
Digitizingorder Model
class Digitizingorder extends Model
{
protected $table = "digitizing_orders";
public function user()
{
return $this->belongsTo('App\User');
}
}
User Model
class User extends Authenticatable
{
public function digitizing()
{
return $this->hasMany('App\Digitizingorder');
}
}
Controller
public function index()
{
$data = [
'digitizings' => Digitizingorder::with('user')->where('id', '!=', Auth::id())->get()
];
return view('front_end.Customerprofile.digitizing_view_order', $data);
}
Use Polices they can protect controller actions on a model from unauthorized users.
After generating and registering the policy you can use its methods like this:
class DigitizingorderPolicy
{
/**
* Determine if the given Model can be Viewed by the user.
*
* #param \App\User $user
* #param \App\Digitizingorder $digitizingorder
* #return bool
*/
public function view(User $user, Digitizingorder $digitizingorder)
{
return $user->id === $digitizingorder->user_id;
}
}
You can define what's inside the method to satisfy a condition for the user to view a model (e.g privileges or Role).
One of the ways to call it is in the controller:
public function show(Request $request, Digitizingorder $digitizingorder )
{
$this->authorize('view', $digitizingorder);
// The current user can view the digitizingorder ...
}
I suggest reading the docs about it, they're Multiple Ways/Methods to use Polices and might contain something useful for you.
use this in controller
$user = \Auth::guard('web')->user();
$data=
[
'digitizings'=> $user->digitizing
];
return view('front_end.Customerprofile.digitizing_view_order',$data);

Call to a member function relationLoaded() on string on voyage admin

I installed the voyager admin successfully from here
On my client page, I created a custom registration which is derived from auth. I can register the user successfully.
After I installed the voyager admin, I added a new user on client's registration form. Then, when i tried to access the http://localhost:8000/admin and then error occurred as seen on the image.
Below is the image of the line 53:
And below is the entire code of VoyagerUse.php
<?php
namespace TCG\Voyager\Traits;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
use TCG\Voyager\Facades\Voyager;
use TCG\Voyager\Models\Role;
/**
* #property \Illuminate\Database\Eloquent\Collection roles
*/
trait VoyagerUser
{
public function role()
{
return $this->belongsTo(Voyager::modelClass('Role'));
}
/**
* Check if User has a Role(s) associated.
*
* #param string|array $name The role to check.
*
* #return bool
*/
public function hasRole($name)
{
if (!$this->relationLoaded('role')) {
$this->load('role');
}
return in_array($this->role->name, (is_array($name) ? $name : [$name]));
}
public function setRole($name)
{
$role = Voyager::model('Role')->where('name', '=', $name)->first();
if ($role) {
$this->role()->associate($role);
$this->save();
}
return $this;
}
public function hasPermission($name)
{
if (!$this->relationLoaded('role')) {
$this->load('role');
}
if (!$this->role->relationLoaded('permissions')) {
$this->role->load('permissions');
}
return in_array($name, $this->role->permissions->pluck('key')->toArray());
}
public function hasPermissionOrFail($name)
{
if (!$this->hasPermission($name)) {
throw new UnauthorizedHttpException(null);
}
return true;
}
public function hasPermissionOrAbort($name, $statusCode = 403)
{
if (!$this->hasPermission($name)) {
return abort($statusCode);
}
return true;
}
}
As mentioned in the VoyagerUser in line 53 :
if(!$this->role->relationLoaded('permissions')){ ...
The role here is considered as a relation not a field :)
and the error
Call to a member function relationLoaded() on string
means that you have the role as attribute in the User Model
So all you have to do is rename the role attribute to something else and everything will work perfectly ;)
You should simply change the name of your attribute named role because Voyager add a relation named role as well

Comment/Post system in Laravel

I can't seem to get relationships concrete in my head with Laravel. Having tried to follow the docs for eloquent orm, I still can't get my foreign keys to mean something (I update them manually). Right now I am trying to get a bulletin board system to work. A user can create a bulletin post, and here it is working in my controller:
public function editPost($id)
{
$user = User::find($id);
$user->bulletin = new Bulletin;//new post
$user->bulletin->creator_id = $id;//why doesn't it automatically update given the relationship?
$user->bulletin->type = Input::get('type');
$user->bulletin->title = Input::get('title');
$user->bulletin->content = Input::get('bulletinEdit');
$user->bulletin->save();
if(Input::hasFile('bulletinImage')){
$extension = Input::file('bulletinImage')->getClientOriginalExtension();
$fileName = str_random(9).'.'.$extension;
$user->bulletin->photo = new Photo;
$user->bulletin->photo->user_id = $id;
$user->bulletin->photo->type = Input::get('type');
$user->bulletin->photo->filename = $fileName;
$user->bulletin->photo->touch();
$user->bulletin->photo->save();
Input::file('bulletinImage')->move('public/images/bulletin/',$fileName);
}
return Redirect::to('bulletin');
}
If I have the relationship set up properly, shouldn't the creator_id be updated automatically? Here is what I have in my models:
Bulletin
<?php
class Bulletin extends Eloquent {
public function creator()
{
return $this->belongsTo('User');
}
public function comments()
{
return $this->hasMany('Comment');
}
public function type()
{
//if 1 then, etc
}
public function photos(){
return $this->hasMany('Photo');
}
}
User
<?php
use Illuminate\Auth\UserTrait;
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableTrait;
use Illuminate\Auth\Reminders\RemindableInterface;
class User extends Eloquent implements UserInterface, RemindableInterface {
use UserTrait, RemindableTrait;
/**
* The database table used by the model.
*
* #var string
*/
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = array('password', 'remember_token');
public function tags()
{
//TO REMOVE RECORD
//User::find(1)->tags()->detach();
return $this->belongsToMany('Tag');
}
public function createUser()
{
$password = Hash::make('secret');
}
public function bulletin()
{
return $this->hasMany('Bulletin','creator_id');
}
public function profile()
{
return $this->hasOne('Profile');
}
}
Could anybody give me some tips on tightening this up?
The way you are doing it should work, you are just using more code and Eloquent has some methods to help you attach relationships, so I would try something like this:
public function editPost($id)
{
$user = User::find($id);
// Create a new bulletin, passing the necesssary data
$bulletin = new Bulletin(Input::only(['type', 'title', 'bulletinEdit']));
// Attach the bulletin model to your user, Laravel should set the creator_id itself
$bulletin = $user->bulletin()->save($bulletin);
...
return Redirect::to('bulletin');
}
In your model, you'll have to:
class User extends Eloquent implements UserInterface, RemindableInterface {
protected $fillable = ['type', 'title', 'bulletinEdit'];
...
}
So Laravel doesn't give you a MassAssignmentException.

Saving related records in laravel

I have users, and users belong to a dealership.
Upon user registration, I'm trying to save a new user, and a new dealership.
User database has a dealership_id column, which I want to be populated with the ID of the newly created dealership.
This is my current code in the UserController store method.
public function store()
{
$user = new User();
$user->email = Input::get('email');
$user->password = Input::get('password');
$dealership = new Dealership();
$dealership->name = Input::get('dealership_name');
$user->push();
return "User Saved";
}
Trying to use $user->push(); User data gets updated, but dealership is not created or updated.
Eloquent's push() saves the model and its relationships, but first you have to tell what you want to be involved in the relationsship.
Since your user-model/table holds the id of the dealership, I assume that a user can belong to only one dealership, so the relationship should look like this:
User Model:
public function dealership()
{
return $this->belongsTo('Dealership');
}
Dealership Model:
public function users()
{
return $this->hasMany('User');
}
To save a User from the Dealership perspective, you do this:
$dealership->users()->save($user);
To associate a dealership with a user, you do this:
$user->dealership()->associate($dealership);
$user->save();
Please check this answer to see the difference of push() and save()
You will need to define correctly your models relationships as per documentation
If this is done correctly, it should work .
This is what push() does :
/**
* Save the model and all of its relationships.
*
* #return bool
*/
public function push()
{
if ( ! $this->save()) return false;
// To sync all of the relationships to the database, we will simply spin through
// the relationships and save each model via this "push" method, which allows
// us to recurse into all of these nested relations for the model instance.
foreach ($this->relations as $models)
{
foreach (Collection::make($models) as $model)
{
if ( ! $model->push()) return false;
}
}
return true;
}
In your case, you have a one (dealership) belongs to many (users)
In your Users model :
class Users extends Eloquent {
public function dealership()
{
return $this->belongsTo('Dealership');
}
}
In the example above, Eloquent will look for a dealership_id column on the users table.
In your Dealership Model :
class Dealership extends Eloquent {
public function users()
{
return $this->hasMany('User');
}
}
In your store function :
public function store()
{
$user = new User();
$user->email = Input::get('email');
$user->password = Input::get('password');
$user->dealership = new Dealership();
$user->dealership->name = Input::get('dealership_name');
$user->push();
return "User Saved";
}
Learn here more about eloquent relationships
Also please take a look at my answer here
By using push on the User model, Laravel is basically recursively calling save on all the related models (which, in this case, is none, since you haven't associated any other models to it yet).
Therefore, in order to accomplish what you're trying to do, you can do first create the user then associate the dealership with it by doing the following:
$user = new User();
$user->email = Input::get('email');
$user->password = Input::get('password');
$user->save();
$dealership = new Dealership();
$dealership->name = Input::get('dealership_name');
$user->dealerships()->save($dealership);
return "User Saved";
However, prior to doing this, you must ensure your User and Dealership models have their relationships set up correctly:
User Model:
public function dealership()
{
return $this->belongsTo('Dealership');
}
Dealership Model:
public function users()
{
return $this->hasMany('User');
}
This is how I manage to do it.
In your controller: (Laravel 5)
use Auth;
$dealership->user = Auth::user()->ref_user->staff_id;

Silex , mongo DB and updating a Document , Unique Constraint validation doesnt work properly

I'm testing silex, mongodb and Form validation. And I run into a validation issue when using MongoDB ODM and a before middelware , wether it is security related or not.
I'm given a document and have added an Unique constraint on a field of the document.
If the document is not requested before the validation actually executes, everything works fine.
Let's say I have a before middleware that requests the document before the controller with validation is executed. In that case the unique constraint does not work properly and displays an error message saying This value is already used. But it should not since the value used is unique to the object that is validated.
To sum up, the issue is, when validating a document with an Unique Constraint on a field, if the document is requested through the document manager (with no modification performed on the document) before the validation code is actually executed, it seems the Unique constraint does not work properly.
I'm going to set up a test case but in the mean time, here is an example of how I set up the validation on the document; if anybody has come across the issue please let me know.
namespace Document;
//use Doctrine\Bundle\MongoDBBundle\Validator\Constraints\Unique as MongoDBUnique;
use Doctrine\Bundle\MongoDBBundle\Validator\Constraints\Unique;
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Validator\Mapping\ClassMetadata;
/**
* #ODM\Document(collection="blog_post")
*/
class Post
{
/**
* #ODM\Id
*
*/
protected $id;
/**
* #ODM\String
* #ODM\UniqueIndex
*/
protected $title;
/**
* #ODM\String
*/
protected $body;
/**
* #ODM\Date
*/
protected $createdAt;
/**
* #ODM\ReferenceOne(targetDocument="Document\User",cascade="update,merge",inversedBy="posts")
*/
protected $user;
function __construct() {
}
public function getTitle() {
return $this->title;
}
public function setTitle($title) {
$this->title = $title;
}
public function getBody() {
return $this->body;
}
public function setBody($body) {
$this->body = $body;
}
public function getCreatedAt() {
return $this->createdAt;
}
public function setCreatedAt($createdAt) {
$this->createdAt = $createdAt;
}
public function getId() {
return $this->id;
}
function getUser() {
return $this->user;
}
function setUser(User $user) {
$this->user = $user;
$this->user->addPost($this);
}
function __toString() {
return $this->title;
}
static function loadValidatorMetadata(ClassMetadata $metadatas) {
$metadatas->addPropertyConstraint("body", new Length(array('min'=>10,'max'=>1000)));
$metadatas->addPropertyConstraint("title", new Length(array('min'=>5,'max'=>255)));
$metadatas->addConstraint(new Unique(array('fields' => 'title')));
}
}
The app is in this Github repository. (work in progress):
Edit 1: An example of a before middleware that would trigger the erratic behavior of the Unique Constraint (in demo/mongoddb/blog/app/Config.php file in the repo linked) :
$app['must_be_post_owner'] = $app->protect(function(Request $req)use($app) {
$postId = $req->attributes->get('id');
$user = $app['security']->getToken()->getUser();
$post = $app['odm.dm']->getRepository('Document\Post')->findOneBy(array('id' => $postId));
if ($post->getUser() !== $user) {
$app['logger']->alert("Access denied for user $user to post with id $postId ");
$app->abort(500, 'You cant access this resource !');
}
}
);
Edit 2: I tried to debug the Symfony/Doctrine-Bridge UniqueEntityValidator class with XDebug but I get socket errors every time there is a MongoDB related function executed during step debugging.

Resources