Create relationships in hashtags - laravel

I want to create a hashtags system. Currently I have this code:
private function hashtags($post){
$htag = '#';
$arr = explode(" ", $post->description);
$arrc = count($arr);
$i = 0;
while($i < $arrc){
if(substr($arr[$i], 0, 1) === $htag ){
$hash = Hashtag::where('name', ltrim($arr[$i], '#'))
->where('slug', str_slug(ltrim($arr[$i], '#')))
->first();
if(!$hash){
Hashtag::create([
'name' => ltrim($arr[$i], '#'),
'type' => 1,
'slug' => str_slug(ltrim($arr[$i], '#'))
]);
}
$current_hash = Hashtag::where('type', 1)
->where('name', ltrim($arr[$i], '#'))
->first();
\DB::insert('insert into hashtag_post (hashtag_id, post_id) values (' .$current_hash->id. ', ' .$post->id. ')');
}
$i++;
}
}
This code isn't good for me because I prefer use attach method but if I try use $post->hashtags()->attach([1, 2, 3]); or other array which I created with hashtag's id, it display error:
"Call to undefined method App\Post::hashtags()".
My question is:How I can use attach with this example and how I can improve my code. It doesn't look well.

Firstly, your relationships should be public methods.
Secondly, both relationships should be belongsToMany.
Post class
public function hashtags()
{
return $this->belongsToMany(Hashtag::class);
}
Hashtag class
public function posts()
{
return $this->belongsToMany(Post::class);
}
Just an FYI, Laravel comes with helper methods that can reduce how much you have to write e.g. firstOrCreate(). So, this:
$hash = Hashtag::where('name', ltrim($arr[$i], '#'))
->where('slug', str_slug(ltrim($arr[$i], '#')))
->first();
if(!$hash){
Hashtag::create([
'name' => ltrim($arr[$i], '#'),
'type' => 1,
'slug' => str_slug(ltrim($arr[$i], '#'))
]);
}
can become:
$hash = Hash::firstOrCreate(
['name' => ltrim($arr[$i], '#'), 'slug' => str_slug(ltrim($arr[$i], '#'))],
['type' => 1]
);

Related

Undefinde offset:1 when importing laravel excel

this my code cause the trouble,
$cust = Customer::where('name', '=', $data[$i][0]['customer_name'])
->pluck('customer_id')[0];
this one for get customer id when i do store to sales order
$sales = array(
'customer_id' => Customer::where('name', '=', $data[$i][0]['customer_name'])->pluck('customer_id')[0],
'logistics_id' => Logistic::where('logistics_name', '=', $data[$i][0]['logistics'])->pluck('logistics_id')[0],
'subtotal' => $data[$i][0]['subtotal_rp'],
'shipping_cost' => $data[$i][0]['shipping_cost_rp'],
'discount_code' => 0,
'date_of_sales' => $data[$i][0]['date'],
'grand_total' => $data[$i][0]['grand_total_rp'],
'tax' => $data[$i][0]['tax_rp'],
'status' => $data[$i][0]['status'],
'discount_amount' => $data[$i][0]['discount_amount_rp']
);
$store_so = SalesOrder::create($sales);
but, when i do dd(), i get the right data
First of all, you need to check if the $data variable returns the data as you expect.
dd($data);
Next, you need to check that the $data array has the number of elements according to $total_data.
dd(count($data) == $total_data));
So basically, you just need to give condition or try-catch (recommended) :
if (isset($data[$i][0])) {
$customer = Customer::where('name', $data[$i][0]['customer_name'])->first();
$logistic = Logistic::where('logistics_name', $data[$i][0]['logistics'])->first();
if(!$customer){
dd('No customer found!');
}
if(!$logistic){
dd('No logistic found!');
}
$sales = [
'customer_id' => $customer->customer_id,
'logistics_id' => $logistic->logistics_id,
'subtotal' => $data[$i][0]['subtotal_rp'],
'shipping_cost' => $data[$i][0]['shipping_cost_rp'],
'discount_code' => 0,
'date_of_sales' => $data[$i][0]['date'],
'grand_total' => $data[$i][0]['grand_total_rp'],
'tax' => $data[$i][0]['tax_rp'],
'status' => $data[$i][0]['status'],
'discount_amount' => $data[$i][0]['discount_amount_rp'],
];
$store_so = SalesOrder::create($sales);
}
else{
dd('No $data[$i][0] found!');
}
PS : I recommend using the first() method instead of pluck('customer_id')[0].
It seems you need to get a customer_id from a customer_name.
Try to make everything simple:
$sales = array(
'customer_id' => Customer::where('name', $data[$i][0]['customer_name'])->first()->id,
...
);

How to sort product at laravel by relationship?

I filter and list the products listed with the code samples on my model page below with some data from the user.
I want to sort the listed products according to their prices. However, as it is seen in the minprice-maxprice sample code block, relation depends on several conditions.
From the period consisting of postFrom and postTo dates received by the user, if the daily is 0, it should be listed according to the old_daily price, if the daily is not 0, it should be listed according to the daily price.
How can I do that?
my model page
public $belongsTo = [
'price' => [
'ac\prices\models\Price',
'key' => 'id',
'otherKey' => 'pro_id',
],
]
public static $allowedSortingOptions = array (
'name desc' => 'Name - desc',
'name asc' => 'Name - asc',
'price desc' => 'Price - desc',
'price asc' => 'Price - asc',
);
public function scopeListFrontEnd($query, $options = []){
extract(array_merge([
'page' => 1,
'perPage' => 10,
'sort' => 'created_at desc',
'postFrom' => null,
'postTo' => null,
'minPrice' => null,
'maxPrice' => null,
], $options));
if(!is_array ($sort)){
$sort = [$sort];
}
foreach ($sort as $_sort){
if(in_array($_sort, array_keys(self::$allowedSortingOptions))){
$parts = explode(' ', $_sort);
if(count($parts) < 2){
array_push($parts, 'desc');
}
list($sortField, $sortDirection) = $parts;
$query->orderBy($sortField, $sortDirection);
}
}
if($minPrice != null) {
if(!is_array($minPrice)){
$minPrice = [$minPrice];
}
foreach ($minPrice as $mnPrice){
$query->whereHas('price', function($q) use ($mnPrice,$maxPrice,$postFrom,$postTo){
$q->where('daily', '==', '0')
->where(function( $query ) use ( $mnPrice, $maxPrice ) {
$query->where('old_daily', '>=', $mnPrice);
$query->where('old_daily', '<=', $maxPrice[0]);
});
$q->orWhere('daily', '!=', '0')
->where(function( $query ) use ( $mnPrice, $maxPrice ) {
$query->where('daily', '>=', $mnPrice);
$query->where('daily', '<=', $maxPrice[0]);
});
$q->when($postFrom == '0', function ($sq) {
$sq->where('id', '>', '0');
}, function ($ssq) use ($postFrom, $postTo) {
$ssq->where(function($q) use ($postFrom) {
$q->whereDate('start_date', '<=', $postFrom[0])
->whereDate('end_date', '>=', $postFrom[0]);
})->orWhere(function($q) use ($postTo) {
$q->whereDate('start_date', '<=', $postTo[0])
->whereDate('end_date', '>=', $postTo[0]);
});
});
});
}
}
$lastPage = $query->paginate($perPage, $page)->lastPage();
if($lastPage < $page){
$page = 1;
}
return $query->paginate($perPage, $page);
}
Without trying to decode exactly what you are trying to do here, I would be adding a sub-query select that pulls a sort_price field into the results that you can then orderBy.
$query->selectRaw('CASE WHEN daily = 0 THEN old_daily ELSE daily END as sort_price');
$query->orderByRaw('(SELECT sort_price)');
You can also do this directly in the sort condition as per MYSQL ORDER BY CASE Issue if you don't need this price in your result.
You can do this in the orderByRaw builder method.

Extend Laravel package

I've searched around and couldn't find a definitive answer for this...
I have a package DevDojo Chatter and would like to extend it using my application. I understand I'd have to override the functions so that a composer update doesn't overwrite my changes.
How do I go about doing this?
UPDATE
public function store(Request $request)
{
$request->request->add(['body_content' => strip_tags($request->body)]);
$validator = Validator::make($request->all(), [
'title' => 'required|min:5|max:255',
'body_content' => 'required|min:10',
'chatter_category_id' => 'required',
]);
Event::fire(new ChatterBeforeNewDiscussion($request, $validator));
if (function_exists('chatter_before_new_discussion')) {
chatter_before_new_discussion($request, $validator);
}
if ($validator->fails()) {
return back()->withErrors($validator)->withInput();
}
$user_id = Auth::user()->id;
if (config('chatter.security.limit_time_between_posts')) {
if ($this->notEnoughTimeBetweenDiscussion()) {
$minute_copy = (config('chatter.security.time_between_posts') == 1) ? ' minute' : ' minutes';
$chatter_alert = [
'chatter_alert_type' => 'danger',
'chatter_alert' => 'In order to prevent spam, please allow at least '.config('chatter.security.time_between_posts').$minute_copy.' in between submitting content.',
];
return redirect('/'.config('chatter.routes.home'))->with($chatter_alert)->withInput();
}
}
// *** Let's gaurantee that we always have a generic slug *** //
$slug = str_slug($request->title, '-');
$discussion_exists = Models::discussion()->where('slug', '=', $slug)->first();
$incrementer = 1;
$new_slug = $slug;
while (isset($discussion_exists->id)) {
$new_slug = $slug.'-'.$incrementer;
$discussion_exists = Models::discussion()->where('slug', '=', $new_slug)->first();
$incrementer += 1;
}
if ($slug != $new_slug) {
$slug = $new_slug;
}
$new_discussion = [
'title' => $request->title,
'chatter_category_id' => $request->chatter_category_id,
'user_id' => $user_id,
'slug' => $slug,
'color' => $request->color,
];
$category = Models::category()->find($request->chatter_category_id);
if (!isset($category->slug)) {
$category = Models::category()->first();
}
$discussion = Models::discussion()->create($new_discussion);
$new_post = [
'chatter_discussion_id' => $discussion->id,
'user_id' => $user_id,
'body' => $request->body,
];
if (config('chatter.editor') == 'simplemde'):
$new_post['markdown'] = 1;
endif;
// add the user to automatically be notified when new posts are submitted
$discussion->users()->attach($user_id);
$post = Models::post()->create($new_post);
if ($post->id) {
Event::fire(new ChatterAfterNewDiscussion($request));
if (function_exists('chatter_after_new_discussion')) {
chatter_after_new_discussion($request);
}
if($discussion->status === 1) {
$chatter_alert = [
'chatter_alert_type' => 'success',
'chatter_alert' => 'Successfully created a new '.config('chatter.titles.discussion').'.',
];
return redirect('/'.config('chatter.routes.home').'/'.config('chatter.routes.discussion').'/'.$category->slug.'/'.$slug)->with($chatter_alert);
} else {
$chatter_alert = [
'chatter_alert_type' => 'info',
'chatter_alert' => 'You post has been submitted for approval.',
];
return redirect()->back()->with($chatter_alert);
}
} else {
$chatter_alert = [
'chatter_alert_type' => 'danger',
'chatter_alert' => 'Whoops :( There seems to be a problem creating your '.config('chatter.titles.discussion').'.',
];
return redirect('/'.config('chatter.routes.home').'/'.config('chatter.routes.discussion').'/'.$category->slug.'/'.$slug)->with($chatter_alert);
}
}
There's a store function within the vendor package that i'd like to modify/override. I want to be able to modify some of the function or perhaps part of it if needed. Please someone point me in the right direction.
If you mean modify class implementation in your application you can change the way class is resolved:
app()->bind(PackageClass:class, YourCustomClass::class);
and now you can create this custom class like so:
class YourCustomClass extends PackageClass
{
public function packageClassYouWantToChange()
{
// here you can modify behavior
}
}
I would advise you to read more about binding.
Of course a lot depends on how class is created, if it is created using new operator you might need to change multiple classes but if it's injected it should be enough to change this single class.

Max number of query steps in Laravel

I am having some trouble querying some data in Laravel.
I start my query doing the following:
$query = User::whereRole('advertiser');
When I query for example $usersall = $query->whereHave_pics('1')->get();
Then I also get users that have 0 in have_pics
The $query can consist of a long string of where queries that are dynamic depending on the users choices. Some of these where queries, the users that have 0 in have_pics do qualify for, but when I end the query with whereHave_pics('1'), shouldn't I only get the users that have '1' in Have_pics?
What I am wondering, is, if there is a max number of steps that laravel can handle in the query builder?
For example, if I but whereHave_pics('1') at the beginning of the query, like this:
$query = User::whereRole('advertiser')->whereHave_pics('1');
/* More queries are added */
$usersall = $query->get();
Then it completely ignores the whereHave_pics but not the whereRole...
If I do it at the end of the query, like this:
$query = User::whereRole('advertiser');
/* More queries are added */
$usersall = $query->whereHave_pics('1')->get();
Then it is dependent on the users choices that also creates queries.
I have been trying a ton of different work arounds, like changing the query model, e.g. instead of whereHave_pics('1') I have done where('have_pics', '1') or where('have_pics', true) etc.
I have no idea what to try next.
This is the complete function, that queries the users
public function search_adv(Request $request, $locale = 'dk') {
App::setLocale($locale);
$hair_queries = [
['input' => 'blonde', 'operator' => '=', 'field' => 'haircolor'],
['input' => 'brown', 'operator' => '=', 'field' => 'haircolor'],
['input' => 'red', 'operator' => '=', 'field' => 'haircolor'],
['input' => 'dark', 'operator' => '=', 'field' => 'haircolor'],
];
$eye_queries = [
['input' => 'green', 'operator' => '=', 'field' => 'eyecolor'],
['input' => 'brown', 'operator' => '=', 'field' => 'eyecolor'],
['input' => 'blue', 'operator' => '=', 'field' => 'eyecolor'],
['input' => 'hazel', 'operator' => '=', 'field' => 'eyecolor'],
['input' => 'silver', 'operator' => '=', 'field' => 'eyecolor'],
['input' => 'amber', 'operator' => '=', 'field' => 'eyecolor'],
];
$query = User::whereRole('advertiser');
/* HAIRCOLOR */
$hair = 0;
foreach($hair_queries as $filter) {
if($hair == 0) {
if(!empty($request->input($filter['input']))) {
$query = $query->where(
$filter['field'],
$filter['operator'],
$filter['input']
);
}
}
if(!empty($request->input($filter['input']))) {
$hair++;
}
}
if ($hair >= 2) {
foreach($hair_queries as $filter){
if(!empty(request()->input($filter['input']))){
$query = $query->orWhere(
$filter['field'],
$filter['operator'],
$filter['input']
);
}
}
}
/* END HAIR COLOR */
/* EYECOLOR */
$eye = 0;
foreach($eye_queries as $filter) {
if($eye == 0) {
if(!empty($request->input($filter['input']))) {
$query = $query->where(
$filter['field'],
$filter['operator'],
$filter['input']
);
}
}
if(!empty($request->input($filter['input']))) {
$eye++;
}
}
if ($eye >= 2) {
foreach($eye_queries as $filter){
if(!empty(request()->input($filter['input']))){
$query = $query->orWhere(
$filter['field'],
$filter['operator'],
$filter['input']
);
}
}
}
/* END EYE COLOR */
$usersall = $query->whereHave_pics('1')->get();
return view('search', compact('usersall'));
}
The problem is you need to understand how where chaining and orWhere chaining works in Laravel.
When you say $query->where(..a..)->orWhere(..b..)->where(..c..)->orWhere(..d..) it will evaluate to: (a || (b && c) || d). Where you may have intended ((a || b) && (c || d)) or you may have intended ((a && c) || b || d). This is why when you need advanced where clauses, use where closures and parameter grouping

Laravel 4 - Return the id of the current insert

I have the following query
public static function createConversation( $toUserId )
{
$now = date('Y-m-d H:i:s');
$currentId = Auth::user()->id;
$results = DB::table('pm_conversations')->insert(
array( 'user_one' => $currentId, 'user_two' => $toUserId, 'ip' => Request::getClientIp(), 'time' => $now )
);
return $results;
}
How would i return the id of the row just inserted?
Cheers,
Instead of doing a raw query, why not create a model...
Call it Conversation, or whatever...
And then you can just do....
$result = Conversation::create(array( 'user_one' => $currentId, 'user_two' => $toUserId, 'ip' => Request::getClientIp(), 'time' => $now ))->id;
Which will return an id...
Or if you're using Laravel 4, you can use the insertGetId method...In Laravel 3 its insert_get_id() I believe
$results = DB::table('pm_conversations')->insertGetId(
array( 'user_one' => $currentId, 'user_two' => $toUserId, 'ip' => Request::getClientIp(), 'time' => $now )
);
This method requires that the id of the table be auto-incrementing, so watch out for that...
The last method, is that you can just return the last inserted mysql object....
Like so...
$result = DB::connection('mysql')->pdo->lastInsertId();
So if you choose that last road...
It'll go...
public static function createConversation( $toUserId )
{
$now = date('Y-m-d H:i:s');
$currentId = Auth::user()->id;
$results = DB::table('pm_conversations')->insert(
array( 'user_one' => $currentId, 'user_two' => $toUserId, 'ip' => Request::getClientIp(), 'time' => $now )
);
$theid= DB::connection('mysql')->pdo->lastInsertId();
return $theid;
}
I would personally choose the first method of creating an actual model. That way you can actually have objects of the item in question.
Then instead of creating a model and just save()....you calll YourModel::create() and that will return the id of the latest model creation
You can use DB::getPdo()->lastInsertId().
Using Eloquent you can do:
$new = Conversation();
$new->currentId = $currentId;
$new->toUserId = $toUserId;
$new->ip = Request::getClientIp();
$new->time = $now;
$new->save();
$the_id = $new->id; //the id of created row
The way I made it work was I ran an insert statement, then I returned the inserted row ID (This is from a self-learning project to for invoicing):
WorkOrder::create(array(
'cust_id' => $c_id,
'date' => Input::get('date'),
'invoice' => Input::get('invoice'),
'qty' => Input::get('qty'),
'description' => Input::get('description'),
'unit_price' => Input::get('unit_price'),
'line_total' => Input::get('line_total'),
'notes' => Input::get('notes'),
'total' => Input::get('total')
));
$w_id = WorkOrder::where('cust_id', '=', $c_id)->pluck('w_order_id');
return $w_id;

Resources