Laravel Relationships (user-upload) - database

I get the following errors when i am trying to save the data with the file upload function because I have declared a new uploader_id to my table which should get its value from the relationship I wrote in the model.
Illuminate \ Database \ QueryException
SQLSTATE[HY000]: General error: 1364 Field 'uploader_id' doesn't have a default value (SQL: insert into `assets` (`filename`, `title`, `body`, `filepath`, `extension`, `realpath`, `mime`, `updated_at`, `created_at`) values (users.mov, New, dummy text data. , /uploads/User Test/2014-03-04_00:48, mov, /private/var/tmp/phpHDpmEI, video/quicktime, 2014-03-04 00:48:59, 2014-03-04 00:48:59))
In my models I defined the following
User Model: where assets its the table name for the uploads table in database
public function assets() {
return hasMany('assets');
}
Upload Model:
public function user() {
return belongsTo('user', 'uploader_id');
}
I have tried in my controller where i am using Upload::create(array()) function to post the data to the database, to add another parameter called 'uploader_id' => Auth::user()->id; but none of this work.
What is the best way to pass the uploader_id to the form each time the user uploads a file ?

That's what events are for:
class Asset extends Eloquent {
public static function boot()
{
static::creating(function($model)
{
$model->uploader_id = Auth::user()->id;
});
}
}

Also your relationships should reference their class -
return $this->hasMany('Asset');

Related

laravel one to many relationships returning null

there are two models.product and image
In My product model:
// one to many relationship with images table
public function images()
{
return $this->hasMany('App\image');
}
Image Model
public function product()
{
return $this->belongsTo('App\product');
}
ProductController
public function productDetail($slug)
{
$product = product::where([
['slug',$slug],
['seller_id' ,Auth::id()],
])->first();
//$storagePath = Storage::get(['images']);
//get the image of that product
//$image = asset('storage/product_images'.$product->images);
if($product)
{
$image = Storage::url($product->images); // give the image path from product table
//give images from the image table
$product_image = \App\product::find(11)->images;
$arr = array();
foreach(\App\product::find($product->id)->images() as $i)
{
array($arr,$i->image);
}
dd($arr); // problem returning always null
return view('backEnd.seller.product_detail',compact('product','image'));
}
Problem Statement:
In my controller when i tried to get all the images of specific product i am getting Null . I am trying to solve this for one day ago.please help me Which i am missing?
image table migration
public function up()
{
Schema::create('images', function (Blueprint $table){
$table->increments('id');
$table->unsignedInteger('product_id');
$table->string('image');
$table->timestamps();
});
}
product table migration
public function up()
{
Schema::create('products', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('seller_id');
$table->unsignedInteger('category_id');
$table->string('product');
$table->text('discription');
$table->string('type')->nullable();
$table->date('date');
$table->string('images');
$table->string('slug');
$table->integer('sold_qty')->default(0);
$table->timestamps();
});
}
Note:
I have make sure that in my image table there are 5 records of product_id 11.Please help Thanks
You have to make the relation in your database. You can do it by adding this to your image migration:
$table->foreign('product_id')->references('id')->on('product');
I assume your model names are Product and Image.
Please check whether below change will give you what you want...
return $this->hasMany('App\Image');
note that model name starts with uppercase letter and,
return $this->belongsTo('App\Product');
and database constraint as #steve-trap mentioned is not necessary. Anyway it will introduce a constraint so that you cannot add image for non-existing product.
Then in controller:
foreach (App\Product::find($product->id)->images as $image) {
$arr[] = $image->image;
}
I solved this problem by:
Changed the model names to uppercase.
Changed the product table column name images to cover.
Changed the method images() to pictures in Product Model
Conclusion:
If you use the column name then don't use that column name for building relationship.
and always write model name that starts with uppercase.

access model class inside entity class of other model

I am using CakePHP 3.4+
I have written an application with multi level membership.
The Pro members will have benefit to view short url for external links which when shared will record the visit count to that url.
The original url is stored in PostVideos table for all user.
I have created a table to store uniuqe keys for short urls inside short_video_post_urls with columns
+----+---------------+------------+-------------+
| id | post_video_id | unique_key | visit_count |
+----+---------------+------------+-------------+
Since, count of Pro members will be low than normal users, I don't want to generate unique_key entry in short_video_post_urls because It will flood database with useless records.
So, what I want is to generate them dynamically and store them for PRO members only
Now, in template file I'm using $postVideo->video_url to display original video url from post_videos table.
Question
What I want is to tweak video_url entity call which will check for
Membership level of logged in user
If member is pro
check if unique key exists in ShortVideoPostUrls model for the url requested
If no record exists, then create a unique_key in ShortVideoPostUrls
return the new url with unique_key
But for that I need to access logged_in user data in the entity class.
What I tried?
class PostVideoLog extends Entity
{
/*
* ----
* ----
*/
protected function _getVideoUrl()
{
$user = $this->Users->get($this->Auth->user('id'), [
'contain' => [
'MembershipLevels'
]
]);
if ($user) {
if (strtolower($user->membership_level->title) === 'pro') {
/**
* check if unique_key exists for this request
*/
$checkShortUrl = $this->ShortVideoPostUrls->find()
->where(['post_video_log_id' => $this->_properties['id']])
->first();
if ($checkShortUrl) {
return $this->_generateUrl($checkShortUrl->unique_key);
}
/**
* create new record
*/
$unique_key_generator = new Hashids(UNIQUE_SHORT_URL_SALT, 4);
$unique_key = $unique_key_generator->encode($this->_properties['id']);
$newShortUrl = $this->ShortVideoPostUrls->newEntity();
$newShortUrl = $this->ShortVideoPostUrls->patchEntity($newShortUrl, [
'unique_key' => $unique_key,
'post_video_log_id' => $this->_properties['id']
]);
if ($this->ShortVideoPostUrls->save($newShortUrl)) {
return $this->_generateUrl($unique_key);
}
}
}
return $this->_properties['video_url'];
}
private function _generateUrl($unique_key)
{
$base_url = Router::url('/', true);
return $base_url . '/u/' . $unique_key;
}
}
I'm not sure, whether my approach is right or wrong.
To load Users model and other models I'm using in above function requires to use
$this->loadModel('Users');
But, loadModel seems not to be working here.
What is other approach to do this? Or how to load external model and Auth component in Entity class?
Edit 2
Is there any better alternative to do what I want without entity? or simply some way to call function from template on each entity?
Ex.
$postVideo->video_url()
To load other model inside entity You can use TableRegistry class
use Cake\ORM\TableRegistry;
class MyModel extends Entity {
protected function _getVideoUrl() {
$table = TableRegistry::get('Users');
$users = $table->find('all')->toArray();
}
}
I think its not the best idea to use Auth component in model - I dont know how to do this "properly", but all session data (including auth data) is still available in $_SESSION array

CakePHP loadModel not working

I have created a Model named "Usermgmt" and I am using table for this model is "users" in following manner.
public $useTable = "users";
Now I am loading this Model into different controller named "MembersController" in following manner
public $this->loadModel('Usermgmt');
But it is showing error when I load this model into "MembersController" controller- table "usermgmts" missing for "Usermgmt" model.
And it is working fine in "UsermgmtController" without showing table "usermgmts" missing error and saving data correctly into the "Users" table.
NOTE- I do not have any table with named - "usermgmts" as I am using "users" table for "Usermgmt" Model
Remove the public portion and call it from inside a function:
So if you are trying to add this is a function in MembersController, you would the add it like this:
App::uses('AppController', 'Controller');
class MembersController extends AppController {
public function myFunction() {
$this->loadModel('Usermgmt');
//do stuff
}
}

Registration form with new fields related

i am trying to add fields to my registration form with FosUserBundle.
Adding normal fields to the Userclass like "name", "age" e.g is easy to do:
class RegistrationFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
// add your custom field
$builder
->add('name')
;
}
public function getParent()
{
return 'fos_user_registration';
}
public function getName()
{
return 'acme_user_registration';
}
}
This is all working and the new fields are written to my database table.
But how do i add there a new FormType into the Registration type of the Fos Bundle, like:
A user can have an Address, which is related OneToMany.
I tried it with the following, by first creating the address class and giving him one user:
/**
* #ORM\ManyToOne(targetEntity="User", inversedBy="addresses")
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
protected $user;
And then by adding addresses to the User class:
/**
* #ORM\OneToMany(targetEntity="Address", mappedBy="user")
*/
protected $addresses;
public function __construct()
{
parent::__construct();
// your own logic
$this->addresses= new ArrayCollection();
}
Adding the AddressType:
class AddressType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('state', 'text')
->add('city','text')
->add('zipcode', 'text')
->add('street', 'text');
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Acme\UserBundle\Entity\Address',
));
}
public function getName()
{
return 'address';
}
}
to the RegistrationFormType works and the fields are displayed in the browser:
public function buildForm(FormBuilderInterface $builder, array $options)
{
// add your custom field
$builder
->add('name')
->add('addresses', new AddressType())
;
}
But when i try to submit the form with new data, i don't know how to say symfony that the address entered should be related to the User.
Im always getting the error:
"The form's view data is expected to be an instance of class Acme\UserBundle\Entity\Address, but is an instance of class Doctrine\Common\Collections\ArrayCollection. You can avoid this error by setting the "data_class" option to null or by adding a view transformer that transforms an instance of class Doctrine\Common\Collections\ArrayCollection to an instance of Acme\UserBundle\Entity\Address."
What am I doing wrong here?
Regards.
you're trying to add a collection as a single field, when you give a "data_class" you're saying "here this is the form for this entity", but as the error says the system has to manage a collection of forms each one related to a single entity, you need to data transform them to something he can manage in a simple (or prebuilt) way (look for DataTransformers)
or you can use the colletion field type and pass them the address form type
-- edited after the comment --
no, sorry i've missed that, you need an entity form type because you state that a user has one address (and many user can be mapped to the same address, i.e. a family), so there's no need of a collection, though you're in the owning side persisting the user you don't have to worry, if you say cascade persist in your mapping schema for the ManyToOne relation, Doctrine will store the address for you (or use an existing one in case of a matching one)
btw i was fuzzed by your sentence "A user can have an Address, which is related OneToMany." that's misleading, a user can have an address, which is related to a ManyToOne relation (many user can have an address), the address is in a oneToMany relation with users (an address is own by many users)

Codeigniter Undefined property: xxxx_model::$db only from Model

First the Model class:
class Xxxx_model extends Model
{
function XxxxModel()
{
parent::Model();
$this->load->database();
}
function isInDatabase()
{
// Please ignore the sql query, it's just to show some random sql code with results
11. $result = $this->db->query('SELECT * FROM someTable WHERE ...');
$numberOfRows = $result->num_rows();
...
return $test;
}
}
Now the controller:
function someLogic()
{
$this->load->model('xxxx_Model', 'xxxxModel'); // not necessary to specify
$this->xxxxModel->isInDatabase();
}
When I run this I get the error:
Severity: Notice --> Undefined property: Xxxx_model::$db .../xxxx_model.php line 11
I have no idea why this is. If I put the db code in the controller it seems to work, it's only with this setup in the model that it fails. I can't for the life of me figure out where the code is astray...
You have to load the db library first. In autoload.php add below code,
$autoload[‘libraries’] = array(‘database’);
add library 'datatabase' to autoload.
/application/config/autoload.php
$autoload['libraries'] = array(
'database'
);
Propably you're started new project, like me ;-)
To add to atno's answer:
class Xxxx_model extends Model
{
function XxxxModel() //<--- does not match model name Xxxx_model
{
parent::Model();
$this->load->database();
}
Basically, you are not constructing the class or the parent class Model. If you are on PHP5, you may use __construct(), otherwise you must match the class name exactly, regardless of what alias you load it with in your controller. Example:
class Xxxx_model extends Model
{
function __construct()
{
parent::__construct(); // construct the Model class
}
}
I may be mistaken (haven't used 1.x in a while), but if you construct the Model class, there's no need to load the database if you are using the default connection settings in config/database.php, it should already be loaded for you.
If function XxxxModel() isn't your constructor, you're not loading the database by calling $this->xxxxModel->isInDatabase();
Try autoloading the database library from within autoload.php, or create a proper constructor in your model.

Resources