Laravel foreign key with img path - php

I basically have this:
foreach ($request->input('images', []) as $imagesData) {
$images = new ScenesImages($imagesData);
$images->product()->associate($product);
$images->save();
}
This saves correctly in my foreign key the name of the image/s but how do I safe the image path dynamicly here.
If I dd($product);
I get this:
> #attributes: array:2 [▼
> "name" => "test"
> "product_id" => 7 ]
but no img(path)
Javascript which creates that html in a loop:
for(var i = 1; i<slider.value; i++) {
$('#sliderAppendSz').append(
'<div class=\"form-group\">'
+'<div class=\"fileinput fileinput-new\" data-provides=\"fileinput\">'
+'<div class=\"input-group\">'
+'<input name=\"images['+i+'][name]\" type=\"text\">'
+'<span class=\"input-group-btn\">'
+'<span class=\"btn btn-primary btn-file\">'
+'<input name=\"images['+i+'][scenes_images]\" type=\"file\" multiple class=\"ImageInput\" accept=\"file_extension/*\">'
+'</span>'
+'</span>'
+'</div>'
+'</div>');
}
And my ScenesImages Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class ScenesImages extends Model
{
protected $table = 'scenes_images';
protected $fillable = ['product_id', 'name', 'scenes_images'];
public function product()
{
return $this->belongsTo('App\Product', 'product_id');
}
}
And here my Product Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
public static $projects = 'C:\\xampp\\htdocs\\MyProject\\Web';
protected $table = 'products';
protected $fillable = [
'scenes_images'
];
public static $rules = [
'scenes_images' => 'max:500',
];
public function scenesImages()
{
return $this->hasMany('App\ScenesImages');
}
}
Edit:
OK I think I got it I had to add this as since I only got input before I just added a foreach with a file, my question now is if it is somehow possible to sum the two foreach loops into one like $requesting->file and input.
foreach ($request->file('images', []) as $imagesData) {
$images = new ScenesImages($imagesData);
$images->product()->associate($product);
$images->save();
}

Could be better if you show us more information about the model ScenesImages, otherwise maybe you can have something like this.
foreach ($request->input('images', []) as $imagesData) {
$images = new ScenesImages($imagesData);
$images->product()->associate($product);
$images->path = $your_path
$images->save();
}
Of course you will need the variable $your_path with the path where is saved the images or if it's an url from Amazon S3, but as I said we need maybe more information about your Models structure.

Don't forget upload the image, save it to the server
foreach ($request->input('images', []) as $imagesData)
{
$images = new ScenesImages($imagesData);
$images->product()->associate($product);
$destinationPath = 'uploads'; // upload path
$extension = $imagesData->getClientOriginalExtension(); // getting image extension
$fileName = $imagesData->getClientOriginalName()'.'.$extension; // renameing image
$imagesData->move($destinationPath, $fileName); // uploading file to given path
$images->path = $destinationPath.'/'.$fileName;
$images->save();
}

Couple of issues I'm having with your code:
I'm a bit confused on what $request->file('images') returns. If it's an array of the UploadedFile object then I'm pretty sure you're doing it wrong. You're not even uploading the images to your server, once uploaded that's the file path you want to use when saving your ScenesImages model.
Your code here:
$images = new ScenesImages($imagesData);
is newing up a ScenesImages object and passing it a variable which would need to satisfy the model's required attributes to be created properly, its attributes being: name, scenes_images according to your question code. If you don't it's not going to work properly. You should be passing it an associative array with the keys matching the attributes the model has.
You should usually make your tables plural: scene_images and then your model singular: SceneImage
Consider doing your code like this:
$product = Product::first(); // assume you've defined this already
$uploadedImages = $request->file('images'); // get the images
$destinationPath = storage_path . '/uploads'; // somewhere to put your images
foreach ($uploadedImages as $uploadedImage) {
// upload the image first!
if ($uploadedImage->isValid()) {
$extension = $uploadedImage->getClientOriginalExtension(); // file extension
$uploadedImageName = uniqid(). '.' .$extension; // unique file name with extension
$uploadedImage->move($destinationPath, $uploadedImageName); // move file to our uploads path
// create ScenesImages record in DB
$image = ScenesImages::create([
'name' => $uploadedImageName, // assuming this is your file path?
'scenes_images' => '' // assign something here, not sure what it's supposed to be?
]);
// associate product
$image->product()->associate($product);
} else {
// handle error here
}
}

Related

Trying to get property of non-object while uploading to database

I have a script when user can clip video, then that video uploads to public folder, and now I want to upload all video data to database. But i get error like in title. Here's my code:
Controller:
public function clip($id)
{
$video = Video::where('id', $id)->first();
$oldId = $video->id;
$originalName = $video->original_name;
$newName = str_random(50) . '.' . 'mp4';
FFMpeg::fromDisk('public')
->open('/uploads/videos/' .$video->file_name)
->addFilter(function ($filters) {
$filters->clip(FFMpeg\Coordinate\TimeCode::fromSeconds(5), FFMpeg\Coordinate\TimeCode::fromSeconds(2));
})
->export()
->toDisk('public')
->inFormat(new \FFMpeg\Format\Video\X264)
->save('/uploads/videos/' . $newName);
$data = ['user_id'=>Auth::user()->id,
'file_name'=>$newName,
'original_name'=> $originalName,
'old_id' => $oldId,
];
$video = Video::edit($data);
}
Model:
public static function edit($request)
{
$video = new Video;
$video->user_id = $request->user_id;
$video->file_name = $request->file_name;
$video->original_name = $request->original_name;
$video->save();
$old = $file = Video::where('id', $request->old_id)->delete();
//$old_file = unlink($request->file('file'));
return $video;
}
What should I edit?
Since you're passing array, you need to use $request['user_id'] syntax instead $request->user_id. You're getting the error because you're trying to treat the array as an object.
But since you have prepared array here, just use create method:
public static function edit($data)
{
$this->destroy($data['old_id']);
return $this->create($data);;
}
Don't forget to add $fillable array to your model to make it work.

Inserts with Laravel 5.1 without page reloading

I've been using Dropzone for several days and I faced some issues. The idea is: the user selects his file, it uploads and goes in his file directory and some of the file's properties (size, name) go in the DB. I can't do it because when the user uploads the file, the page does not refresh and nothing goes in Input::file('file'). I just can't do it. Here is the code i'm using:
class UploadController extends Controller {
public function upload() {
if(Input::hasFile('file')){
$file = Input::file('file');
$user = Auth::id();
$file->move('uploads/'.$user, $file->getClientOriginalName());
}
else {
echo 'Please select a file first';
}
}
Here are the two functions in File.php model
public function getFileId(){
$fileName = Input::file('file')->getClientOriginalName();
$files = File::where('filename', $fileName)->get(); //$fileName
foreach ($files as $file) {
$fileid = $file->fileid;
echo $fileid.'<br>';
Input::file('file')->fileid = $file->fileid; // put fileid as an attribute to the object file for futher usage
}
}
public function incrementFileId(){
$files = File::orderBy('fileid', 'desc')->take(1)->get();
foreach($files as $file){
echo $file->fileid + 1 .' incremented file id<br>';
}
}
So how should my third model function look like to upload the file's properties? DropZone uses Ajax and I though that I should get the file attributes from there but could this be done?!
Use Request instead of Input:
public function upload(Request $request)
{
if ($request->hasFile('file'))
{
$file = $request->file('file');
$file->move('uploads/'.$user, $file->getClientOriginalName());
}

naming a file after submitting a form in Symfony

I am working on a form which accepts some user input and an image file, the submission part and the data getting entered into the database is working fine but I am stuck at how to name a file once it is uploaded, right now this is what i see as an image name in database C:\wamp2.5\tmp\phpF360.tmp which obviously is not correct.
This is what my controller looks like DefaultController.php
public function createBlogAction(Request $request)
{
$post = new Post();
$form = $this->createForm(new PostCreate(), $post);
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$post->upload();
$post->setDate(date_create(date('Y-m-d H:i:s')));
$post->setAuthor('ClickTeck');
$em->persist($post);
$em->flush();
$this->get('session')->getFlashBag()->add(
'notice',
'Success'
);
}
return $this->render('BlogBundle:Default:blog-create.html.twig', array(
'form' => $form->createView()
)
);
}
This is what my upload() looks like inside Entity/Post.php which is uploading the file and moving it into the folder, the file name that I see in a folder is correct however now the one that goes into the database
public function upload()
{
if (null === $this->getImage()) {
return;
}
// I might be wrong, but I feel it is here that i need to name the file
$this->getImage()->move(
$this->getUploadRootDir(),
$this->getImage()->getClientOriginalName()
);
$this->path = $this->getUploadDir();
$this->file = null;
}
I will really appreciate if someone can push me in right direction, I just need to name the file, a name which gets assigned to the image in database and the file should get uploaded with the same name as well.
UPDATE
I managed to get it to work using the following function, not sure if this is the best practice but it did work, i would love to hear from others on this. please do not provide any links, if you can refine what has already been done that would be great.
public function upload()
{
// the file property can be empty if the field is not required
if (null === $this->getImage()) {
return;
}
$dirpath = $this->getUploadRootDir();
$image = $this->getImage()->getClientOriginalName();
$ext = $this->getImage()->guessExtension();
$name = substr($image, 0, - strlen($ext));
$i = 1;
while(file_exists($dirpath . '/' . $image)) {
$image = $name . '-' . $i .'.'. $ext;
$i++;
}
$this->getImage()->move($dirpath,$image);
$this->image = $image;
$this->path = $this->getUploadDir();
$this->file = null;
}
This topic from documentation may help you : http://symfony.com/doc/current/cookbook/doctrine/file_uploads.html
In addition, you should not put your upload function in the controller but rather use Doctrine events (Lifecycle callbacks) to call your function automatically.
as per suggestion of #theofabry you can check symfony2 documentation How to handle File Uploads with Doctrine, Controller must be thin as much as possible and try to do upload with Doctrine Events.
If you want to continue with your logic you may try following code, I have not tested yet...so please be careful.
// set the path property to the filename where you'ved saved the file
$this->path = $this->file->getClientOriginalName();
instead of
$this->path = $this->getUploadDir();

Many to Many Relationship Laravel 4

I am working on a laravel-4 application. Currently It is coming together nicely and I've been getting my head around defining the relationships between the various table s of the database. However I've run into a problem that I'm having trouble solving.
In my db there is a resources table and tags table. There is a many to many relationship between them so I've also got a resource_tags table which has both tables id as the foreign keys.
Now, when I am creating a resource based on data provided by the user via a form I create the resource, check the type and decide on an action. Then I retrieve the tags of the resource and loop through them and create an entry into the Tags table.
My issue is placing information into the resource_tags table. Is there a method that can enable me to do this with relative ease?
This is my controller that is handling the form submission:
class SharedResourcesController extends BaseController {
//Add a shared Resource to the DB
//To do: Error checking and validation.
public function handleResource(){
//Create Object
$resource = new SharedResource;
$resource->title = Input::get('title'); //Title of resource
$resource->user_id = Input::get('user_id'); //User who uploads
$resource->book_id = Input::get('book_id'); //Book it is associated with
$resource->type_id = Input::get('type_id'); //Type of resource
//STORE LINKS
//if type is link... 1
if($resource->type_id == "1"){
$resource->web_link = Input::get('link');
}
//if type is video...2
if($resource->type_id == "2"){
$resource->vid_link = Input::get('link');
}
//UPLOADING
//If type is doc...3
if($resource->type_id == "3"){
if(Input::hasFile('file')){
$destinationPath = '';
$filename = '';
$file = Input::file('file');
$basename = Str::random(12);
$extension = $file->getClientOriginalExtension();
$destinationPath = public_path().'/file/';
$filename = Str::slug($basename, '_').".".$extension;//Create the filename
$file->move($destinationPath, $filename);
$resource->doc_link = $filename;
}
}
//if type is img...4
if($resource->type_id == "4"){
if(Input::hasFile('file')){
$destinationPath = '';
$filename = '';
$file = Input::file('file');
$basename = Str::random(12);
$extension = $file->getClientOriginalExtension();
$destinationPath = public_path().'/img/uploads/';
$filename = Str::slug($basename, '_').".".$extension;//Create the filename
$file->move($destinationPath, $filename);
$resource->img_link = $filename;
}
}
//TAGS
//Get the tags
$tags = Array();
$tags = explode(',', Input::get('tags'));
foreach($tags as $tag){
//Create a new Tag in DB - TO DO: Only Unique TAGS
$newTag = new Tag;
$newTag->name = $tag;
$newTag->save();
//Enter to resource tags
}
//Entry to resouce_tags
//Save Object
$resource->save();
return Redirect::action('User_BaseController#getSharedResources')->with('success', 'Resouce Created!');
//Any errors return to Form...
}
}
MODELS
class SharedResource extends Eloquent{
//set up many to many
public function tags(){
return $this->belongsToMany('Tag');
}
and
class Tag extends Eloquent{
//set up many to many
public function sharedResources(){
return $this->belongsToMany('SharedResource');
}
I know that there is lots missing in terms of validation and error handling, but I'm just trying to get the flow working and I can modify it at a later date. I'd appreciate any help.
All you have to do is build or grab the Resource and build or grab the Tags then call saveMany on the resource's tags relationship and pass an array of tag items into it, like this (pseudo-codey example):
$resource = Resource::create(['name' => 'Resource 1']);
$tag = [];
for ($i = 5; $i > 0; $i--) {
$tag = Tag::create(['name' => 'Tag '.$i]);
array_push($tags, $tag);
}
$resource->tags()->saveMany($tags);
The $tags have to be an array of Tag objects, and the saveMany called on the relationship will take care of the pivot table insertions for you. You should end up with a Resource 1 resource in the resources table, five Tags in the tag table, and 5 records in the resource_tag table with the relationships saved.
Can you add the code for both of your models as well? Do you have the relationship defined in them?
For example:
class Resource extends Eloquent {
public function tags()
{
return $this->belongsToMany('tag');
}
}
and
class Tag extends Eloquent {
public function resources()
{
return $this->belongsToMany('resource');
}
}

Laravel Eloquent many-to-many attach

I am new to laravel, and trying to build a photo album with it.
My problem is that i use the attach function to insert the user id and group id to my database, it works okay, but in the documentation it says this about the attach function
For example, perhaps the role you wish to attach to the user already
exists. Just use the attach method:
So i wanted to use it the same way, if the album_id already exist just update it, other wise insert thr new one, but my problem is it always insters, it does not checks if the album_id already exsits
My model
class User extends Eloquent
{
public static $timestamps = false;
public function album()
{
return $this->has_many_and_belongs_to('album', 'users_album');
}
}
Post function
public function post_albums()
{
$user = User::find($this->id);
$album_id = Input::get('album');
$path = 'addons/uploads/albums/'.$this->id.'/'. $album_id . '/';
$folders = array('path' => $path, 'small' => $path. 'small/', 'medium' => $path. 'medium/', );
if (! is_dir($path) )
{
foreach ($folders as $folder)
{
#mkdir($folder, 0, true);
}
}
$sizes = array(
array(50 , 50 , 'crop', $folders['small'], 90 ),
array(164 , 200 , 'crop', $folders['medium'], 90 ),
);
$upload = Multup::open('photos', 'image|max:3000|mimes:jpg,gif,png', $path)
->sizes( $sizes )
->upload();
if($upload)
{
$user->album()->attach($album_id);
return Redirect::back();
}
else
{
// error show message remove folder
}
}
Could please someone point out what im doing wrong? Or i totally misunderstod the attach function?
I believe you have misunderstood the attach function. The sync function uses attach to add relationships but only if the relationship doesn't already exist. Following what was done there, i'd suggest pulling a list of id's then only inserting if it doesn't already exist in the list.
$current = $user->album()->lists( 'album_id' );
if ( !in_array( $album_id, $current ) )
{
$user->album()->attach( $album_id );
}
On a side note I'm going to suggest that you follow the default naming convention from laravel. The relationship method should be $user->albums() because there are many of them. The pivot table should also be named 'album_user'. You will thank yourself later.
Contains method of Laravel Collections
The laravel collections provides a very useful method 'contains'. It determine if a key exists in the collection. You can get the collection in your case using $user->album. You can note the difference that album is without paranthesis.
Working code
Now all you had to do is use the contains method. The full code will be.
if (!$user->album->contains($album_id)
{
$user->album()->attach($album_id);
}
Its more cleaner and 'Laravel' way of getting the required solution.
Thanks #Collin i noticed i misunderstand i made my check yesterday
$album = $user->album()->where_album_id($album_id)->get();
if(empty($album))
{
$user->album()->attach($album_id);
}

Categories