Here is an example of an IIR filter taken from this thread that shows how to use filter (instead of conv) to achieve an approximate zero-phase response (a true zero-phase response for an IIR filter is not numerically computable, in general, because it would be an infinite length response).
Design the filter of interest
bp = designfilt('bandpassiir', 'StopbandFrequency1', 50, 'PassbandFrequency1', 250,...
'PassbandFrequency2', 3600, 'StopbandFrequency2', 3700, 'StopbandAttenuation1', 30,...
'PassbandRipple', 0.1, 'StopbandAttenuation2', 30, 'SampleRate', 8000, 'DesignMethod', 'cheby2');
% apply filtfilt to a random (white) long input signal; output signal shows an undesirable transient
rng(100);
x = randn(1,2^20);
%y = filtfilt(bp,x);
Apply forward/backward filtering w/o padding.
% forward/backward filter w/o padding
y2 = flip(filter(bp,flip(filter(bp,x))));
Apply forward/backward filtering with padding going in both directions. For this example, a pad length of 2x the length of the impulse response seems to work well. A generalized approach would be needed for a general solution
Npad = 2*numel(impz(bp));
y3full = flip(filter(bp,[flip(filter(bp,[x,zeros(1,Npad)])),zeros(1,Npad)]));
The corresponding input sequence and discrete-time vector
x3full = [zeros(1,Npad),x,zeros(1,Npad)];
nfull = -Npad:numel(x)-1+Npad;
Compare the magnitude of the input/output response to the square of the magnitude of the filter frequency response and plot the phase of the input/output response, which should be zero (not expected to be perfect, particularly where the magnitude is small)
[h3,w] = tfestimate(x3full,y3full);
hbp = freqz(bp,w);
figure
plot(subplot(211),w,db(abs(h3)),w,db(abs(hbp).^2)),grid,ylabel('Magnitude (db)')
plot(subplot(212),w,angle(h3)*180/pi),grid
ylim([-1,1]);ylabel('Phase (deg)'),xlabel('\omega (rad/sample)')

Extract the portion of the zero-phase response that corresponds to the original input signal
y3 = y3full((1:numel(x))+Npad);
Compare to the forward/backward output w/o padding, we see a difference at one end (I'm actually surprised there's not a difference at both ends).
e = abs(y2-y3);
figure
plot(e)

figure
plot(e)
xlim([numel(e)-500,numel(e)])

In this example, that difference over the small interval at the end doesn't really make any visible difference in the estimated frequency response based on x and y2 (not shown), probably because the input signal is so long.
What happens with a shorter input?
x = x(1:2^10);
y2 = flip(filter(bp,flip(filter(bp,x))));
y3full = flip(filter(bp,[flip(filter(bp,[x,zeros(1,Npad)])),zeros(1,Npad)]));
x3full = [zeros(1,Npad),x,zeros(1,Npad)];
[h3,w] = tfestimate(x3full,y3full);
hbp = freqz(bp,w);
figure
plot(subplot(211),w,db(abs(h3)),w,db(abs(hbp).^2)),grid,ylabel('Magnitude (db)')
plot(subplot(212),w,angle(h3)*180/pi),grid
ylim([-1,1]);ylabel('Phase (deg)'),xlabel('\omega (rad/sample)')

y3 = y3full((1:numel(x))+Npad);
e = abs(y2-y3);
figure
plot(e)

h2 = tfestimate(x,y2,w);
figure
plot(subplot(211),w,db(abs(h2)),w,db(abs(hbp).^2)),grid,ylabel('Magnitude (db)')
plot(subplot(212),w,angle(h2)*180/pi),grid

Now we see that not padding has a clear effect on the estimated frequency, though to be fair a similar result would be obtained if only considering the elements of y3full that correspond to the original input, x.




