I'm learning Laravel and I've created a basic blog. Now, I'm trying to create something similar to an autoblog where posts change status based on either start_date or end_date. So I've created an enum table in my migration with the statuses I need to use. Right now, what I'm trying to do is change the post status to Upcoming if the date and time are greater than today but I'm not having any luck. Initially, I created an event and put the code below in the listener but is working (or not working) in the same way as in the observer. I read that it would be better in the observer if there will be several events.
The flow would be, when the post is created, check the start_date and change the status if the date is greater than today. The code below changes the status to Upcoming if I change it to creating, instead of created but it still doesn't take the start_date into account because it adds it to every post, regardless of the start_date. I tried using an if statement but I kept getting stuck. What am I missing or doing wrong?
Eventually, my goal is for the posts to change the status automatically without any user-initiated action. Perhaps, I could use Laravel queues for that but I haven't got that far yet. For the moment, I'm trying to get past this one.
<?php
namespace App\Observers;
use App\Models\Post;
use Carbon\Carbon;
class PostObserver
{
public function created(Post $post)
{
$post = Post::whereDate('start_date', '>', Carbon::now()->toDateString(){
$post->post_status = 1 // 1 = Upcoming status
});
}
}
Got it working like this, kind of a combination of the two responses, for which I'm thankful:
if (Carbon::parse($post->start_date)->greaterThan(Carbon::now()))
{
$post->post_status = 1;
}
Use method creating
<?php
namespace App\Observers;
use App\Models\Post;
use Carbon\Carbon;
class PostObserver
{
public function creating(Post $post)
{
if ($post->start_date->greaterThan(Carbon::now())) {
$post->post_status = 1;
}
}
}
Creating method will be invoked before post is saved to database. In that point you make check and only in case that start_date is bigger than current timestamp post_status will get value of 1. If you need you can set else block where you give value of 0 to post status in case it is not db default or if there is need for something like that.
Related
This is my first question in this forum so please be patient to me ;)
I'm making a blog using Laravel and
I have a page with a view of all articles inside my database
enter image description here
Last column is "Action" column whet after hit the button you can see single article.
The problem is to show each content (title,subtitle etc.) i must create loooong UrL like this
http://127.0.0.1:8000/article/Test/Test/test/2020-05-08%2016:00:00
Is there any chance to cut URL to be like that:
http://127.0.0.1:800/article/Test
and still have all content?
Files
web.php
Route::get('article/{title_article}/{subtitle_created}/{text_article}/{created_at}','ReadController#index');
Controller
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Article;
class ReadController extends Controller
{
public function index($title_article,$subtitle_article,$text_article,$created_at)
{
return view('article',compact('title_article','subtitle_article','text_article','created_at'))->with('title','Artykuł');
}
}
You should use the primary key (probably an incrementing id) of your database object (App\Article) to identify the object. Laravel has a wonderful function to automatically convert the primary key (id) in the route to an eloquent model.
In your case:
Route::get('article/{article}','ReadController#index');
and
public function index(Article $article) { ... }
I hope this helps you. If you don't understand parts of it, feel free to ask :)
There are many items in the Items table and there is an expired date column in the items table. I just want to get a push notification every day before each items going expire one date before (Expire dates are different to each other and can have one expire date to multuple items). im new to laravel. Please help me.
This can be simply done with Laravel task scheduling
You need to create a custom artisan command like
php artisan make:command SendItemExpiryEmailsToAdmin
Under App\Console\Commands You will find a class SendItemExpiryEmailsToAdmin should be created.
i) First you need to define the signature of the command which will be used to call from the command line.
protected $signature = 'email:send-item-expiry-email-to-admin';
ii) Inside the handle() of the same class, write your logic. A sample logic is given below. You will need to create a Mailable class to send the mail.
public function handle() {
// To fetch all the items ids which are going to expired today.
$itemsIds = Items::whereBetween('expired',
[Carbon::now()->setTime(0,0)->format('Y-m-d H:i:s'),
Carbon::now()->setTime(23,59,59)->format('Y-m-d H:i:s')])
->pluck('id')
->toArray();
$itemsIds = implode(" ", $itemsIds);
Mail::queue(new ItemsExpiryEmail($itemsIds));
// If you are not using queue, just replace `queue` with `send` in above line
}
Mailable to send the mail.
i) Run the following command to create a mailable
php artisan make:mail ItemsExpiryEmail
ii) In the mailable, write your code. A sample code is given below, you can use $this->itemIds in the mail view as it is a public variable.
class ItemsExpiryEmail extends Mailable
{
use Queueable, SerializesModels; // don't forget to import these.
public $itemIds;
public function __construct($itemIds)
{
$this->itemIds = $itemIds;
}
public function build()
{
return $this->view('emails.orders.shipped');
return $this->to('test#example.com', 'Admin')
->subject('Subject of the mail')
->view('emails.adminNotification'); // adminNotification will be the view to be sent out as email body
}
}
This command needs to be executed daily using the Cornjob.
Try this, I'm sure this will help. Let me know if you have any questions.
You can create Task scheduler in Laravel. you can get more info from it's doc here: https://laravel.com/docs/5.8/scheduling
1) you get create login in the scheduling code like. get the all the items which is expiring tomorrow, And send the detail of items to the admin email.
if you have some knowledge in user define artisan command you can also implement scheduling-artisan-commands https://laravel.com/docs/5.8/scheduling#scheduling-artisan-commands.
I have a Model Correo with a custom connection that changes dinamically.
The problem is that when I want to retrieve results from the database like this: Correo::on(session('conexion'))->get(), session('conexion') has the connection name, the following error appears:
Call to a member function newCollection() on null
I can get the results using this: DB::connection(session('conexion'))->table('correos')->get(), but I need the Model's methods and the previous one just returns a generic Collection.
Thanks!
You can use setConnection function
$correo = new Correo;
$correo->setConnection('yourConnectionName');
$data = $correo->find(1);
dd($data);
So based on the session ( if you don't have that many remote connections )
if (session('xyz')) {
$correo->setConnection('xyz');
} else {
$correo->setConnection('pqr');
}
`
Well, I solved it, when I created the model I wrote every property and then created every getter and setter, apparently it didn't like the new setConnection setter. I don't know why, but it stopped me from using it.
I'd like to log the user's name along with the error that is outputted to the log. How do I add a variable to the beginning of an error log entry that outputs an exception?
I think I've got a fairly easy way to do this.
Solution 1
Create a new folder under app called handlers and create a new class called CustomStreamHandler.php which will hold the custom monolog handler.
namespace App\Handlers;
use Monolog\Handler\StreamHandler;
use Auth;
class CustomStreamHandler extends StreamHandler
{
protected function write(array $record)
{
$record['context']['user'] = Auth::check() ? Auth::user()->name : 'guest';
parent::write($record);
}
}
Make sure you set the namespace if you changed it from App and also modify the line where it's setting the user in the context so it works with your users table.
Now we need to drop the current StreamHandler from monolog. Laravel sets this up by default and as far as I can see, there isn't a good way to stop Laravel from doing this.
in app/Providers/AppServiceProvider, we should modify the boot() function to do remove the handler and insert the new one. Add the following...
// Get the underlying instance of monolog
$monolog = \Log::getMonolog();
// Instantiate a new handler.
$customStreamHandler = new \App\Handlers\CustomStreamHandler(storage_path('logs/laravel.log'));
// Set the handlers on monolog. Note this would remove all existing handlers.
$monolog->setHandlers([$customStreamHandler]);
Solution 2
This is a much easier solution but also not exactly what you are looking for (but it might still work for you).
Add the following to AppServiceProvider.php boot().
Log::listen(function()
{
Log::debug('Additional info', ['user' => Auth::check() ? Auth::user()->name : 'guest']);
});
This will simply listen for any logging and also log a debug line containing user information.
I have a function inside of a Helper in Magento that returns whether or not a customer attribute equals one.
Here is my Helper class
class Nie_Nie_Helper_Data extends Mage_Core_Helper_Abstract {
public function isNieAdmin() {
if(Mage::getSingleton('customer/session')->getCustomer()->getNieAdmin() == 1) {
return true;
} else {
return false;
}
}
}
Now when I call this function from a class that extends Mage_Core_Block_Template, everything seems to work fine. However when I try to use this inside one of my controllers, it does not work. In fact when I do Mage::getSingleton('customer/session')->getCustomer()->debug() the only variable that is returned is the website_id.
Does anyone know what I have to do in order to get this to work?
At the time of the controller the session objects are not yet initialised (although the session variable must be) so it returns a blank model. My guess is the website_id is deliberately set in the creation of a customer object to act as a default.
You could access $_SESSION['customer'] directly to find what you need, but that is messy. An alternative would be to do what you want in an event that occurs later.
I hope someone can come up with a better answer than mine.
Ok it looks like I had to load up the session myself. I had to put the following in my functions:
Mage::getSingleton('core/session', array('name' => 'frontend'));
Hope this helps.